# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import json
from django.shortcuts import render

from utils.views import *
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.db import connection
from django.utils import timezone
from django.apps import apps
# Create your views here.
from django.contrib.auth.decorators import login_required
import datetime
from django.utils import timezone
from django.utils.timezone import now
from django.utils.safestring import SafeString
from django.utils.translation import gettext_lazy as _
from calendar import monthrange
from django.conf import settings
import os
from pure_pagination import Paginator
from .models import *
from product.models import Product
from company.models import Company,ChangeLog
from company.views import brands_agent_level_update,sale_task_agent_update
from django.apps import apps
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
import requests
#import pandas as pd 
from sales.models import *
from .forms import *
from django.forms import modelformset_factory 

#2020-09-14
from decimal import *
from dateutil.relativedelta import relativedelta

import redis
#import pickle
import uuid
from listobj.views import get_obj_info


import urllib.parse
#from def app_get_obj_info(request):


from django.db.utils import IntegrityError
import calendar
#from datacenter.common import query_json



sK = 'fgfdvgu$#&3t@j'



WULIU_STR = 'DRIVER={SQL Server};SERVER=127.0.0.1\TJSQL14;DATABASE=jiugui_local;UID=jk;PWD=tianjian2019'
#2022-06-18 需要取os系统数据的企业  长宇酒业 19651 对应os 130
os_cids={
    '19651':'130'
}
cn_os=settings.WULIU_STR




#2021-12-20
from taskman import tasks

def test_label_query(request,code,what):    
    u=User.objects.get(id=2)
    if what=='stkdev':
        data=label_stkdev(code,u)
    elif what=='relations':
        data=label_relations(code,u)
    #label_stkdev(code,user,has_price=False)
    #label_relations(code,user)
    return JsonResponse(data)



#2020-10-27 11位解密
def decrypt_11(code):  
    c=''
    if len(code)==11:  
        s=code.lower()[:10]    
        code=s[9]+s[2]+s[1]+s[3:9]+s[0] 
        try:
            c=str(int('0x'+code,16))
        except Exception:
            c=code
    return c


def decrypt_11h(code):    
    if code[0].lower() in ('h','g'):
        return decrypt_11(code[1:])
    return ''





#2020-04-06 酒鬼本地数据(sql server 2012)放在116服务器(sql server 2014)
#def jiugui_local116(box_code):
#    data = {
#        'e':'',
#        'product':'',
#        'boxes': {'pk': '', 'related': []},
#        'bottles': [],
#        'stock_dev':[]
#    }
#    url="http://davis.china315net.com:8118/wuliu/jiugui/local/?code="+box_code
#    r = requests.get(url)
#    if r.status_code == requests.codes.ok:
#        data=r.json()
#    else:
#        data['e']='local data error'
#    return data


















#2021-07-03
class LabelQueryOld():
    def __init__(self,company_id,code,conn=None):
        if not conn:
            conn=connection
        self.code=code    
        self.tb_cross=''    #卷标跨段表名
        self.company_id=int(company_id)
        self.connection=conn 
        self.package={}        
        self.infor={
            'code':code,                #查询的106301364235
            'label_a':'',               #A标号码
            'label_b':'',               #B标号码
            'label_pk_id':0,            #主箱标ID

            #2022-02-23
            'label_id':0,               #标签ID

            'label_pk_code':'',         #主箱标号码
            'ab_bindding':False,        #是否为AB标 
            'has_nfc':False,            #是否有NFC标签
            'is_thirdparty':False,      #是否为第三方标签
            'ab_data':1,                #AB标基础数据表 0:单枚标 无基础数据 1:code_a 2:code_b
            'is_active':False,          #标签是否已激活（系统内是否有物流记录）
            'is_bottlecap':False,       #是否为瓶盖码
            'bottlecap':'',             #瓶盖码
            'wl':'',                    #系统内物流编码

            #2022-04-25 后补主箱标IDS 
            #如诗仙太白：159箱，箱-箱（跨段）绑定，1托3 +1托6 =9瓶/箱
            'sup_pk_id':{}
        } 
        #取主箱标ID，包装，是否已激活          
        self.infor['label_pk_id']=self.get_label_pk()     
        
    def get_label_pk(self):
        label_pk_id=None
        company_id=self.company_id
        company=Company.objects.get(id=int(company_id))
        code=self.code    
        cur=self.connection.cursor()

        sPkg='package_id'   #一般情况下，标签类别取标签基础表的 package_id 字段
        #2021-05-06 瓶盖码
        if not code.isdigit():  
            #2022-03-14 酒鬼小圆标也有替换
            s="select code0,code from label.lbl_replace_details "+\
                "where code='"+code+"' order by id desc limit 1"
            cur.execute(s)
            r=cur.fetchone()
            if r:
                code=r[0]
            #2022-03-14

            d_code=decrypt_11h(code)
            if not d_code:               
                return None
            else:
                self.infor['is_bottlecap']=True
                self.infor['bottlecap']=code
                self.infor['code']=d_code
                sPkg='100 package_id'  #瓶盖码标签类别id为100

                #cur.execute("select bottle from label.bottlecap where label='"+code+"'")
                #2022-02-17
                cur.execute("select bottle from label.bottlecap where  label='"+code+"' "+\
                    " union all "+\
                    "select bottle from z_bottlecap_binding where  label='"+code+"' "
                )

                r=cur.fetchone()
                if r:
                    code=r[0]                    
                else:
                    #2021-09-13 是否为小圆标活动码
                    code=d_code  

                #2021-11-29
                self.code=code   
        #2022-04-27 可能查询的是瓶盖码解密后的数据
        else:             
            cur.execute("select bottle from label.bottlecap where code='"+code+"' "+\
                " union all "+\
                "select bottle from z_bottlecap_binding where code='"+code+"' "
            )
            r=cur.fetchone()
            if r:
                self.infor['code']=code
                self.infor['bottlecap']=code
                code=r[0]   
                sPkg='100 package_id'  #瓶盖码标签类别id为100 


        if company.ancestor_id in (1,1644) and code[:1]=='4':
            r = requests.request('GET', 'http://www.china315net.com:35088/jg/fw_wl/'+code+'/')
            d = json.loads(r.text) 
            if d['wl']:
                code=d['wl']   
                self.infor['wl']=code
                
            else:       
                #cur.close()
                #return None 2022-03-15 酒鬼有4开头的物流码 如早期 54°500ml简优  
                pass
        #查BA表
        cur.execute("select coalesce(code_a,''),coalesce(code_b,''),id FROM label.lbl_abcode "+\
            "where code_a='"+code+"' or code_b='"+code+"'")
        r=cur.fetchone()
        if r:            
            code=r[0] 
            self.infor['ab_bindding']=True
            self.infor['label_a']=r[0]
            self.infor['label_b']=r[1]
            #2021-07-14 默认查找 code_a 数据表
            self.code=code


            #2022-04-25 诗仙太白 code_a,跨段 箱-箱 159箱
            if r[1][:4]=='1045' or r[0][:4]=='1045':
                s="select code from label.t1045 where package_id=3 and left(code,4)='1044' and parent_id="+\
                    "(select id from label.t1045 where code='"+code+"')"  
                cur.execute(s)
                rrr=cur.fetchone()
                if rrr:     
                    s="select id from label.t9073 where code="+\
                        "(select code_a from label.lbl_abcode where code_b='"+rrr[0]+"')"                    
                    cur.execute(s)
                    rrr=cur.fetchone()
                    if rrr:
                        self.infor['sup_pk_id']={'id':rrr[0],'tb':'label.t9073'} 


            #2021-09-18 已确保标签替换明细里，AB标的替换，新标和旧标都是A标
            s="select code0,code,dt from label.lbl_replace_details where code='"+r[0]+"' order by id desc limit 1"  
        else:
            # 标签是否有被替换的情况
            s="select code0,code,dt from label.lbl_replace_details where code='" + code +"' order by id desc limit 1"    
        cur.execute(s)   
        rr=cur.fetchone()    
        if rr:
            code=rr[0]   

        if not self.infor['wl']:    
            self.infor['wl']=code
        t="label.t" +code[:4]
        #2020-07-27 是否跨段动态绑定
        cur.execute("select tbname from label.lbl_tbcross where segment='"+code[:4]+"'")
        rrr=cur.fetchone()     
        if rrr:
            #2022-05-09 有些样标，号段也在跨段表范围内，实则为AB标
            if not self.infor['ab_bindding']:
                t='label.'+rrr[0] 
                self.tb_cross=t
        
        #2021-11-27是否为第三方标签
        #cur.execute("select id,code from label.thirdparty where cid="+str(company_id)+" and (code='"+code+"' or fw_code='"+code+"')")
        #rrr=cur.fetchone()
        #if rrr:
        #    t='label.thirdparty'
        #    self.infor['is_thirdparty']=True
        #    code=rrr[1]


        try:            
            s="select p.id,p.name,coalesce(p.remark,''),p.outermost,p.innermost,p.binding,"+\
                "coalesce((select parent_id from " +t+ " where id=l.parent_id),l.parent_id,l.id),"+\
                "l.id from "+\
                "(select id,"+sPkg+",parent_id from "+t+" where code='"+code+"') l "+\
                "left outer join "+\
                "(SELECT id,name,remark,outermost,innermost,binding FROM label.lbl_package) p "+\
                "on l.package_id=p.id"     
            cur.execute(s)   
            r = cur.fetchone()
            if not r: 
                cur.close()
                return None
        except Exception as e:  
            #2021-09-18
            if self.infor['ab_bindding']:
                #基础数据是否在code_b
                cur.execute("select count(*) from information_schema.tables where table_schema='label' and "+\
                    "table_type='BASE TABLE' and table_name='t"+self.infor['label_b'][:4]+"'")
                rr=cur.fetchone()     
                if rrr[0]:
                    t='label.t'+self.infor['label_b'][:4]
                    code=self.infor['label_b']
                    s="select p.id,p.name,coalesce(p.remark,''),p.outermost,p.innermost,p.binding,"+\
                        "coalesce((select parent_id from " +t+ " where id=l.parent_id),l.parent_id,l.id),"+\
                        "l.id from "+\
                        "(select id,"+sPkg+",parent_id from "+t+" where code='"+code+"') l "+\
                        "left outer join "+\
                        "(SELECT id,name,remark,outermost,innermost,binding FROM label.lbl_package) p "+\
                        "on l.package_id=p.id"     
                    cur.execute(s)   
                    r = cur.fetchone()                    
                    if not r:
                        #AB标有单枚标,只在BA表内写入映射，没有基础数据表  
                        cur.close()
                        return None     
                
            else:
                # 2022-06-12是否为第三方标签
                cur.execute("select id,code from label.thirdparty where cid=" + str(
                    company_id) + " and (code='" + code + "' or fw_code='" + code + "')")
                rrr = cur.fetchone()
                if rrr:
                    t = 'label.thirdparty'
                    self.infor['is_thirdparty'] = True
                    code = rrr[1]
                    s = "select p.id,p.name,coalesce(p.remark,''),p.outermost,p.innermost,p.binding," + \
                        "coalesce((select parent_id from " + t + " where id=l.parent_id),l.parent_id,l.id)," + \
                        "l.id from " + \
                        "(select id," + sPkg + ",parent_id from " + t + " where code='" + code + "') l " + \
                        "left outer join " + \
                        "(SELECT id,name,remark,outermost,innermost,binding FROM label.lbl_package) p " + \
                        "on l.package_id=p.id"
                    cur.execute(s)
                    r = cur.fetchone()
                else:
                    cur.close()
                    return None

        if r[6]:
            label_pk_id=r[6]    
            #2022-02-23
            self.infor['label_id']=r[7]            
        else:
            return None    

        self.package={'id':r[0],'name':r[1],'remark':r[2],'outermost':r[3],'innermost':r[4],'is_biding':r[5]}  
        
        cur.execute("select code from "+t+" where id="+str(label_pk_id))
        r=cur.fetchone()
        #self.infor['label_pk_code']=r[0]
        
        #2022-05-20 小型企业，套标再绑定，箱瓶可能不在一个表
        if r:
            self.infor['label_pk_code']=r[0]
        else:
            s="select parent_id,parent_code,parent_tb "+\
                "from  label.lbl_rebinding_details where code='"+code+"'"
            cur.execute(s)
            rr=cur.fetchone()
            if rr:
                label_pk_id=rr[0]
                self.infor['label_pk_code']=rr[1]
                self.tb_cross=rr[2]

        cur.execute("select id from inventory_stkdetails where label_pk_id="+str(label_pk_id)+" limit 1")
        r=cur.fetchone()
        if r:
            self.infor['is_active']=True        
        cur.close()        
        return label_pk_id     


    #获取套标关系，目前只考虑箱carton，盒box，瓶bottle 三级对应关系
    #2022-05-20 AB标，跟亮亮确认，肉眼看到的是B标，套标关系一律显示B标
    def get_relations(self):
        data={'level':0}
        pk=self.infor['label_pk_id']
        if not pk:
            return data
        pk=str(pk)    
        #c=self.code    
        #2021-12-02
        c=self.infor['wl']
        cur=self.connection.cursor()     

        #2021-12-03
        if self.tb_cross:
            t=self.tb_cross    
        elif self.infor['is_thirdparty']: 
            t="label.thirdparty"
        else:
            t="label.t" +c[:4]    
        
        sA="coalesce((select code_a from label.lbl_abcode where code_a=l.code or code_b=l.code),'')"
        sB="coalesce((select code_b from label.lbl_abcode where code_a=l.code or code_b=l.code),'')"
        sNFC="coalesce((select nfc from label.lbl_nfc where label_code=l.code order by label_code limit 1),'')" 
        
        s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
            sA+","+sB+","+sNFC+" "+\
            "from "+\
            "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid " +\
                "from "+t+" a where id="+pk+" or (parent_id="+pk+" and package_id=3) order by is_pk desc) l "+\
            "left outer join "+\
            "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
            "on l.rid=r.id"
        cur.execute(s)
        rs1=cur.fetchall()
        cartons=[]  
        children=[]
        #箱标
        for r1 in rs1:
            clr_x=''
            nfc_x=r1[7]
            if c in [ r1[1],r1[2],r1[3],r1[5],r1[6] ]:
                clr_x='red'
            cartons.append({'label':r1[1],'code0':r1[2],'code':r1[3],'dt_replace':r1[4],'bottlecap':{},'code_a':r1[5],'code_b':r1[6],'color':clr_x,'nfc':nfc_x})    

        s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
            sA+","+sB+","+sNFC+" "+\
            "from "+\
            "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid " +\
                "from "+t+" a where parent_id="+pk+" and package_id=2"+\
            ") l "+\
            "left outer join "+\
            "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
            "on l.rid=r.id"
        cur.execute(s)
        rs2=cur.fetchall()
        if rs2:            
            data['level']=3     
            #盒标
            for r2 in rs2:
                clr_h=''
                nfc_h=r2[7]
                if c in [ r2[1],r2[2],r2[3],r2[5],r2[6] ] :
                    clr_h='red'
                bottles=[]                  
                processed=False                
                s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from label.bottlecap where bottle in (r.code0,r.code,l.code) order by dt limit 1),''),"+\
                    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from logistics.z_bottlecap_binding where bottle in (r.code0,r.code,l.code) order by id desc limit 1),''),"+\
                    sA+","+sB+","+sNFC+" "+\
                    "from "+\
                    "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid " +\
                        "from "+t+" a where parent_id="+str(r2[0])+" and package_id=1"+\
                    ") l "+\
                    "left outer join "+\
                    "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                    "on l.rid=r.id"
                cur.execute(s)
                rs3=cur.fetchall()
                #瓶标
                for r3 in rs3:                    
                    clr_p=''
                    cap={'code':''}
                    nfc_p=r3[9]
                    if c in [ r3[1],r3[2],r3[7],r3[8] ]:
                        clr_p='red'                    
                    if r3[5]:                        
                        cap={'complete':True,'code':r3[5]}
                    elif r3[6]:
                        cap={'complete':False,'code':r3[6]}                                          
                    bottles.append({'label':r3[1],'code0':r3[2],'code':r3[3],'dt_replace':r3[4],'bottlecap':cap,'code_a':r3[7],'code_b':r3[8],'color':clr_p,'nfc':nfc_p})                
                children.append({'label':r2[1],'code0':r2[2],'code':r2[3],'dt_replace':r2[4],'bottlecap':{},'code_a':r2[5],'code_b':r2[6],'children':bottles,'color':clr_h,'nfc':nfc_h})
        else:
            data['level']=2

            #2021-11-29 第三方防伪码，目前只考虑二级对应
            data['level']=2
            sFw="'' fw_code"
            if self.infor['is_thirdparty']: 
                sFw="coalesce(fw_code,'') fw_code"
            
            #s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
            #    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from label.bottlecap where bottle in (r.code0,r.code,l.code) order by dt limit 1),''),"+\
            #    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from logistics.z_bottlecap_binding where bottle in (r.code0,r.code,l.code) order by id desc limit 1),''),"+\
            #    sA+","+sB+","+sNFC+","+sFw+" "+\
            #    "from "+\
            #    "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid,"+sFw+" "+\
            #        "from "+t+" a where parent_id="+pk+" and package_id=1"+\
            #    ") l "+\
            #    "left outer join "+\
            #    "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
            #    "on l.rid=r.id"



            #2022-05-20
            s="select l.id,coalesce((select code_b from label.lbl_abcode where code_a=l.code or code_b=l.code),l.code),"+\
                "coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from label.bottlecap where bottle in (r.code0,r.code,l.code) order by dt limit 1),''),"+\
                "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from logistics.z_bottlecap_binding where bottle in (r.code0,r.code,l.code) order by id desc limit 1),''),"+\
                sA+","+sB+","+sNFC+","+sFw+" "+\
                "from "+\
                "(select max(id) id,code,rid,"+sFw+" from "+\
                    "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid,"+sFw+" "+\
                        "from "+t+" a where parent_id="+pk+" and package_id=1 "+\
                    "union all "+\
                    "select parent_id id,code,null rid,"+sFw+" from label.lbl_rebinding_details "+\
                        "where parent_id="+pk+\
                    ") u "+\
                    "group by code,fw_code,rid "+\
                ") l "+\
                "left outer join "+\
                "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                "on l.rid=r.id "+\
                "order by l.code"               

            cur.execute(s)
            rs3=cur.fetchall()            

            for r3 in rs3:
                cap={'code':''}               
                if r3[5]:
                    cap={'complete':True,'code':r3[5]}
                elif r3[6]:
                    cap={'complete':False,'code':r3[6]}  
                clr_p=''                
                if r3[1]==c:
                    clr_p='red'   
                children.append({'label':r3[1],'code0':r3[2],'code':r3[3],'dt_replace':r3[4],'bottlecap':cap,'code_a':r3[7],'code_b':r3[8],'is_bottlecap':False,'fw':r3[10],'color':clr_p,'nfc':r3[9] })   
            
            

            #2022-04-25 诗仙太白 code_a,跨段 箱-箱 159箱
            if self.infor['sup_pk_id']:
                clr=''
                s="select code,"+sA+","+sB+","+sNFC+" "+\
                    "from "+self.infor['sup_pk_id']['tb']+" l where parent_id="+str(self.infor['sup_pk_id']['id'])   
                cur.execute(s)
                for r3 in cur.fetchall():
                    if r3[0]==c:
                        cls='red'
                    cap={'complete':False,'code':''}
                    children.append({'label':r3[0],'code0':'','code':'','dt_replace':'','bottlecap':cap,'code_a':r3[1],'code_b':r3[2],'is_bottlecap':False,'fw':'','color':clr,'nfc':r3[3] })
                #删除159箱 箱-箱 绑定关系里后补关联箱
                #cartons.append({'label':r1[1],'code0':r1[2],'code':r1[3],'dt_replace':r1[4],'bottlecap':r1[5],'code_a':r1[1],'code_b':r1[6]})  
                i=0
                for ct in cartons:                    
                    if ct['label'][:4]=='1044':
                        cartons.pop(i)
                    i=i+1              
            
            #2021-05-03 酒鬼酷客白在线绑定,把米多瓶盖码做为瓶标显示
            if not children:  
                cur.execute("select bottle from label.bottlecap where label_pk_id="+pk)
                rs4=cur.fetchall()                
                if rs4:
                    cap={'complete':True,'code':''}
                    for r4 in rs4:
                        clr=''
                        if r4[0]==c:
                            clr='red'
                        children.append({'label':r4[0],'code0':'','code':'','dt_replace':'','bottlecap':cap,'code_a':'','code_b':'','is_bottlecap':True,'color':clr,'nfc':''})
                else:
                    cur.execute("select bottle from logistics.z_bottlecap_binding where label_pk_id="+pk)
                    rs4=cur.fetchall()  
                    cap={'complete':False,'code':''}
                    for r4 in rs4:
                        clr=''
                        if r4[0]==c:
                            clr='red'
                        children.append({'label':r4[0],'code0':'','code':'','dt_replace':'','bottlecap':cap,'code_a':'','code_b':'','is_bottlecap':True,'color':clr,'nfc':''})

        cur.close()
        data['cartons']=cartons
        data['children']=children        
        return data

    def get_product(self):
        data={'name':'未知','price':'未知','property':[],'id':0,'external_code':'','inbound_date':'','inbound_lot':'','inbound_aging':'','inbound_vendor':'','outbound_aging':''}
        pk=self.infor['label_pk_id']
        if not pk:
            return data
        pk=str(pk)
        cur=self.connection.cursor()
        cur.execute("select ancestor_id from company_company where id="+str(self.company_id))
        r=cur.fetchone()
        aid=str(r[0])

        s="select s.product_id,s.tm,p.name,coalesce(to_char(p.price,'99999.09'),'未知'),p.contents,p.external_code from "+\
            "(select product_id,tm from "+\
                "(select product_id,tm from inventory_stkdetails where company_id="+aid+" "+\
                        "and label_pk_id="+pk+" and vtype_id=1 and is_delete=false "+\
                    "union all "+\
                    "select product_id,tm from inventory_stkdetails where company_id="+aid+" "+\
                        "and label_pk_id="+pk+" and  vtype_id=2 "+\
                    "order by tm limit 1"+\
                ") a "+\
            ") s "+\
            "left outer join "+\
            "(select id,name,price,coalesce(contents,'') contents,external_code from product_product) p "+\
            "on s.product_id=p.id"
        
        #2022-02-17
        
        s="select s.product_id,p.name,coalesce(to_char(p.price,'99999.09'),'未知'),p.contents,p.external_code from "+\
            "(select coalesce("+\
                    "(select product_id from inventory_stkdetails where company_id="+aid+" "+\
                        "and label_pk_id="+pk+" and vtype_id=1 and is_delete=false order by id limit 1),"+\
                    "(select product_id from inventory_stkdetails where company_id="+aid+" "+\
                        "and label_pk_id="+pk+" and  vtype_id=2 order by id limit 1), "+\
                    "(select product_id from z_bottle_cap_product where id="+\
                        "(select coalesce((select product_id from label.bottlecap where label_pk_id="+pk+" limit 1),"+\
                            "(select product_id from z_bottlecap_binding where label_pk_id="+pk+" limit 1))) "+\
                    ")"+\
                ") product_id "+\
            ") s "+\
            "left outer join "+\
            "(select id,name,price,coalesce(contents,'') contents,external_code from product_product) p "+\
            "on s.product_id=p.id  where s.product_id>0"
        
        
        cur.execute(s)
        r=cur.fetchone()
        if r:      
            data['name']=r[1]
            data['price']=r[2].strip()
            data['id']=r[0]
            data['external_code']=r[4]
            s="select coalesce(c.value,'') val,g.name,g.desc_cn,coalesce(g.unit,'') from "+\
                "(SELECT * FROM product_prdprops where product_id="+str(r[0])+") p "+\
                "left outer join "+\
                "(SELECT * FROM product_productprop where company_id="+aid+") c "+\
                "on p.prd_property_id=c.id "+\
                "left outer join "+\
                "(select * from company_categoryprop) g "+\
                "on c.categoryprop_id=g.id"
            cur.execute(s)
            for rr in cur.fetchall():
                data['property'].append({'desc_cn':rr[2],'unit':rr[3],'value':rr[0]})                
            #2021-08-05 颂恩在产品表添加contents字段，用于存放当前产品的多张图片
            contents=''
            if r[3]:
                if r[4]:
                    contents=urllib.parse.quote(r[4])
            data['contents']=contents
            
            #2022-04-18 取生产批次,采摘日期（入库）,入库日期，供应商           
            s="select coalesce(b.code,b.batch_no),coalesce(b.product_aging,''),"+\
                "coalesce((select name from mes_vendor where id=vendor_id),''),to_char(b.dt,'yyyy-mm-dd') "+\
                "from "+\
                "(select batch_id from inventory_stkdetails where company_id="+aid+" and vtype_id=1 "+\
                    "and is_delete=false and label_pk_id="+pk+" order by id limit 1) d "+\
                "left outer join "+\
                "(select id,code,batch_no,product_aging,vendor_id,dt from inventory_batch where company_id="+aid+" and vtype_id=1) b "+\
                "on d.batch_id=b.id"
            cur.execute(s)
            rr=cur.fetchone()
            if rr:
                data['inbound_lot']=rr[0]
                data['inbound_aging']=rr[1]
                data['inbound_vendor']=rr[2]
                data['inbound_date']=rr[3]
            #产品年份（内参销售出库）
            s="select coalesce(b.product_aging,'')    from "+\
                "(select batch_id from inventory_stkdetails where company_id="+aid+" and vtype_id=2 "+\
                    "and is_delete=false and label_pk_id="+pk+" order by id desc limit 1) d "+\
                "left outer join "+\
                "(select id,code,batch_no,product_aging from inventory_batch where company_id="+aid+" and vtype_id=2) b "+\
                "on d.batch_id=b.id"
            cur.execute(s)
            rr=cur.fetchone()
            if rr:
                data['outbound_aging']=rr[0]       

        cur.close()            
        return data

    #2022-04-18 返回防伪查询信息
    def get_security_info(self):
        aid=str(self.company_id)
        data={"times":0,"image":""}        
        url_internal='http://www.china315net.com:35088/get/codes/from/wuliu/'+aid+'/'
        sK_internal='$internal&GLker5w3jtQLx#'
        #根据物流码取防伪码        
        wl_code=self.infor['wl']
        t = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        m2 = hashlib.md5((sK_internal + t).encode('utf8'))
        key = m2.hexdigest()
        d=[{'id':1,'label':wl_code}]
        r=requests.post(url_internal + '/fw/', json={'key': key, 'time': t, 'labels': d}) 
        if r.status_code==200:
            d = json.loads(r.text)
            fw_code=d['data'][0]['code']        
            url='http://www.china315net.com:35207/tjfw/get/'
            guid=str(uuid.uuid1())
            param={
                'fwcode':fw_code,   #防伪码
                'record':1,         #需要写入查询记录
                'uid':'hand_'+guid,       #用户名，上海汉得
                #'pid':,             #产品ID
                #'cid':1,            #酒鬼酒
                #'package':          #包装
            }
            r=requests.get(url,param) 
            #{
            # "err":错误信息,
            # "img":Base64,
            # "counter":{
            #   "tel":电话查询次数,
            #   "sms":短信查询次数,
            #   "net":网络查询次数
            #  },
            #  "am":暗码,
            #  "wz":文字,
            #  "company":公司名称,
            #  "product":产品名称,
            #  "QueryResult":查询结果,
            #  "CodeState":0出错,1正常,
            #  "history":[前10条查询记录]
            #}
            if r.status_code==200:
                d=json.loads(r.text)
                cnt=d['counter']['net']
                img=d['img']
                data={'times':cnt,'image':img}
        return data



    def get_replaced_labels(self):
        b=[]
        pk=self.infor['label_pk_id']
        if not pk:
            return b
        pk=str(pk)
        c=self.infor['label_pk_code']
        if self.tb_cross:
            tb=self.tb_cross
        elif self.infor['is_thirdparty']:
            tb="label.thirdparty"
        else:
            tb="label.t"+c[:4]

        s="select code from label.lbl_replace_details where code0 in "+\
            "(select code from "+tb+" where id="+pk+" or parent_id="+pk+") "+\
            "group by code"
        cur=self.connection.cursor()
        cur.execute(s)
        for r in cur.fetchall():
            b.append(r[0])
        cur.close()
        return b
    

    def get_stk_dev(self):
        data=[]
        pk=self.infor['label_pk_id']
        if not pk:
            return data
        pk=str(pk)
        cur=cur=self.connection.cursor()
        cur.execute("select ancestor_id from company_company where id="+str(self.company_id))
        r=cur.fetchone()
        aid=str(r[0])

        if str(self.company_id)==aid:
            sAid=" and ancestor_id="+aid
            if aid=='1':
                sAid=" and ancestor_id in (1,1644)"
        else:
            #经销商可查自己和下级物流
            #sAid=" and company_id="+str(self.company_id)+" or (select parent_id from company_company where id=company_id)="+str(self.company_id)   
            sAid=" and (company_id="+str(self.company_id)+" or  parent_id="+str(self.company_id)+")" 
        
        replaced_labels=self.get_replaced_labels()
        sRep=''
        if replaced_labels:
            sRep=" or label_code in ('"+"','".join(replaced_labels)+"')"
        s="select "+\
            "coalesce((select code_b from label.lbl_abcode where code_a=s.label_code or code_b=s.label_code limit 1),s.label_code),"+\
            "b.code,to_char(s.tm,'yyyy-MM-dd HH24:MI:ss'),"+\
            "(select name from inventory_voucher where id=s.vtype_id),"+\
            "(select name from product_product where id=s.product_id),"+\
            "(select username from company_user where id=b.user_id),"+\
            "(select name from company_company where id=s.company_id),"+\
            "coalesce(c.name,''),"+\
            "coalesce((select name from inventory_storehouse where id=s.store_id),''),"+\
            "coalesce((select name from inventory_storehouse where id=s.store_to_id),''),"+\
            "(select name from label.lbl_package where id=s.label_pkg),"+\
            "coalesce((select code_b from label.lbl_abcode where code_a=s.label_code),''),"+\
            "vtype_id,case when is_delete then 1 else 0 end,"+\
            "coalesce(c.external_code,''),b.id,coalesce(c.address,''),"+\
            "coalesce((select name from gis.adm where id=c.province_gis_id),c.province,''),"+\
            "coalesce((select name from gis.adm where id=c.city_gis_id),c.city,''),"+\
            "s.label_pkg "+\
            "from "+\
            "(select label_code,label_pkg,company_id,company_to_id,product_id,"+\
                "store_id,store_to_id,batch_id,tm,vtype_id,is_delete FROM inventory_stkdetails "+\
                "where (label_pk_id="+pk+sRep+")"+sAid+") s "+\
            "left outer join "+\
            "(select id,code,user_id from inventory_batch) b "+\
            "on s.batch_id=b.id "+\
            "left outer join "+\
            "(select id,name,external_code,address,province,province_gis_id,city,city_gis_id "+\
                "from company_company where ancestor_id="+aid+\
            ") c "+\
            "on s.company_to_id=c.id "+\
            "order by s.batch_id "
        cur.execute(s)
        #print(s)
        bOut=False #是否需要查询酒鬼酒本地数据库
        for r in cur.fetchall():
            if r[12]==2:
                bOut=True
            data.append({
                'label_code':r[0],'bill_no':r[1],'tm':r[2],'voucher':r[3],'product':r[4],'user':r[5],'vtype_id':r[12],
                'company':r[6],'customer':r[7],'store':r[8],'store_to':r[9],'label_pkg':r[10],"code_b":r[11],'is_delete':r[13],
                'customer_external_code':r[14],'batch_id':r[15],'label_pkg_id':r[19],
                'agent':{'name':r[7],'external_code':r[14],'address':r[16],'province':r[17],'city':r[18]}
            })
        if not bOut and aid=='1': 
            #dd=jiugui_local116(self.infor['label_pk_code']) 
            #2022-03-15 酒鬼酒本地sql svr数据已转入 pg jiugui_local            
            dd=get_jiugui_local(pk)            
            
            for d in dd['stock_dev']:
                data.append({ 
                    'vtype_id':0,
                    'label_code':d['label_code'],
                    'bill_no':d['voucher_no'],
                    'tm':d['time'],  
                    'voucher':d['voucher_type'],
                    'product':d['product'],                                  
                    'user':'',                    
                    'company':'酒鬼酒股份有限公司',                    
                    'customer':d['to_company'],
                    'store':d['store'],
                    'store_from':'',
                    'label_pkg':d['package'],
                    'label_pkg_id':3,
                    'code_b':'',
                    'is_delete':0,
                    'agent':{'name':'','external_code':'','address':'','province':'','city':''}
                }) 
        cur.close()
        return data























#2022-03-15 酒鬼本地SQLSVR数据转到了 pg jiugui_local下
def get_jiugui_local(label_pk_id):
    data = {
        'e':'',        
        'stock_dev':[]
    }
    cur=connection.cursor()
    s="select vtype_id,"+\
        "coalesce(code,''),"+\
        "coalesce((select tm from jiugui_local.inbound where label_code=s.label_code),tm_inbound),"+\
        "tm_outbound,"+\
        "coalesce((select name from jiugui_local.customer where id=customer_id),''),"+\
        "coalesce((select name from jiugui_local.product where id=product_id),''),"+\
        "coalesce((select name from jiugui_local.storehouse where id=storehouse_id),''),"+\
        "label_code,"+\
        "coalesce((select batch_no from jiugui_local.inbound where label_code=s.label_code),'') "+\
        "from jiugui_local.stk_details s where label_pk_id="+str(label_pk_id)+\
        "order by id desc limit 1"
    cur.execute(s)
    r=cur.fetchone()
    if r:
        if r[0] == 1:
                t = ''
                if r[2]:
                    t = r[2].strftime('%Y-%m-%d %H:%M')
                data['stock_dev'] = [{
                    'label_code': r[7],
                    'voucher_type': '成品入库',
                    'voucher_no': r[8],
                    'time': t,
                    'user': '',
                    'product': r[5],
                    'store': r[6],
                    'store_fr': '',
                    'package': '箱',
                    'to_company': '',
                    'fr_company':'酒鬼酒股份有限公司',
                    'vtype_id':1,
                }]
        elif r[0] == 2:
                t1 = ''
                t2 = ''
                if r[2]:
                    t1 = r[2].strftime('%Y-%m-%d %H:%M')
                if r[3]:
                    t2 = r[3].strftime('%Y-%m-%d %H:%M')
                data['stock_dev'] = [
                    {
                        'label_code': r[7],
                        'voucher_type': '成品入库',
                        'voucher_no': r[8],
                        'time': t1,
                        'user': '',
                        'product': r[5],
                        'store': r[6],
                        'store_fr': '',
                        'package': '箱',
                        'to_company': '',
                        'fr_company':'酒鬼酒股份有限公司',
                        'vtype_id':1,
                    },
                    {
                        'label_code': r[7],
                        'voucher_type': '销售出库',
                        'voucher_no': r[1],
                        'time': t2,
                        'user': '',
                        'product': r[5],
                        'store': r[6],
                        'store_fr': '',
                        'package': '箱',
                        'to_company': r[4],
                        'fr_company':'酒鬼酒股份有限公司 ',
                        'vtype_id':2,
                    }
                ]
    
    cur.close()
    return data





#2022-06-18 查询os平台标签发货记录
def os_label_outbound(cid,box_code):
    data=[]    
    rg = box_code[:4]
    sFlds=s="BoxLabel01,FromAgentID,FromStorehouseID,ToAgentID,UserID,FHDate,FHPici,PID,CompID,FHKey "
    a = []
    cn = pyodbc.connect(cn_os)
    cur = cn.cursor()
    for n in range(4):
        # 表是否存在
        cur.execute("select name from sysobjects where  name='W" + rg + "_0" + str(n) + "'")
        r0 = cur.fetchone()
        if r0:
            s = "select "+sFlds+" from W"+rg+"_0"+str(n)+"_FH where CompID="+cid+" and BoxLabel01 in ("+\
                "isnull((select BoxLabel01 FROM W"+rg+"_0"+str(n)+"_BX where BoxLabel='"+box_code+"'),'"+box_code+"'))"
            a.append(s)
    if a:
        s="select BoxLabel01,CONVERT(varchar,FHDate,120),isnull(FHPici,''),"+\
            "isnull((select Products_Name from TB_Products_Infor where Infor_ID=PID),"+\
                "isnull((select Products_Name from TB_Products_Infor where Infor_ID="+\
                "(select top 1 ProID from TB_FaHuoInfo_"+cid+" where FHKey=a.FHKey)),'')),"+\
            "isnull((select LoginName from TJMarketingSystemYin.dbo.TJ_User where UserID=a.UserID),''),"+\
            "isnull((select StoreHouseName from TB_StoreHouse where STID=FromStorehouseID),''),"+\
            "isnull((select CompName from TJMarketingSystemYin.dbo.TJ_RegisterCompanys where CompID=a.CompID),''),"+\
            "isnull((select CompName from TJMarketingSystemYin.dbo.TJ_RegisterCompanys where CompID=ToAgentID),'') "+\
            "from ("+ " union ".join(a) + ") a"    
        try:
            cur.execute(s)
            for r in cur.fetchall(): 
                batch_id = '0'
                b = Batch.objects.filter(code=r[2]).order_by('id')
                if b:
                    batch_id = b[0].id
                #cur.execute(f"select id from inventory_batch where code = '{r[2]}' order by id limit 1 ")
                #rr = cur.fetchone()
                #if rr:
                #    batch_id = rr[0]
                data.append({ 
                    'vtype_id':2,
                    'label_code':r[0],
                    'bill_no':r[2],
                    'tm':r[1],  
                    'voucher':'销售出库',
                    'product':r[3],                                  
                    'user':r[4],                    
                    'company':r[6],                    
                    'customer':r[7],
                    'store':r[5],
                    'store_from':'',
                    'label_pkg':'箱标',
                    'label_pkg_id':3,
                    'code_b':'',
                    'is_delete':0,
                    'agent':{'name':'','external_code':'','address':'','province':'','city':''},
                    'batch_id':batch_id
                })
        except Exception:
            pass
        cur.close()
    return data



#2022-06-18 os平台 对像自动补全
@login_required
def os_autocomplete(request,cid,what):  
    data=[] 
    lmt=request.GET.get('lmt','10')       
    q=request.GET.get('term','')    
    if what=='product':
        s="select top "+lmt+" Infor_ID,Products_Name from TB_Products_Infor "+\
            "where CompID="+cid+" and Products_Name like '%"+q+"%' order by Products_Name"
    elif what=='agent':
        s="select top "+lmt+" CompID,CompName from TJMarketingSystemYin.dbo.TJ_RegisterCompanys "+\
            "where ParentID="+cid+" and CompName like '%"+q+"%' order by CompName"        
    if s:
        cn = pyodbc.connect(cn_os)
        cur = cn.cursor() 
        cur.execute(s)
        for r in cur.fetchall():
            data.append({"value":str(r[0]),"label":r[1]})
        cur.close()       
    return JsonResponse(data,safe=False)


#2022-06-18 取OS平台销售出库数据
@login_required
def os_outbound(request,cid,what):   
    e=''
    if what=='list':        
        html='os_outbound_list.html'
        dt = datetime.datetime.now().strftime('%Y-%m-%d')
        dt_fr = request.GET.get('date_fr', dt)
        dt_to = request.GET.get('date_to', dt)
        dt_max = max(dt_fr, dt_to)
        dt_min = min(dt_fr, dt_to)
        dt_fr = dt_min
        dt_to = dt_max
        product_id = request.GET.get("product_id", "")
        product_label=request.GET.get('product_label','')
        agent_id=request.GET.get("agent_id","")
        agent_label=request.GET.get('agent_label','')
        code=request.GET.get('code','')
        params = {
            'dt_fr': dt_fr,
            'dt_to': dt_to,
            'agent_id': agent_id,
            'agent_label':agent_label,
            'product_id': product_id,
            'product_label':product_label,
            'code':code,
        }
        sWhere=" where (FHDate between '"+dt_fr+"' and '"+dt_to+"')"
        if product_id:
            sWhere=sWhere+" and ProID="+product_id
        if agent_id:
            sWhere=sWhere+" and AgentID="+agent_id

        saldiv_rpt=False
        try:
            if request.user.company.cfg_company:
                saldiv_rpt=request.user.company.cfg_company.saldiv_report
        except Exception:
            pass
        #需要需要显示战区分区
        if saldiv_rpt:
            clmns=['上传时间','单据编号','客户名称','战区','分区','产品名称','仓库名称','操作人','数量']
        else:
            clmns=['上传时间','单据编号','客户名称','产品名称','仓库名称','操作人','数量']

        cn = pyodbc.connect(cn_os)
        cur = cn.cursor()
        
        #clmns=['上传时间','单据编号','客户名称','产品名称','仓库名称','操作人','箱数']
        data=[]
        s="select CONVERT(varchar,FHDate,120),isnull(FHPiCi,''),XiangNumber,"+\
            "isnull((select CompName from TJMarketingSystemYin.dbo.TJ_RegisterCompanys where CompID=AgentID),''),"+\
            "isnull((select Products_Name from TB_Products_Infor where Infor_ID=ProID),''),"+\
            "isnull((select StoreHouseName from TB_StoreHouse where STID=d.STID),''),"+\
            "isnull((select LoginName from TJMarketingSystemYin.dbo.TJ_User where UserID=FHUserID),''),"+\
            "FHKey,tbs,TableNameInfo "+\
            "from TB_FaHuoInfo_"+cid+" d "+sWhere+" order by FHDate"   
        cur.execute(s)
        for r in cur.fetchall():
            data.append([  r[0],r[1],r[3],r[4],r[5],r[6],r[2]  ])
        d= {      
            'cid':cid,
            'data':SafeString(data),            
            'clmns':clmns,
            'e': e,        
            'params': params
        }
        cur.close()
        cn.close()        
    return render(request, 'inventory/stock/'+html,d)










def jiugui_local116(box_code):
    data = {
        'e':'',
        'product':'',
        'boxes': {'pk': '', 'related': []},
        'bottles': [],
        'stock_dev':[]
    }
    #box_code=request.GET.get('code','')
    #if not box_code:
    #    data['e']=u'box code missing'
    #    return JsonResponse(data)
    cn = pyodbc.connect(WULIU_STR)
    cur = cn.cursor() 
    a = []
    rg = box_code[:4]   
    for n in range(3):
        # 表是否存在             
        cur.execute("select name from sysobjects where  name='W" + rg + "_0" + str(n)  + "'")
        r0 = cur.fetchone ()
        if r0:
            s = "select IsFaHuo,HuoDanHao,RuKuShiJian,FaHuoShiJian,MuDiDi,PinMing,FaHuoCang," + \
                "'W" + rg + "_0" + str(n) + "' tb, BoxLabel01,AgentID "+ \
                "FROM W" + rg + "_0" + str(n) + " where BoxLabel01=" + \
                "isnull((select BoxLabel01 FROM W"+rg+"_0"+str(n)+"_BX where BoxLabel='"+box_code+"'),'" + box_code+"')"
            
            a.append(s)    
    if a:
        s = "select IsFaHuo,isnull(HuoDanHao,''),RuKuShiJian,FaHuoShiJian," \
            "isnull(isnull(MuDiDi,(select Agent_Name from TB_Agents_Infor where Agent_ID=a.AgentID)),'')," + \
            "(select Products_Name from TB_Products_Infor where Infor_ID=PinMing)," \
            "(select StoreHouseName from TB_StoreHouse where STID=FaHuoCang)," + \
            "tb,BoxLabel01 from " + \
            "("+ " union ".join(a) + ") a where IsFaHuo is not null"

        cur.execute(s)
        r = cur.fetchone()
        if r:
            data['product'] = r[5]
            if r[0] == '已入库':
                t = ''
                if r[2]:
                    t = r[2].strftime('%Y-%m-%d %H:%M')
                data['stock_dev'] = [{
                    'label_code': box_code,
                    'voucher_type': '成品入库',
                    'voucher_no': '',
                    'time': t,
                    'user': '',
                    'product': r[5],
                    'store': r[6],
                    'store_fr': '',
                    'package': '箱',
                    'to_company': '',
                    'fr_company':'酒鬼酒股份有限公司',
                }]
            elif r[0] == '已发货':
                t1 = ''
                t2 = ''
                if r[2]:
                    t1 = r[2].strftime('%Y-%m-%d %H:%M')
                if r[3]:
                    t2 = r[3].strftime('%Y-%m-%d %H:%M')
                data['stock_dev'] = [
                    {
                        'label_code': box_code,
                        'voucher_type': '成品入库',
                        'voucher_no': '',
                        'time': t1,
                        'user': '',
                        'product': r[5],
                        'store': r[6],
                        'store_fr': '',
                        'package': '箱',
                        'to_company': '',
                        'fr_company':'酒鬼酒股份有限公司',
                    },
                    {
                        'label_code': box_code,
                        'voucher_type': '销售出库',
                        'voucher_no': r[1],
                        'time': t2,
                        'user': '',
                        'product': r[5],
                        'store': r[6],
                        'store_fr': '',
                        'package': '箱',
                        'to_company': r[4],
                        'fr_company':'酒鬼酒股份有限公司 ',
                    }
                ]
            t = r[7]
            c = r[8]
            a = []
            # 关联箱标
            data['boxes']['pk'] = c
            cur.execute("SELECT BoxLabel FROM " + t + "_BX where BoxLabel01='" + c + "'")
            for r in cur.fetchall():
                a.append(r[0])
            if a:
                data['boxes']['related'] = a
                a = []
            # 瓶标
            cur.execute("SELECT BottleLabel FROM " + t + "_BT where BoxLabel01='" + c + "'")
            for r in cur.fetchall():
                a.append(r[0])
            if a:
                data['bottles'] = a
    else:
        data['e'] = '缺少基础数据'

    cur.close()
    cn.close()
    return data


#2021-04-02
def app_obj_info(request,obj_name,id):
    data = {'e':'' ,'data':{}}
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    app_name='inventory'
    data=get_obj_info(app_name,obj_name,id)    
    return JsonResponse(data)





#2020-06-28
#对外标签查询接口
def external_label_info(request,company_id):
    sK='yglkfdvgu$#&3t@j'
    code=request.GET.get('code','')
    data = {
        'e': '',
        'code': code,
        'product': '',
        'package': '',    
        'photo':'',
        'price':'',
        'replace': '',        
        'boxes': {'pk': '', 'related': []},
        'packets': [],
        'bottles': [],
        'stock_dev': [],
        
        #2020-11-02
        'qc':'',
        'batch_no':'',
        'barcode':'',       
    }
    if not code:
        data['e']='code missing'
        return JsonResponse(data)    
      
    e = time_key_check(request, sK)
    if e:
        data['e'] = e
        return JsonResponse(data)   
    c=Company.objects.get(id=int(company_id))
    d=label_sys_info(code,c,has_price=True)   
    if d['e']:
        data['e']=d['e']
        return JsonResponse(data)  
    data['inboud_ticket']=d['inboud_ticket']
    data['replace']=d['replace']
    data['package']=d['package']['name']
    data['product']=d['product']['name']
    data['price']=d['product']['price']
    data['packets']=d['packets']
    data['bottles']=d['bottles']
    data['boxes']=d['boxes']
    data['stock_dev']=d['stock_dev']
    if d['product']['photo']:
        data['photo']='/media/'+d['product']['photo']
    
    if 'batch_no' in  d:
        data['batch_no']=d['batch_no']
    if 'qc' in d:
        data['qc']=d['qc']
    if 'barcode' in d:
        data['barcode']=d['barcode']

    return JsonResponse(data)




def user_label_info(user,code):   
    data = {
        'e': '',
        'code': code,
        'product': '',
        'product_id':0,
        'product_remark':'',
        'package': '',        
        'replace': '',
        'boxes': {'pk': '', 'related': []},
        'packets': [],
        'bottles': [],
        'stock_dev': []        
    }     
    u=user
    c=u.company
    d=label_sys_info(code,c)   
   

    if d['e']:
        data['e']=d['e']
        return data    
    data['packets']=d['packets']
    data['bottles']=d['bottles']
    data['boxes']=d['boxes']
    #天鉴品控部 只能查询套标关系
    if u.id==4:   
        return data    
    cur=connection.cursor()
    if d['stock_dev']: 
        data['replace']=d['replace']      
        data['package']=d['package']['name'] 
        data['product']=d['product']['name'] 
        data['product_id']=d['product']['id']
        data['product_remark']=d['product']['remark']
        

        #2021-02-23
        has_perm=True
        #市场稽查产品授权
        #cur.execute("select id from company_user_groups where user_id="+str(u.id)+" and group_id=1")
        #r=cur.fetchone()        
        #if r:            
        #    cur.execute("select what,content from product_authquery where user_id="+str(u.id)+" and what is not null")
        #    r=cur.fetchone()            
        #    if not r:
        #        has_perm=True
        #    else:
        #        if r[0]=='product':
        #            a=r[1].split(',')
        #            #酒鬼可以查看内参产品物流
        #            if u.company_id==1:
        #                s="select id from product_product where company_id=1644 and name in "+\
        #                    "(select name from product_product where id in  ("+r[1]+"))"
        #                cur.execute(s)
        #                for r1 in cur.fetchall():
        #                    a.append(r1[0])
        #            if d['product']['id'] in a:
        #                has_perm=True
        #        elif r[0]=='series':
        #            if d['series']['id'] in r[1].split(','):
        #                has_perm=True
        #else:
        #    has_perm=True

        if has_perm:
            data['stock_dev']=d['stock_dev']
            if not d['has_outbound']:
                dd=jiugui_local116(d['boxes']['pk'])
                for rr in dd['stock_dev']:
                    if rr['voucher_type']=='销售出库':
                        data['stock_dev'].append(rr)   

    else:
        if c.id==1:
            data['package']=d['package']['name']
            dd=jiugui_local116(d['boxes']['pk'])
            #罗秋吉
            if u.id==2:
                data['bottles']=d['bottles']
                data['boxes']=d['boxes']                
                data['stock_dev']=dd['stock_dev']
            else:
                data['bottles']=dd['bottles']
                data['boxes']=dd['boxes']                
                data['stock_dev']=dd['stock_dev']                
        else:
            data['e']=_('标签未激活')    
    
    return data     




#2020-06-22 重写标签查询接口
def label_sys_info(code,company=None,has_price=False):

    data = {
        'e': '',
        'label_pk_id':0,
        'replace':'',
        'batch_no':'',
        'qc':'',
        'barcode':'',
        'code': code,
        'has_outbound':False,
        'stock_dev':[], 
        'packets': [],
        'bottles': [],
        'series':{'id':0,'name':''},
        'product':{'id':0,'name':'','photo':'','price':'','remark':''},  
        'package':{'id':0, 'name':''},        
        'boxes': {'pk':'', 'related':[]},
        'inboud_ticket':{},
        'product_aging':'',
        'vendor_id':''
    }        
    cur=connection.cursor()
    label_pk_id=0   


    # 标签是否有被替换的情况 2022-03-24：小圆标也有替换
    s="select code0,code,dt from label.lbl_replace_details where code='" + code + "' or code0='"+code+"' order by id desc limit 1"    
    cur.execute(s)   
    rr=cur.fetchone()    
    if rr:
        code=rr[0]
        data['replace']="此标签有替换记录 "+rr[2].strftime('%Y-%m-%d')+": "+rr[0]+" -> "+rr[1] 
    #2021-05-06 瓶盖码/活动码
    if not code.isdigit():     
        #2022-03-24 可能会查询瓶盖码
        cur.execute("select bottle from label.bottlecap where  label='"+code+"' "+\
            " union all "+\
            "select bottle from z_bottlecap_binding where  label='"+code+"' "
        )
        rt=cur.fetchone()
        if rt:
            code=rt[0]
        else:
            code=decrypt_11h(code)
            if not code:
                data['e']='label code error'
                return data   
    
    
    if company.id in (1,1644) and code[:1]=='4':
        r = requests.request('GET', 'http://www.china315net.com:35088/jg/fw_wl/'+code+'/')
        d = json.loads(r.text)
        if d['wl']:
            code=d['wl']
            data['code']=d['wl']
        else:
            data['e']='获取物流码失败'
            return data
    #2020-04-30 有标签要查BA表 "湖北裕贡酒业销售有限公司"
    #if company.id in [16716]:
    cur.execute("select code_a FROM label.lbl_abcode where code_b='"+code+"'")
    r=cur.fetchone()
    if r:
        code=r[0]    
    t="label.t" +code[:4]

    #2020-07-27 是否跨段动态绑定
    cur.execute("select tbname from label.lbl_tbcross where segment='"+code[:4]+"'")
    rrr=cur.fetchone()
    if rrr:
        t='label.'+rrr[0] 
    else:
        #2021-12-09 是否为第三方标签
        cur.execute("select id,code from label.thirdparty where cid="+str(company.id)+" and (code='"+code+"' or fw_code='"+code+"')")
        rrr=cur.fetchone()
        if rrr:
            t='label.thirdparty'
            #self.infor['is_thirdparty']=True
            #code=rrr[1]


    try:
        cur.execute("select id,package_id,(SELECT name FROM label.lbl_package where id=package_id)," + \
            "coalesce((select parent_id from " +t+ " where id=a.parent_id),parent_id) from "+t+" a where code='"+code+"'") 
        r = cur.fetchone()
        if not r:
            data['e'] = _('标签号码异常')
            return data
    except Exception as e:
        data['e'] = _('标签号码异常')
        return data
    data['package']['id']=r[1]
    data['package']['name']=r[2]
    if r[3]:
        label_pk_id=r[3]
    else:
        label_pk_id=r[0] 

    data['label_pk_id']=label_pk_id
    #箱标
    s="select code,"+\
        "array_to_string(array(select code from "+t+" where parent_id="+str(label_pk_id)+" and package_id=3),',') "+\
        "from "+t+" where id="+str(label_pk_id)
    cur.execute(s)
    r=cur.fetchone()
    if r:
        data['boxes']['pk']=r[0]
        if r[1]:
            data['boxes']['related']=r[1].split(',')
    #是否有盒标    
    cur.execute("select id,code from "+t+" where package_id=2 and parent_id="+str(label_pk_id))
    rs=cur.fetchall()


   

    #有盒标，三级对应
    if rs:
        for r in rs:            
            a = []
            cur.execute("select coalesce((select code from label.lbl_replace_details where code0=a.code),a.code) " +\
                "from " + t + " a where parent_id=" + str(r[0]) + " order by code")
            for r1 in cur.fetchall():
                a.append(r1[0])
            data['packets'].append({'code': r[1], 'bottles': a})
    else:
        #箱瓶二级对应
        cur.execute("select array_to_string(array(select "+\
            "coalesce((select code from label.lbl_replace_details where code0=a.code),a.code) "+\
            "from "+t+" a where package_id=1 and parent_id="+str(label_pk_id)+"),',')")
        r=cur.fetchone()
        data['bottles']=r[0].split(',')

     
        
        #2021-05-03 酒鬼酷客白在线绑定
        if not data['bottles']:
            cur.execute("select array_to_string(array(select "+\
                "coalesce((select code from label.lbl_replace_details where code0=a.bottle),a.bottle) "+\
                "from label.bottlecap a where label_pk_id="+str(label_pk_id)+"),',')")
            r=cur.fetchone()
            data['bottles']=r[0].split(',')







    #天鉴品控部 不属于任何公司，且只能查询套标关系 
    if not company:
        return data        
    #产品，公司，物流信息
    sWhere=" where label_pk_id="+str(label_pk_id)
    if company.level_id==1:
        #酒鬼可查内参物流
        if company.id==1:
            sAnd=" and ancestor_id in (1,1644)"
        else:
            sAnd=" and ancestor_id="+str(company.id)
    else:        
        sAnd=" and company_id="+str(company.id)  
    #price=" "
    price=",'' "
    if has_price:
        price=",coalesce(to_char((select price from product_product where id=a.product_id),'FM999999.90'),'') "
    s="select a.label_code, b.code, a.product_id,a.vtype_id,"+\
        "(select series_id from product_product where id=a.product_id),"+\
        "(select name from product_series where id=(select series_id from product_product where id=a.product_id)),"+\
        "(select name FROM label.lbl_package where id=a.label_pkg),"+\
        "(select name from inventory_voucher where id=a.vtype_id),"+\
        "to_char(a.tm,'yyyy-mm-dd HH24:MI:SS'),"+\
        "(select username from company_user where id=b.user_id),"+\
        "(select name from product_product where id=a.product_id),"+\
        "coalesce((select name from inventory_storehouse where id=a.store_id),''),"+\
        "case when a.vtype_id=3 then coalesce((select name from  inventory_storehouse where id=a.store_fr_id),'') else '' end,"+\
        "coalesce((select name from company_company where id=a.company_to_id),''),"+\
        "coalesce((select photo from product_product where id=a.product_id),''),"+\
        "coalesce((select barcode from product_product where id=a.product_id),''),"+\
        "b.code,"+\
        "b.qc "+\
        price +\
        ",(select name from company_company where id=a.company_id) "+\
        "from "+\
        "(SELECT label_code,vtype_id,batch_id,tm,product_id,store_id,store_fr_id,company_to_id,label_pkg,company_id"+\
           " from inventory_stkdetails"+sWhere+sAnd+" order by tm) a "+\
        "left outer join "+\
        "(select id,code,user_id,coalesce(qc_name,'') qc,product_aging,vendor_id from inventory_batch) b "+\
        "on a.batch_id=b.id "+\
        "order by a.tm"    

    s="select a.label_code, b.code, a.product_id,a.vtype_id,"+\
        "(select series_id from product_product where id=a.product_id),"+\
        "(select name from product_series where id=(select series_id from product_product where id=a.product_id)),"+\
        "(select name FROM label.lbl_package where id=a.label_pkg),"+\
        "(select name from inventory_voucher where id=a.vtype_id),"+\
        "to_char(a.tm,'yyyy-mm-dd HH24:MI:SS'),"+\
        "(select username from company_user where id=b.user_id),"+\
        "(select name from product_product where id=a.product_id),"+\
        "coalesce((select name from inventory_storehouse where id=a.store_id),''),"+\
        "case when a.vtype_id=3 then coalesce((select name from  inventory_storehouse where id=a.store_fr_id),'') else '' end,"+\
        "coalesce((select name from company_company where id=a.company_to_id),''),"+\
        "coalesce((select photo from product_product where id=a.product_id),''),"+\
        "coalesce((select barcode from product_product where id=a.product_id),''),"+\
        "b.code,"+\
        "b.qc "+\
        price +\
        ",(select name from company_company where id=a.company_id),"+\
        "b.inbound_ticket_id,a.company_id,"+\
        "coalesce((select remark from product_product where id=a.product_id),''),"+\
        "b.product_aging,b.vendor_id "+\
        "from "+\
        "(SELECT label_code,vtype_id,batch_id,tm,product_id,store_id,store_fr_id,company_to_id,label_pkg,company_id"+\
           " from inventory_stkdetails"+sWhere+sAnd+" order by tm) a "+\
        "left outer join "+\
        "(select id,code,user_id,coalesce(qc_name,'') qc,inbound_ticket_id,product_aging,vendor_id from inventory_batch) b "+\
        "on a.batch_id=b.id "+\
        "order by a.tm"   

   
    cur.execute(s)    
    inbound_ticket_id=None
    for r in cur.fetchall():         

        if r[3]==1:
            data['product']['id']=r[2]
            data['product']['name']=r[10]
            data['product']['photo']=r[14]            

            #2020-11-12
            data['barcode']=r[15]  
            data['qc']=r[16]
            data['batch_no']=r[17]

            data['product']['price']=r[18]
            data['product']['remark']=r[22]

            data['series']['id']=r[4]
            data['series']['name']=r[5]
            if r[20]:
                inbound_ticket_id=r[20]
                
            data['product_aging'] = r[23]
            data['vendor_id'] = r[24]

        elif not data['product']['id']:
            data['product']['id']=r[2]
            data['product']['name']=r[10]
            data['product']['photo']=r[14]
            data['product']['price']=r[15]
            data['product']['remark']=r[22]
            data['series']['id']=r[4]
            data['series']['name']=r[5]   
        if r[3]==2:
            data['has_outbound']=True
        i={
            'label_code': r[0],
            'voucher_no': r[1],
            'package': r[6],
            'voucher_type': r[7],            
            'time': r[8],
            'user': r[9],
            'product': r[10],
            'store': r[11],
            'store_fr': r[12] ,            
            'to_company': r[13],
            'company':r[19],
            'company_id':r[21]
        }
        if has_price:
            if r[14]:
                i['price']=str(r[15])
            else:
                i['price']=''
        data['stock_dev'].append(i)  
        
    

    if inbound_ticket_id:
        ts=InboundTickets.objects.filter(id=inbound_ticket_id)
        if ts:
            t=ts[0]
            tk={                  
                'production_time': t.first_tm,
                'pihao': t.pihao,
                'pici': t.pici,
                'security_code': t.fangweiqr,
                'check_time': t.check_tm,
                'check_user': t.check_user,
                'export_number': t.ckwszcbh,
                'production_license': t.scxkzbh,
                'yuanchandi': t.origin,
                'assembly':t.assembly,  
                #2021-04-14
                'chandi':t.chandi, 
                'shengchanaddress':t.shengchanaddress, 
                'shengchanfactory':t.shengchanfactory,         
            }
            data['inboud_ticket']=tk            
    return data
   


#2020-06-28
@tj_login_required
def get_label_sys_info(request, code):   
    data = {
        'e': '',
        'code': code,
        'product': '',
        'package': '',        
        'replace': '',
        'boxes': {'pk': '', 'related': []},
        'packets': [],
        'bottles': [],
        'stock_dev': []        
    }     
    user=request.user
    data=user_label_info(user,code)   
    return JsonResponse(data) 


#2020-06-28
def wx_user_label_info(request, user_id, code):   
    data = {
        'e': '',
        'code': code,
        'product': '',
        'package': '',        
        'replace': '',
        'boxes': {'pk': '', 'related': []},
        'packets': [],
        'bottles': [],
        'stock_dev': []        
    }     
    user=User.objects.get(id=int(user_id))
    data=user_label_info(user,code)   
    return JsonResponse(data)

#2021-06-01
'''
@csrf_exempt
def wx_qz_get_label_info(request, user_id, code):      
    user=User.objects.get(id=int(user_id))
    data = {
        'e': '',
        'code': code,
        'product': '',
        'product_id':0,
        'package': '',        
        'replace': '',
        'boxes': {'pk': '', 'related': []},
        'packets': [],
        'bottles': [],
        'stock_dev': []        
    }     
    u=user
    c=u.company
    print(c)
    d=label_sys_info(code,c)
    if d['e']:
        data['e']=d['e']
        return data    
    data['packets']=d['packets']
    data['bottles']=d['bottles']
    data['boxes']=d['boxes']

    data['replace']=d['replace']      
    data['package']=d['package']['name'] 
    data['product']=d['product']['name'] 
    data['product_id']=d['product']['id']
    
    return JsonResponse(data) 
'''


#2020-05-21 酒鬼酒，若新平台没有发货记录，查询116本地发货记录
#def jiugui_delivery(box_code):
#    delivery = {}
#    url="http://davis.china315net.com:8118/wuliu/jiugui/delivery/?code="+box_code


#    r = requests.get(url)
#    if r.status_code == requests.codes.ok:
#        delivery=r.json()   
#    return delivery

def jiugui_delivery(box_code):
    data = {
        'e':'',        
        'delivery':{}
    }    
    cn = pyodbc.connect(WULIU_STR)
    cur = cn.cursor() 
    a = []
    rg = box_code[:4]   
    for n in range(3):
        # 表是否存在             
        cur.execute("select name from sysobjects where  name='W" + rg + "_0" + str(n)  + "'")
        r0 = cur.fetchone ()
        if r0:
            s = "select IsFaHuo,HuoDanHao,RuKuShiJian,FaHuoShiJian,MuDiDi,PinMing,FaHuoCang," + \
                "'W" + rg + "_0" + str(n) + "' tb, BoxLabel01,AgentID "+ \
                "FROM W" + rg + "_0" + str(n) + " where BoxLabel01=" + \
                "isnull((select BoxLabel01 FROM W"+rg+"_0"+str(n)+"_BX where BoxLabel='"+box_code+"'),'" + box_code+"')"
            
            a.append(s)    
    if a:
        s = "select IsFaHuo,isnull(HuoDanHao,''),RuKuShiJian,FaHuoShiJian," \
            "isnull(isnull(MuDiDi,(select Agent_Name from TB_Agents_Infor where Agent_ID=a.AgentID)),'')," + \
            "(select Products_Name from TB_Products_Infor where Infor_ID=PinMing)," \
            "(select StoreHouseName from TB_StoreHouse where STID=FaHuoCang)," + \
            "tb,BoxLabel01 from " + \
            "("+ " union ".join(a) + ") a where IsFaHuo is not null"
        cur.execute(s)
        r = cur.fetchone()
        if r:   
            if r[0] == '已发货':
                t1 = ''
                t2 = ''
                if r[2]:
                    t1 = r[2].strftime('%Y-%m-%d %H:%M')
                if r[3]:
                    t2 = r[3].strftime('%Y-%m-%d %H:%M')
                data['delivery'] ={
                        'label_code': box_code,
                        'voucher_type': '销售出库',
                        'voucher_no': r[1],
                        'time': t2,
                        'user': '',
                        'product': r[5],
                        'store': r[6],
                        'store_fr': '',
                        'package': '箱',
                        'to_company': r[4]
                }   
    cur.close()
    cn.close()    
    return data



@csrf_exempt
def fg_update000(request,is_app=False):
    """
    新物流系统，产成品入库，出库处理
    :param request: json
    :return: json
    """
    data = {'e': '', 'cnt': 0, 'rebate':{'promotion_id':0}}
    k = sK
    r = json.loads(request.body)
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    keys = ['bill_number', 'user_id', 'company_id', 'voucher_id', 'voucher_time']
    
    
    #for k in keys:
    #    if k not in keys:
    #        data['e'] = _('缺少参数') + k
    #        return JsonResponse(data)
    
    """单据类别：voucher id
    1;"成品入库单";"GRN";1
    2;"销售出库单";"GDN";-1
    3;"成品转库单";"GTN";0
    4;"销售退库单";"GWN";1
    5;"入库单退库";"GCN";-1
    """
    # 必传：单号，用户ID，公司ID, 单据类别ID, 单据生成时间
    code = r['bill_number']
    # hdh+"|" + yyyyMMddHHmmss  比如：8785454567|20190528220956  |号前是交货单号，后面是一个年月日时分秒的虚拟单号
    code = code.split('|')[0]

    usr_id = int(r['user_id'])
    cmp_id = int(r['company_id'])
    vch_id = int(r['voucher_id'])
    
    #2020-10-30
    qc=None
    if 'qc' in r:
        qc=r['qc']
    #生产批次号/批次号
    batch_no=None
    if 'batch_no' in r:        
        batch_no=r['batch_no']
    else:
        if vch_id==1:
            batch_no=code    

    vch_tm = r['voucher_time']
    #2020-08-29 是否强制发货
    force=False
    if 'force' in r:
        force=r['force']
    if cmp_id==1:   #酒鬼有大量销售退库
        force=True

    # 扫码枪传过来的voucher_time，不可靠
    vch_tm = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    vch_dt = vch_tm[:10]
    c = Company.objects.get(id=int(cmp_id))




    voucher = Voucher.objects.get(id=int(vch_id))    
    #m = apps.get_model('inventory', voucher.code)
    batch = Batch()    
    batch.code = code    
    batch.company_id=c.id
    batch.company_fr_id = c.id
    batch.level_id=c.level_id
    batch.hierarchy_id=c.hierarchy_id
    batch.version=c.version   
    batch.user_id = int(usr_id)   
    batch.ancestor_id=c.ancestor_id
    
    #2020-10-30
    batch.qc_name=qc
    batch.batch_no=batch_no
    #2021-01-05
    if 'order_sn' in r:
        batch.order_sn=r['order_sn']
    #2021-01-29
    if 'recommender_id' in r:
        if r['recommender_id']:
            batch.recommender_id=int(r['recommender_id'])

    #2020-09-17       
    if 'lnglat_start' in r:
        batch.lnglat_start=r['lnglat_start']
    if 'lnglat_end' in r:
        batch.lnglat_end=r['lnglat_end']
    if 'distance' in r:
        batch.distance=r['distance']
    if 'storegeo_id' in r:
        batch.storegeo_id=r['storegeo_id']
    # 终端店订单 
    if 'agent_order_number' in r:        
        agent_order_number=r['agent_order_number']
        cur.execute("update company_agentorderbatch set batch_code = '"+code+"' where code = '"+agent_order_number+"' ")
    #2021-03-03
    if 'ticket_id' in r:                #销售启票id
        batch.outbound_ticket_id=int(r['ticket_id'])    
    if 'bill_number2' in r:             #入库 启票id
        if r['bill_number2'].isdigit():
            batch.inbound_ticket_id=int(r['bill_number2'])   


    # 写入到delivery
    prd_id = 'null'
    sto_id = 'null'
    agt_id = 'null'

    # 成品入库，号码唯一
    label_unique=''
    batch.voucher_id = voucher.id
    batch.vtype_id=int(vch_id)   
   
    
    #2020-05-30
    STRICT=True         #直营店要扫码入库
    if vch_dt[:7]=='2020-06' and c.ancestor_id==1644:
        STRICT=False    #扫码出库时，若直营店未扫码入库，系统补一笔入库


    # 有没有传产品ID；转库有没有from_store_id
    store_fr_id_o = 0
    if 'from_store_id' in r:
        store_fr_id_o = int(r['from_store_id'])
        if vch_id == 3 and store_fr_id_o:            
            batch.store_fr_id = store_fr_id_o
    product_id_o = None
    if 'product_id' in r:
        if int(r['product_id'])>0:
            product_id_o=int(r['product_id'])
          
    batch.product_id = product_id_o
    if vch_id == 1:         # 产成品入库
        # 成品入库，号码唯一
        #label_unique=" and (select id from logistics.inventory_stkdetails " + \
        #             "where voucher_type='grn' and label_code=a.label_code and company_id=" + str(c.id) + " ) is null"        

        batch.store_fr_id = int(r['store_id'])
        if c.has_plant:      
            #2020-04-21 超鹏把plant_id写死了，使用的是gongchang_id
            if 'gongchang_id' in r:
                batch.prd_plant_id = int(r['gongchang_id'])
            else:
                batch.prd_plant_id = int(r['plant_id'])     

        if c.has_workshop:           
            batch.prd_workshop_id = int(r['workshop_id'])
        if 'qc_id' in r:           
            batch.qc_id = int(r['qc_id'])
        if 'batch_no' in r:           
            batch.batch_no = r['batch_no']
        if 'workline_id' in r:           
            batch.prd_line_id = r['workline_id']
    #elif vch_id == 2:       # 销售出库
    #2022-01-14
    elif vch_id in  (2,7):       # 销售出库 礼品出库
        sto_id = r['store_id'] 
        if sto_id:
            batch.store_fr_id = int(sto_id)
        agt_id = r['to_company_id']       
        batch.company_to_id = int(agt_id)
        #2020-05-28 微信小程序，销售出库给团购，①单位名称，②姓名，③电话。        
        if is_app and int(agt_id)==11014:  
            batch.customer_company=r['company']                 
            batch.customer_name=r['name']                 
            batch.customer_phone=r['phone']
    elif vch_id == 3:       # 转库        
        batch.store_to_id = int(r['store_id'])
    elif vch_id == 4:       # 销售退库       
        batch.store_fr_id = int(r['store_id'])
    elif vch_id == 5:       # 标签退库
        if 'store_id' in r:            
            batch.store_fr_id = int(r['store_id'])
    
    if not batch.store_fr_id:
        batch.store_fr_id=None
    batch.save()
    b_id = str(batch.id)    
    codes = r['codes']
    rec_cnt = len(codes)
    a = []
    cur = connection.cursor()
    #2020-10-19
    cur.execute("create temp table codes(label_code character varying(20),tb character varying(20),product_id integer ,"+\
        "code character varying(20),label_id bigint,label_pk_id bigint,label_pkg smallint,err character varying(100))")
    for code in codes:
        #物流终端发货CODES
        #codes:[{"code": "104700934637","err_code": "", "e": "错误信息", "product_id":2221, "from_agent_id":21754}]    
        if is_app:  
            e='null'
            pid='null'
            #if code['product_id']:
            if 'product_id' in code:
                if int(code['product_id'])>0:
                    pid=str(code['product_id'])   
            elif batch.product_id:
                pid=str(batch.product_id)
            if code['e']:
                e="'"+code['e'][:100]+"'"
            a.append("('"+code['code']+"','"+code['code'][:4]+"',"+e+","+pid+")")
            sSql="insert into codes (label_code,tb,err,product_id) values " + ",".join(a)
        else:  
            if batch.product_id:
                a.append("('" + code + "','" + code[:4] + "',"+str(batch.product_id)+")")
            else:
                a.append("('" + code + "','" + code[:4] + "',null)")
            sSql="insert into codes (label_code,tb,product_id) values " + ",".join(a)       
    cur.execute(sSql)   
    #处理标签替换
    s="update codes o set code=coalesce"+\
        "((select code0 from label.lbl_replace_details where code=o.label_code order by batch_id desc limit 1),o.label_code)"
    cur.execute(s)

    #2020-12-18 处理AB标
    #cur.execute("select code_a FROM label.lbl_abcode where code_b='"+code+"'")
    s="update codes set code="+\
        "coalesce((select code_a FROM label.lbl_abcode where code_b=label_code),code)"
    cur.execute(s) 

    #2020-07-27 处理跨段动态绑定
    s="update codes set tb=b.tbname from "+\
        "(SELECT tb,label_code from codes) a "+\
        "left outer join "+\
        "(SELECT segment, tbname FROM label.lbl_tbcross) b "+\
        "on a.tb=b.segment "+\
        "where  codes.label_code=a.label_code and b.tbname is not null"
    cur.execute(s)
    cur.execute("update codes set tb='t'||left(code,4) where length(tb)=4")   


    cur.execute("select tb from codes group by tb")
    rs = cur.fetchall()
    for r in rs:  
        cur.execute("select to_regclass('label." + r[0] + "')")
        r0 = cur.fetchone()
        if r0[0]:
            #s="update codes set "+\
            #    "label_id=b.id,"+\
            #    "label_pkg=b.package_id,"+\
            #    "label_pk_id=coalesce(b.parent_id,b.id) "+\
            #    "from "+\
            #    "(SELECT label_code,code from codes where tb='"+r[0]+"') a "+\
            #    "left outer join "+\
            #    "(select id,code,parent_id,package_id,is_pk from label."+r[0]+") b "+\
            #    "on a.label_code=b.code "+\
            #    "where tb='"+r[0]+"' and codes.code=a.code"
            s="update codes set "+\
                "label_id=b.id,"+\
                "label_pkg=b.package_id,"+\
                "label_pk_id=coalesce(b.parent_id,b.id) "+\
                "from "+\
                "(SELECT label_code,code from codes where tb='"+r[0]+"') a "+\
                "left outer join "+\
                "(select id,code,parent_id,package_id,is_pk from label."+r[0]+") b "+\
                "on a.code=b.code "+\
                "where tb='"+r[0]+"' and codes.code=a.code"
            cur.execute(s)   


    #2020-10-19
    #s="insert into logistics.inventory_batchdetails(batch_id,label_code,label_id,label_pkg,tm,label_pk_id,company_id,ancestor_id,err,product_id) " +\
    #    "select "+str(batch.id)+",code,label_id,label_pkg,now(),label_pk_id,"+str(c.id)+","+str(c.ancestor_id)+",err,product_id from codes"
    #2021-01-17 codes可能有重复号码
    s="insert into logistics.inventory_batchdetails(batch_id,label_code,label_id,label_pkg,tm,label_pk_id,company_id,ancestor_id,err,product_id) " +\
        "select "+str(batch.id)+",code,label_id,label_pkg,now(),label_pk_id,"+str(c.id)+","+str(c.ancestor_id)+",err,product_id from codes "+\
        "group by code,label_id,label_pkg,label_pk_id,product_id,err"
    s="insert into logistics.inventory_batchdetails(batch_id,label_code,label_id,label_pkg,tm,label_pk_id,company_id,ancestor_id,err,product_id) " +\
        "select "+str(batch.id)+",label_code,label_id,label_pkg,now(),label_pk_id,"+str(c.id)+","+str(c.ancestor_id)+",err,product_id from codes "+\
        "group by label_code,label_id,label_pkg,label_pk_id,product_id,err"
    cur.execute(s)
    cnt = cur.rowcount  

    store_fr = "null"
    d = 'false'
    if product_id_o:
        product = str(product_id_o)
    else:        
        product = "(select product_id from logistics.inventory_stkdetails where vtype_id in (1,2) " + \
            "and ancestor_id="+str(c.ancestor_id)+" and label_pk_id=a.label_pk_id and product_id is not null order by id desc limit 1)"  
    if vch_id == 5:     # 标签退库
        d = "true"
        store = "(select store_id from logistics.inventory_stkdetails where voucher_type='grn' " + \
            "and  label_code=a.label_code and store_id is not null order by id desc limit 1)"
    elif vch_id == 3:    # 成品转库
        store = str(batch.store_to_id)        
        store_fr = "coalesce(" + str(store_fr_id_o) + "," + \
                "(select store_id from logistics.inventory_stkdetails where voucher_type='gtn' " + \
                "and  label_code=a.label_code and store_id is not null order by id desc limit 1)," + \
                "(select store_id from logistics.inventory_stkdetails where voucher_type='grn' " + \
                "and  label_code=a.label_code and store_id is not null order by id desc limit 1))" 
    else:
        if batch.store_fr_id:
            store = str(batch.store_fr_id)
        else:
            store='null'     





    cur.execute("update logistics.inventory_batchdetails set err='标签错误'  where batch_id="+b_id+" and label_id is null")
    #2020-05-01 无论是微信小程序还是扫码枪，入库和出库，同一箱号只能有一条记录    
    #if vch_id in [1,2]:
    
    #2020-11-09,内参小程序新模式：扫了瓶标，可以扫箱标，置换出瓶标(数据检查已在小程序端完成)    
    if batch.ancestor_id==1644 and is_app:
        pass
    elif vch_id in [1,2]:
        s=''
        rmk=voucher.remark  
        #if vch_id==2:
        #2022-01-14
        if vch_id in (2,7):
            if not force:
                s="update logistics.inventory_batchdetails b set err='此标签已于'||("+\
                    "select to_char(tm,'yyyy-mm-dd HH24:MI:SS') from logistics.inventory_stkdetails where "+\
                        "vtype_id="+str(vch_id)+" and company_id="+str(c.id)+\
                        " and label_code=b.label_code  limit 1)||'"+rmk+"' "+\
                    " where batch_id="+b_id+" and err is null "\
                    " and (select tm from logistics.inventory_stkdetails where "+\
                        "vtype_id="+str(vch_id)+" and company_id="+str(c.id)+\
                        " and label_code=b.label_code limit 1) is not null"
        elif vch_id==1:
            #2020-11-25    酒鬼扫码非实时上传，再次入库可能早于标签退库，先不做重复入库检查            
            s=''
            
            #s="update logistics.inventory_batchdetails b set err='此标签已于'||("+\
            #    "select to_char(tm,'yyyy-mm-dd HH24:MI:SS') from logistics.inventory_stkdetails where "+\
            #        "vtype_id="+str(vch_id)+" and company_id="+str(c.id)+\
            #        " and label_code=b.label_code order by id desc limit 1)||'"+rmk+"' "+\
            #    " where batch_id="+b_id+" and err is null "\
            #    " and (select tm from logistics.inventory_stkdetails where "+\
            #        "vtype_id="+str(vch_id)+" and company_id="+str(c.id)+\
            #        " and label_code=b.label_code limit 1) is not null "+\
            #    " and (select id from logistics.inventory_stkdetails where "+\
            #        "label_code=b.label_code and is_delete=true limit 1) is null"
        if s:
            cur.execute(s)


    #2021-01-16,如果所有标签已有相同物流记录,直接返回,不再写入进出存明细,避免了内参返利重复计算
    if batch.ancestor_id==1644 and is_app:        
        #先不考虑退货后再发货
        s="select count(a.label_code) from "+\
            "(select label_code,company_id,(select vtype_id from inventory_batch where id="+b_id+") vtype_id "+\
                "from inventory_batchdetails where batch_id="+b_id+\
            ") a "+\
            "where a.label_code in (select label_code from inventory_stkdetails where company_id="+str(c.id)+" and vtype_id=a.vtype_id)"  
        cur.execute(s)
        r=cur.fetchone()
        if r[0]==cnt:
            return JsonResponse(data)


    # 写入进出存明细
    #if vch_id == 2:     # 销售出库单
    #2022-01-14
    if vch_id in (2,7):     # 销售出库单 礼品出库
        #sql = "INSERT INTO logistics.inventory_stkdetails (company_to_id,is_delete,dt,label_code,batch_id," + \
        #    "company_id,product_id,store_fr_id,store_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select " + \
        #    str(batch.company_to_id) + "," + d + ",'" + vch_dt + "',label_code,"+b_id+"," + \
        #    str(c.id) + ", product_id," + store + "," + store + ",label_id," + \
        #    "label_pkg,"+str(vch_id)+",label_pk_id,"+str(c.ancestor_id)+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
        #    " and product_id is not null and err is null"
        
        #2021-12-20  云南宝龄富锦生物科技,扫码枪发货不选择产品名称,取其人库时产品名
        sql = "INSERT INTO logistics.inventory_stkdetails (company_to_id,is_delete,dt,label_code,batch_id," + \
            "company_id,product_id,store_fr_id,store_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select " + \
            str(batch.company_to_id) + "," + d + ",'" + vch_dt + "',label_code,"+b_id+"," + \
            str(c.id) + ","+product+"," + store + "," + store + ",label_id," + \
            "label_pkg,"+str(vch_id)+",label_pk_id,"+str(c.ancestor_id)+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
            " and product_id is not null and err is null"
    elif vch_id==3:     # 成品转库
        sql = "INSERT INTO logistics.inventory_stkdetails (is_delete,dt,label_code,batch_id," + \
            "company_id,product_id,store_fr_id,store_id,store_to_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select " + \
            d + ",'" + vch_dt + "',label_code,"+b_id+"," +\
            str(c.id) + "," + product + "," + store_fr + "," +store + "," +  store + ",label_id," + \
            "label_pkg,"+str(vch_id)+",label_pk_id,"+str(c.ancestor_id)+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
            " and " + product + " is not null and " +  store + " is not null" + label_unique + " and err is null"
    
    elif vch_id==5:
        sql = "INSERT INTO logistics.inventory_stkdetails (is_delete,dt,label_code,batch_id," + \
            "company_id,product_id,store_fr_id,store_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select " + \
            "true,'" + vch_dt + "',label_code,"+b_id+"," +\
            str(c.id) + "," + product + "," + store + "," +  store + ",label_id," + \
            "label_pkg,"+str(vch_id)+",label_pk_id,"+str(c.ancestor_id)+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
            " and " + product + " is not null " +  label_unique   + " and err is null"
    elif vch_id==4:
        sql = "INSERT INTO logistics.inventory_stkdetails (is_delete,dt,label_code,batch_id," + \
            "company_id,product_id,store_fr_id,store_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select " + \
            "false,'" + vch_dt + "',label_code,"+b_id+"," +\
            str(c.id) + "," + product + "," + store + "," +  store + ",label_id," + \
            "label_pkg,"+str(vch_id)+",label_pk_id,"+str(c.ancestor_id)+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
            " and " + product + " is not null " +  label_unique   + " and err is null"
    else:
        sql = "INSERT INTO logistics.inventory_stkdetails (is_delete,dt,label_code,batch_id," + \
            "company_id,product_id,store_fr_id,store_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select " + \
            d + ",'" + vch_dt + "',label_code,"+b_id+"," +\
            str(c.id) + ",product_id," + store + "," +  store + ",label_id," + \
            "label_pkg,"+str(vch_id)+",label_pk_id,"+str(c.ancestor_id)+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
            "  and product_id>0 " + label_unique + " and err is null"

    #f=open('d:\\test_update.txt','w')
    #f.write(sql)
    #f.close()


    cur.execute(sql)
    #if rec_cnt == cur.rowcount:
    #2021-01-04
    if rec_cnt >1:
        batch.dt_handled = timezone.now()
        batch.tm_handled = timezone.now()
        batch.save()
    data['cnt'] = cnt
    
    #2021-01-29 酒鬼发货,检查是否发送给透云，改为查表，不再使用SETTINGS里的定义
    #if vch_id==2 and cmp_id==1: 
    #    cur.execute("select "+str(batch.product_id)+" in (select product_id from z_jgty_product)")
    #    r=cur.fetchone()
    #    if r[0]:   
    #        try:
    #            delivery_ty(batch.id,False)
    #        except Exception:
    #            pass

    #入库退标，对原入库标签做删除标记(一箱可能贴2个标签，即入库扫的是一枚标，退库时可能是同一箱的另一枚)
    if vch_id==5:                 
        s="update inventory_stkdetails set is_delete=true where vtype_id=1 and "+\
            "label_pk_id in (select label_pk_id from logistics.inventory_batchdetails where batch_id="+b_id+")"
        cur.execute(s)    
        
        #2020-05-01 酒鬼酒公司:红坛酒退标，删除19.9跳转和奖项记录
        if cmp_id==1 and batch.id in settings.JG_HT_GR:          
            bts=[]
            s="select left(label_code,4) from inventory_stkdetails where batch_id="+b_id+"group by left(label_code,4)"
            cur.execute(s)
            rs00=cur.fetchall()
            for r00 in rs00:
                cur.execute("select code from label.t"+r00[0]+" where package_id=1 and parent_id in  ("+\
                    "select label_pk_id from inventory_stkdetails where batch_id="+b_id+")")
                for r000 in cur.fetchall():
                    bts.append("'"+r000[0]+"'")
            if bts:
                cn_al=pyodbc.connect(settings.CN_AL)  
                cn_xa=pyodbc.connect(settings.CN_XA)
                cur_al=cn_al.cursor()
                cur_xa=cn_xa.cursor()
                #跳转                
                cur_al.execute("delete from TJ_JG_Activity where labelcode in ("+",".join(bts)+")")       
                cn_al.commit()
                #奖项
                cur_xa.execute("delete from  TB_BaseLabelInfo where LabelCode in ("+",".join(bts)+")") 
                cn_xa.commit()

                cur_al.close()
                cn_al.close()
                cur_xa.close()            
                cn_xa.close()   
    elif vch_id==2:     
        #内参发货一级经销商，发货直接作为一级经销商入库
        #if c.id==1644:
        #2020-04-25修改为
        #公司发货一级经销商，发货直接作为一级经销商入库(酒鬼除外）

        #2020-07-17
        cfgs=CompanyCfg.objects.filter(company_id=c.id)
        auto_inbound=False

        #2021-01-19 杨盖:内参有直接发货给二级,不做自动入库
        cur.execute("select level_id from company_company where id="+str(agt_id))
        r=cur.fetchone()
        agt_lv_id=r[0]

        if cfgs:        
            cfg=cfgs[0]
            if agt_lv_id==2:
                if cfg.inbound_auto_lv1:
                    auto_inbound=True  
            elif agt_lv_id==4:
                if cfg.inbound_auto_lv2:
                    auto_inbound=True 

        #酒鬼公司发给内参，发货直接作为内参入库
        if c.id==1 and agt_id==7212:    
            sto=None
            if int(sto_id)==37:
                sto=45
            elif int(sto_id)==47:
                sto=46
            else:
                #默认吉首仓库
                sto=45
            #batch
            b=Batch(vtype_id=1,level_id=1,hierarchy_id=1,version=1,company_id=1644,company_fr_id=1,store_fr_id=sto,
                code=batch.code,product_id=batch.product_id,user_id=int(usr_id),ancestor_id=1644)
            b.save()           
            #batchdetails
            sql="insert into logistics.inventory_batchdetails(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id) "+\
                "select "+str(b.id)+",label_code,label_id,label_pkg,label_pk_id,company_id from logistics.inventory_batchdetails where batch_id="+b_id
            cur.execute(sql)
            
            #stkdetails
            if not sto:
                sto='null'
            else:
                sto=str(sto)
            sql = "INSERT INTO logistics.inventory_stkdetails (dt,label_code,batch_id," + \
                "company_id,product_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id,store_id,store_fr_id) select '" + \
                vch_dt + "',label_code,"+str(b.id)+",1644,"+\
                "coalesce((select nc_id from z_jg_nc_product where jg_id=product_id limit 1),product_id),"+\
                "label_id,label_pkg,1,label_pk_id,1644,"+sto+","+sto+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
                " and label_id is not null"         
            cur.execute(sql)
            b.dt_handled = timezone.now()
            b.tm_handled = timezone.now()
            b.save()   
        elif auto_inbound: 
            #2021-01-19 杨盖:内参有直接发货给二级,不做自动入库           
            if c.id==1644 and agt_lv_id==4:
                pass
            else:
                #batch
                b=Batch(vtype_id=1,level_id=agt_lv_id,hierarchy_id=1,version=1,company_id=int(agt_id),company_fr_id=c.id,code=batch.code,
                    reference_id=batch.id, product_id=batch.product_id,user_id=int(usr_id),ancestor_id=c.ancestor_id)
                b.save()
                #batchdetails
                sql="insert into logistics.inventory_batchdetails(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id,ancestor_id) select "+\
                    str(b.id)+",label_code,label_id,label_pkg,label_pk_id,"+str(agt_id)+",company_id from logistics.inventory_batchdetails where batch_id="+b_id
                cur.execute(sql)
                #stkdetails
                sql = "INSERT INTO logistics.inventory_stkdetails (dt,label_code,batch_id," + \
                    "company_id,product_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select '" + \
                    vch_dt + "',label_code,"+str(b.id)+"," + str(agt_id) + "," + product + ", label_id," + \
                    "label_pkg,1,label_pk_id,"+str(c.ancestor_id)+" from inventory_batchdetails a where batch_id=" + str(b.id) + \
                    " and label_id is not null"         
                cur.execute(sql)
                b.dt_handled = timezone.now()
                b.tm_handled = timezone.now()
                b.save()

        #2020-06-10，取消直营店自动补入库，改为先入库再出库
        #扫码出库时，若直营店未扫码入库，系统补一笔入库 level_id:1,公司；2,平台商，4：终端店（直营店）
        #elif c.level_id>2 and STRICT==False:            
        #    s="select id from inventory_stkdetails a where batch_id="+str(batch.id)+" and (select id from inventory_stkdetails"+\
        #        " where company_id="+str(c.id)+" and vtype_id=1 and label_code=a.label_code) is null limit 1"  
        #    cur.execute(s)
        #    rs_add=cur.fetchone()
        #    if rs_add:  
        #        b=Batch(vtype_id=1,level_id=c.level_id,hierarchy_id=c.hierarchy_id,version=0,company_id=c.id,company_fr_id=c.parent_id,
        #            code=batch.code,product_id=batch.product_id,user_id=int(usr_id),ancestor_id=c.ancestor_id)
        #        b.save()                
        #        a_id=str(c.ancestor_id)
        #        p_id=str(c.parent_id)
        #        c_id=str(c.id)
        #        #batchdetails
        #        sql="insert into inventory_batchdetails(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id,ancestor_id) select "+\
        #            str(b.id)+",label_code,label_id,label_pkg,label_pk_id,"+c_id+","+a_id+" from inventory_batchdetails a "+\
        #            "where batch_id="+b_id+" and (select id from inventory_stkdetails where "+\
        #                " company_id="+c_id+" and vtype_id=1 and label_code=a.label_code) is null"
        #        cur.execute(sql)
        #        #stkdetails
        #        sql = "INSERT INTO logistics.inventory_stkdetails (dt,label_code,batch_id," + \
        #            "company_id,product_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select '" + \
        #            vch_dt+"',label_code,"+str(b.id)+","+c_id+","+product+",label_id,label_pkg,1,label_pk_id,"+a_id+\
        #            " from inventory_batchdetails a where batch_id="+str(b.id)+" and label_id is not null"                             
        #        cur.execute(sql)
        #        b.dt_handled = timezone.now()
        #        b.tm_handled = timezone.now()
        #        b.save()   
        #酒鬼公司发给内参，发货直接作为内参入库
        #elif c.id==1 and agt_id==7212:    
        #    sto=None
        #    if int(sto_id)==37:
        #        sto=45
        #    elif int(sto_id)==47:
        #        sto=46
        #    else:
        #        #默认吉首仓库
        #        sto=45
        #    #batch
        #    b=Batch(vtype_id=1,level_id=1,hierarchy_id=1,version=1,company_id=1644,company_fr_id=1,store_fr_id=sto,
        #        code=batch.code,product_id=batch.product_id,user_id=int(usr_id),ancestor_id=1644)
        #    b.save()           
        #    #batchdetails
        #    sql="insert into logistics.inventory_batchdetails(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id) "+\
        #        "select "+str(b.id)+",label_code,label_id,label_pkg,label_pk_id,company_id from logistics.inventory_batchdetails where batch_id="+b_id
        #    cur.execute(sql)
            
        #    #stkdetails
        #    if not sto:
        #        sto='null'
        #    else:
        #        sto=str(sto)
        #    sql = "INSERT INTO logistics.inventory_stkdetails (dt,label_code,batch_id," + \
        #        "company_id,product_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id,store_id,store_fr_id) select '" + \
        #        vch_dt + "',label_code,"+str(b.id)+",1644,"+\
        #        "coalesce((select nc_id from z_jg_nc_product where jg_id=product_id limit 1),product_id),"+\
        #        "label_id,label_pkg,1,label_pk_id,1644,"+sto+","+sto+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
        #        " and label_id is not null"         
        #    cur.execute(sql)
        #    b.dt_handled = timezone.now()
        #    b.tm_handled = timezone.now()
        #    b.save()   

    
    #2020-09-16 层级返利
    if c.level.sn>0 and is_app:      
        #try:    
            data['rebate']=channel_rebate(batch)            
        #except:
        #    pass
    if batch.ancestor_id == 19257 or batch.ancestor_id == 16687 : 

        if vch_id == 2 and c.level.sn>=1:
            brands_agent_level_update(batch.ancestor_id,batch.company_id)
            sale_task_agent_update(batch.ancestor_id,batch.company_id)

        ssql = ("update company_agentorderbatch set tm_complete = now() where id in ("
                "SELECT id from company_agentorderbatch WHERE batch_code in (SELECT  "
	            "(SELECT code from inventory_batch where id = batch_id) "
	            "FROM inventory_stkdetails WHERE "
            	"label_code in (SELECT label_code from inventory_stkdetails where batch_id = "+b_id+") )"
                "and tm_complete is null)")
        cur.execute(ssql)


    
    return JsonResponse(data) 













#2021-03-31
@csrf_exempt
def fg_update(request,is_app=False):
    """
    新物流系统，产成品入库，出库处理
    :param request: json
    :return: json
    """
    data = {'e': '', 'cnt': 0, 'rebate':{'promotion_id':0}}
    k = sK
    r = json.loads(request.body)
    e = time_key_check(request, k)
    
    if e:
        data['e'] = e
        return JsonResponse(data)
    keys = ['bill_number', 'user_id', 'company_id', 'voucher_id', 'voucher_time']
    
    
    #for k in keys:
    #    if k not in keys:
    #        data['e'] = _('缺少参数') + k
    #        return JsonResponse(data)
    
    """单据类别：voucher id
    1;"成品入库单";"GRN";1
    2;"销售出库单";"GDN";-1
    3;"成品转库单";"GTN";0
    4;"销售退库单";"GWN";1
    5;"入库单退库";"GCN";-1
    """
    # 必传：单号，用户ID，公司ID, 单据类别ID, 单据生成时间
    code = r['bill_number']
    # hdh+"|" + yyyyMMddHHmmss  比如：8785454567|20190528220956  |号前是交货单号，后面是一个年月日时分秒的虚拟单号
    code = code.split('|')[0]

    usr_id = int(r['user_id'])
    cmp_id = int(r['company_id'])
    vch_id = int(r['voucher_id'])

    
    
    #2020-10-30
    qc=None
    if 'qc' in r:
        qc=r['qc']
    #生产批次号/批次号
    batch_no=None
    if 'batch_no' in r:        
        batch_no=r['batch_no']
    else:
        if vch_id==1:
            batch_no=code    

    #2022-04-27  有些发货数据可能从OS等系统导出的，单据日期时间重要    
    tm_crucial=False
    tm0=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")    
    if 'time_is_crucial' in r:
        if r['time_is_crucial']:
            if 'voucher_time' in r:        
                tm0 = r['voucher_time']
                tm_crucial=True
    dt0 = tm0[:10]
    vch_dt=dt0
    

   
    
    # 2022-07-20 数据写入日志
    cs = Company.objects.filter(id=int(cmp_id))
    if not cs:
        data['e']="company id error"
        return JsonResponse(data)
    c=cs[0]
    try:
        cid=str(c.id)+"_"+c.name
        s = request.body.decode('utf8')   
        pth="F:\\hzy\\log\\inventory_update\\"
        dt=datetime.datetime.now().strftime('%Y-%m-%d')
        if not os.path.exists(pth+dt):
            os.mkdir(pth+dt)        
        fn=cid+".txt"
        f=open(pth+dt+'\\'+fn,'a',encoding='utf-8')
        f.write(s+'\n-------------------------------------------------------\n')
        f.close()
    except Exception:
        pass


    #2022-06-14
    c_parent_id=str(c.parent_id)

    #2021-04-03
    cfg=None

    #2021-07-09
    bDuplication_inboud=False
    cfgs=CompanyCfg.objects.filter(company_id=c.ancestor_id) 
    if cfgs:
        cfg=cfgs[0]
        if c.level_id==1:
            if cfg.duplication_inbound_company:            
                bDuplication_inboud=True
        else:
            if cfg.duplication_inbound_agent:            
                bDuplication_inboud=True



    #2020-08-29 是否强制发货
    force=False
    if 'force' in r:
        force=r['force']
    if cmp_id==1:   #酒鬼有大量销售退库
        force=True
    elif cfg:
        if c.level_id==2:
            if vch_id==2 and cfg.duplication_outbound_agent==1:
                force=True
        elif c.level_id==1:
            if vch_id==2 and cfg.duplication_outbound_company==1:
                force=True

    #2021-03-31
    is_stack=False
    if 'is_stack' in r:
        is_stack=r['is_stack']


    cur = connection.cursor()
    



    voucher = Voucher.objects.get(id=int(vch_id))    
    #m = apps.get_model('inventory', voucher.code)
    batch = Batch()    
    batch.code = code    


    # 2022-07-20 
    ref_id=None 
    if 'ref_id' in r:
        ref_id=r['ref_id']
    batch.reference_id=ref_id

    
    #2021-04-17 业务员登录：换货    
    #2021-12-27                     
    #20;"GXN";"下级换货单";0;"下级换货"
    #9;"GXI";"换货入库";1;"换货入库"  
    #10;"GXO";"换货出库";-1;"换货出库" 
    if vch_id==20:        
        from_agent_id=int(r['from_agent_id'])
        to_agent_id=int(r['to_agent_id'])
        c=Company.objects.get(id=to_agent_id)      
        batch.company_id=to_agent_id        
        batch.company_fr_id =from_agent_id
        batch.company_to_id=to_agent_id
    else:
        batch.company_id=c.id
        batch.company_fr_id = c.id    
    
    #暂不修改
    batch.level_id=c.level_id
    
    batch.hierarchy_id=c.hierarchy_id
    batch.version=c.version   
    batch.user_id = int(usr_id)   
    batch.ancestor_id=c.ancestor_id

    #2022-04-27 使用前端传过来的单据时间
    #if tm_crucial:
    #    batch.dt=dt0
    #    batch.tm=tm0
    
    #2020-10-30
    batch.qc_name=qc
    batch.batch_no=batch_no
    #2021-01-05
    if 'order_sn' in r:
        batch.order_sn=r['order_sn']
    #2021-01-29
    if 'recommender_id' in r:
        if r['recommender_id']:
            batch.recommender_id=int(r['recommender_id'])

    #2020-09-17       
    if 'lnglat_start' in r:
        batch.lnglat_start=r['lnglat_start']
    if 'lnglat_end' in r:
        batch.lnglat_end=r['lnglat_end']
    if 'distance' in r:
        batch.distance=r['distance']
    if 'storegeo_id' in r:
        batch.storegeo_id=r['storegeo_id']
    # 终端店订单 
    if 'agent_order_number' in r:        
        agent_order_number=r['agent_order_number']
        cur.execute("update company_agentorderbatch set batch_code = '"+code+"' where code = '"+agent_order_number+"' ")
    #2021-03-03
    if 'ticket_id' in r:                #销售启票id
        batch.outbound_ticket_id=int(r['ticket_id'])    
    if 'bill_number2' in r:             #入库 启票id
        if r['bill_number2'].isdigit():
            batch.inbound_ticket_id=int(r['bill_number2'])   



    #2021-11-13
    #dn_id=models.IntegerField(_('发货单/拣配单_ID'),blank=True,null=True)
    #dn_number=models.CharField(_('发货单/拣配单_编号'),blank=True,null=True,max_length=20)
    #salesorder_id=models.IntegerField(_('销售订单_ID'),blank=True,null=True)
    #salesorder_code=models.CharField(_('销售订单_编码'),blank=True,null=True,max_length=20)
    #salesorder_type_id=models.IntegerField(_('销售订单类型_ID'),blank=True,null=True)
    #salesorder_type_code=models.CharField(_('销售订单类型_编码'),blank=True,null=True,max_length=20)
    
    if 'dn_number' in r:
        batch.dn_number=r['dn_number']
    if 'order_number' in r:
        batch.salesorder_code=r['order_number']

        cur.execute("select id from erp_salesorder where company_id="+str(c.id)+" and code='"+r['order_number']+"'")
        ro=cur.fetchone()
        if ro:
            batch.salesorder_id=ro[0] 
    if 'ordertype_code' in r:
        batch.salesorder_type_code=r['ordertype_code']
        
        cur.execute("select id from erp_ordertype where company_id="+str(c.id)+" and  code='"+r['ordertype_code']+"'")
        rt=cur.fetchone()
        if rt:
            batch.salesorder_type_id=rt[0]
   
    # 写入到delivery
    prd_id = 'null'
    sto_id = 'null'
    agt_id = 'null'

    # 成品入库，号码唯一
    label_unique=''
    batch.voucher_id = voucher.id     
    #2021-12-27
    if vch_id==20:
        batch.vtype_id=9                    #先将单据转为入库方单据   
    else:
        batch.vtype_id=int(vch_id)   
   
    #2021-04-01
    if 'stacks' in r:
        batch.stacks=r['stacks']
    


    #2022-04-16 产品年份/库龄/采摘日期
    if 'product_aging' in r:
        if r['product_aging']:
            batch.product_aging=r['product_aging']
    #众茶国际，入库，指定茶叶供应商ID
    if 'vendor_id' in r:
        if r['vendor_id']:
            batch.vendor_id=int(r['vendor_id'])



    #2020-05-30
    STRICT=True         #直营店要扫码入库
    if vch_dt[:7]=='2020-06' and c.ancestor_id==1644:
        STRICT=False    #扫码出库时，若直营店未扫码入库，系统补一笔入库  

    # 有没有传产品ID；转库有没有from_store_id
    store_fr_id_o = 0
    if 'from_store_id' in r:
        store_fr_id_o = int(r['from_store_id'])
        if vch_id == 3 and store_fr_id_o:            
            batch.store_fr_id = store_fr_id_o
    product_id_o = None
    if 'product_id' in r:
        if int(r['product_id'])>0:
            product_id_o=int(r['product_id'])    

          
    batch.product_id = product_id_o
    if vch_id == 1:         # 产成品入库
        # 成品入库，号码唯一
        #label_unique=" and (select id from logistics.inventory_stkdetails " + \
        #             "where voucher_type='grn' and label_code=a.label_code and company_id=" + str(c.id) + " ) is null"        
        if 'store_id' in r: 
            sto_id = int(r['store_id'])   
            if sto_id>0:
                batch.store_fr_id = sto_id        
        if 'qc_id' in r:           
            batch.qc_id = int(r['qc_id'])
        if 'batch_no' in r:           
            batch.batch_no = r['batch_no']

        #if c.has_plant:      
        #2020-04-21 超鹏把plant_id写死了，使用的是gongchang_id
        if 'gongchang_id' in r:
            if r['gongchang_id']:
                if int(r['gongchang_id']):
                    batch.prd_plant_id = int(r['gongchang_id'])
        else:
            if 'plant_id' in r:
                if r['plant_id']:
                    batch.prd_plant_id = int(r['plant_id'])     

        #if c.has_workshop: 
        if 'workshop_id' in r:
            if r['workshop_id']:
                batch.prd_workshop_id = int(r['workshop_id'])

        if 'workline_id' in r:     
            if r['workline_id']:
                batch.prd_line_id = r['workline_id']
        #2022-01-04
        if 'prdshop_id' in r:
            if r['prdshop_id']:
                batch.prd_workshop_id=int(r['prdshop_id'])
        if 'prdline_id' in r:
            if r['prdline_id']:
                batch.prd_line_id=int(r['prdline_id'])
        if 'prdteam_id' in r:
            if r['prdteam_id']:
                batch.prd_team_id=int(r['prdteam_id'])
    #elif vch_id == 2:       # 销售出库
    #2022-01-14
    elif vch_id in  (2,7):       # 销售出库 礼品出库
        #如百得信,经销商也用扫描枪发货
        if 'store_id' in r: 
            sto_id = int(r['store_id'])   
            if sto_id>0:
                batch.store_fr_id = sto_id
        agt_id = r['to_company_id']       
        batch.company_to_id = int(agt_id)
        #2020-05-28 微信小程序，销售出库给团购，①单位名称，②姓名，③电话。        
        if is_app and int(agt_id)==11014:  
            batch.customer_company=r['company']                 
            batch.customer_name=r['name']                 
            batch.customer_phone=r['phone']
    elif vch_id == 3:       # 转库
        if 'store_id' in r: 
            sto_id = int(r['store_id'])   
            if sto_id>0:
                batch.store_to_id = sto_id
    elif vch_id == 4:       # 销售退库    
        if 'store_id' in r:    
            sto_id = int(r['store_id']) 
            if sto_id>0:
                batch.store_fr_id = sto_id               
    elif vch_id == 5:       # 标签退库
        if 'store_id' in r:  
            batch.store_fr_id = int(r['store_id'])
    
    if not batch.store_fr_id:
        batch.store_fr_id=None
    batch.save()
    b_id = str(batch.id)    
    codes = r['codes']
    rec_cnt = len(codes)
    a = []    
    #2021-04-01    
    cur.execute("create temp table codes("+\
        "label_code character varying(20),"+\
        "tb character varying(20),"+\
        "product_id integer,"+\
        "stack_id integer,"+\
        "wrapper_id integer,"+\
        "code character varying(20),"+\
        "label_id bigint,"+\
        "label_pk_id bigint,"+\
        "label_pkg smallint,"+\
        "err character varying(100),"+\
        "label_code0 character varying(20),"+\
        "from_agent_id integer)"
    )
    
    #2022-02-25 
    fws=[] #保存防伪码
    for code in codes:
        #物流终端发货CODES
        #codes: [{code: 123456789012,  err_code: 1,  e: "错误信息1"}]
        if is_app:  
            e='null'
            pid='null'
            #if code['product_id']:
            if 'product_id' in code:
                if int(code['product_id'])>0:
                    pid=str(code['product_id'])   
            elif batch.product_id:
                pid=str(batch.product_id)
            if code['e']:
                e="'"+code['e'][:100]+"'"            
            #退货来源经销商
            from_agent_id='null'
            if 'from_agent_id' in code:
                if code['from_agent_id']:
                    from_agent_id=str(code['from_agent_id'])
                    
            if from_agent_id == 'null':
                rr = cur.execute(f"select company_id from inventory_stkdetails where label_code = '{code['code']}' and vtype_id = 1 ORDER BY id desc LIMIT 1 ")
                
                if rr:
                    from_agent_id = rr[0]
            a.append("('"+code['code']+"','"+code['code'][:4]+"',"+e+","+pid+","+from_agent_id+")")
        else:  
            #退货来源经销商
            from_agent_id='null'
            
            
            if vch_id == 4 and batch.company_id == 19257:
                rr = cur.execute(f"select company_id from inventory_stkdetails where label_code = '{str(code)}' and vtype_id = 1 ORDER BY id desc LIMIT 1 ")
                rr = cur.fetchone()
                if rr:
                    from_agent_id = str(rr[0])
                 
            if batch.product_id:
                a.append("('" + code + "','" + code[:4] + "',"+str(batch.product_id)+","+from_agent_id+")")
            else:
                a.append("('" + code + "','" + code[:4] + "',null,"+from_agent_id+")")
            #sSql="insert into codes (label_code,tb,product_id) values " + ",".join(a)   
            #2022-02-25
            if cmp_id in [1,1644] and code[0]=='4' and {'id':1,'label':code} not in fws:  #酒鬼和内参，二维码是防伪码的情况,号段4000
                fws.append({'id':1,'label':code})


    #2021-04-02 这里改进,判断数组 a
    if is_app:
        #sSql="insert into codes (label_code,tb,err,product_id) values "
        sSql="insert into codes (label_code,tb,err,product_id,from_agent_id) values "
    else:
        sSql="insert into codes (label_code,tb,product_id,from_agent_id) values "
    if a:
        cur.execute(sSql+",".join(a))
    
    
    
    stacks=[]
    if 'stacks' in r:
        st=r['stacks']
        if len(st)>0:
            stacks=r['stacks']
    if stacks and vch_id==1:
        aSql=stack_inbound_codes_sql(batch,r['stacks'])
        if aSql:           
            sSql="insert into codes(label_code,tb,product_id,stack_id) values "+",".join(aSql) 
            cur.execute(sSql)



    #2022-05-10 保存原始标签号码
    cur.execute("update codes set label_code0=label_code")         
        

    #2022-02-25 防伪码转物流码
    if fws:       
        cur.execute("create temp table fg_fw("+\
            "fw character varying(20),"+\
            "wl character varying(20)"+\
            ")"
        )
        tm=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        m2=hashlib.md5((settings.INTERNAL_SK+tm).encode('utf8'))
        key=m2.hexdigest()
        r = requests.post(settings.INTERNAL_URL + '/wl/', json={'key': key, 'time': tm, 'labels': fws})
        if r.status_code == 200:
            d = json.loads(r.text)
            a = []            
            for cc in d['data']:
                if cc['code']:
                    a.append("('" + cc['label'] + "','" + cc['code'] + "')")
            if a:
                cur.execute("insert into fg_fw(fw,wl) values " + ",".join(a))            
                #物流码替换防伪码   
                s="update codes o set  "+\
                    "label_code=coalesce(f.wl,c.label_code),"+\
                    "code=coalesce(f.wl,c.label_code),"+\
                    "tb=left(coalesce(f.wl,c.label_code),4) "+\
                    "from "+\
                    "(select tb,label_code,code from codes) c "+\
                    "left outer join "+\
                    "(select fw,wl from fg_fw) f "+\
                    "on c.label_code=f.fw "+\
                    "where o.label_code=c.label_code"                    
                cur.execute(s)        

    #处理标签替换 2021-09-18 
    s="update codes o set code=coalesce"+\
        "((select code0 from label.lbl_replace_details where code=o.label_code order by batch_id desc limit 1),o.label_code)"
    cur.execute(s)    

    

    #2020-07-27 处理跨段动态绑定
    s="update codes set tb=b.tbname from "+\
        "(SELECT tb,label_code from codes) a "+\
        "left outer join "+\
        "(SELECT segment, tbname FROM label.lbl_tbcross) b "+\
        "on a.tb=b.segment "+\
        "where  codes.label_code=a.label_code and b.tbname is not null"
    cur.execute(s)


    #2020-12-18 处理AB标,
    #cur.execute("select code_a FROM label.lbl_abcode where code_b='"+code+"'")
    #s="update codes set code="+\
    #    "coalesce((select code_a FROM label.lbl_abcode where code_b=label_code),code)"
    #2022-05-09 有些AB样标使用了跨段表里的号段 
    s="select "+\
        "(select code_a FROM label.lbl_abcode where code_b=label_code or code_a=label_code),"+\
        "tb='t'||left((select code_a FROM label.lbl_abcode where code_b=label_code or code_a=label_code),4) "+\
        "from codes "+\
        "where (select id from label.lbl_abcode where code_a=label_code or code_b=label_code limit 1)>0"
    cur.execute(s)
    r=cur.fetchone()  

    s="update codes set code="+\
        "(select code_a FROM label.lbl_abcode where code_b=label_code or code_a=label_code),"+\
        "tb='t'||left((select code_a FROM label.lbl_abcode where code_b=label_code or code_a=label_code),4) "+\
        "where (select id from label.lbl_abcode where code_a=label_code or code_b=label_code limit 1)>0"
    cur.execute(s) 


    cur.execute("update codes set tb='t'||left(code,4) where length(tb)=4")       


    cur.execute("select tb from codes group by tb")
    rs = cur.fetchall()
    for r in rs:  
        #cur.execute("select to_regclass('label." + r[0] + "')")
        cur.execute("select count(*) from information_schema.tables where table_schema='label' "+\
            "and table_type='BASE TABLE' and  table_name='" + r[0]+"'"
        )            
        r0 = cur.fetchone()        
        if r0[0]:            
            s="update codes set "+\
                "label_id=b.id,"+\
                "label_pkg=b.package_id,"+\
                "label_pk_id=coalesce(b.parent_id,b.id) "+\
                "from "+\
                "(SELECT label_code,code from codes where tb='"+r[0]+"') a "+\
                "left outer join "+\
                "(select id,code,parent_id,package_id,is_pk from label."+r[0]+") b "+\
                "on a.code=b.code "+\
                "where tb='"+r[0]+"' and codes.code=a.code"
            cur.execute(s)   

    #2021-11-29
    #没有标签id的，看是不是企业第三方标签
    s="update codes set "+\
        "label_id=b.id,"+\
        "label_pkg=b.package_id,"+\
        "label_pk_id=coalesce(b.parent_id,b.id) "+\
        "from "+\
        "(SELECT label_code,code from codes where label_id is null) a "+\
        "left outer join "+\
        "(select id,code,parent_id,package_id,is_pk from label.thirdparty where cid="+str(c.ancestor_id)+") b "+\
        "on a.code=b.code "+\
        "where codes.code=a.code and label_id is null"
    cur.execute(s)  

    #2021-12-27 下级转库单，更新from_agent_id
    if vch_id==20:
        cur.execute("update codes set from_agent_id="+str(batch.company_fr_id))
   
   
    #2022-01-14 产品名称
    if cfg.product_depend_on==1:
        #以入库时产品名称优先
        s="update codes c set product_id=coalesce("+\
            "(select product_id from inventory_stkdetails where vtype_id=1 and label_pk_id=c.label_pk_id and is_delete=false order by id desc limit 1),product_id)"     
        try:
            cur.execute(s)
        except Exception:
            pass


    #2022-04-16
    #处理包码数据 20;"外包码";"按包发货，如众茶国际，1包100套"
    cur.execute("select label_code from codes where label_pkg=20 group by label_code")
    rs=cur.fetchall()
    if rs:
        wrapper_codes=[]
        wrappers=[]
        for r in rs:            
            wrappers.append(r[0])
            wrapper_codes.append("'"+r[0]+"'")
        batch.wrappers=wrappers
        pid='null'
        if product_id_o:
            pid=str(product_id_o)
        s="insert into codes(label_code,tb,product_id,wrapper_id,label_pk_id,label_id,label_pkg) select "+\
            "label_code,'t'||left(label_code,4),"+pid+","+\
            "id,label_pk_id,label_id,label_pkg "+\
            "from label.lbl_overwrap "+\
            "where label_wrapper in ("+",".join(wrapper_codes)+")"
        cur.execute(s)


    #2022-04-16 临时表删除包码
    cur.execute("delete from codes where label_pkg=20")   

    #2022-05-11 保留原数据，不做任何修改,用以说明扫码人员扫码质量
    s="insert into logistics.inventory_batchdetails(batch_id,label_code,label_id,label_pkg,tm,label_pk_id,company_id,ancestor_id,err,product_id,stack_id,from_agent_id,wrapper_id,label_code0) " +\
        "select "+str(batch.id)+",label_code,label_id,label_pkg,now(),label_pk_id,"+str(c.id)+","+str(c.ancestor_id)+",err,product_id,stack_id,from_agent_id,wrapper_id,label_code0 from codes" 
    cur.execute(s)
    cnt = cur.rowcount 


    store_fr = "null"
    d = 'false'
    if product_id_o:
        product = str(product_id_o)
    else:        
        product = "(select product_id from logistics.inventory_stkdetails where vtype_id in (1,2) " + \
            "and ancestor_id="+str(c.ancestor_id)+" and label_pk_id=a.label_pk_id and product_id is not null order by id desc limit 1)"  
    if vch_id == 5:     # 标签退库
        d = "true"
        store = "(select store_id from logistics.inventory_stkdetails where voucher_type='grn' " + \
            "and  label_code=a.label_code and store_id is not null order by id desc limit 1)"
    elif vch_id == 3:    # 成品转库
        store = str(batch.store_to_id)        
        store_fr = "coalesce(" + str(store_fr_id_o) + "," + \
                "(select store_id from logistics.inventory_stkdetails where voucher_type='gtn' " + \
                "and  label_code=a.label_code and store_id is not null order by id desc limit 1)," + \
                "(select store_id from logistics.inventory_stkdetails where voucher_type='grn' " + \
                "and  label_code=a.label_code and store_id is not null order by id desc limit 1))" 
    else:
        if batch.store_fr_id:
            store = str(batch.store_fr_id)
        else:
            store='null'     

    #2021-04-01
    if stacks and vch_id==2:
        #s="insert into inventory_batchdetails(batch_id,label_code,label_id,label_pkg,tm,label_pk_id,company_id,ancestor_id,err,product_id,stack_id) " +\
        #    "select "+str(batch.id)+",label_code,label_id,label_pkg,now(),label_pk_id,"+str(c.id)+","+str(c.ancestor_id)+",null,product_id,stack_id from inventory_stackdetails s "+\
        #    "where stack_id in (select id from inventory_stack s where code in ('"+"','".join(stacks)+"')) "+\
        #    "and (select id from inventory_batchdetails where batch_id="+str(batch.id)+" and label_id=s.label_id limit 1) is null"
        #cur.execute(s)

        #2022-07-02 如诗仙太白含垛标的套标，出库时可能没做入库，即垛标没有产品id,取当前的batch产品id
        pid='null'
        if batch.product_id:
            pid=str(batch.product_id)
        s="insert into inventory_batchdetails(batch_id,label_code,label_id,label_pkg,tm,label_pk_id,company_id,ancestor_id,err,product_id,stack_id) " +\
            "select "+str(batch.id)+",label_code,label_id,label_pkg,now(),label_pk_id,"+str(c.id)+","+str(c.ancestor_id)+",null,"+\
            "coalesce(product_id,"+pid+"),stack_id from inventory_stackdetails s "+\
            "where stack_id in (select id from inventory_stack s where code in ('"+"','".join(stacks)+"')) "+\
            "and (select id from inventory_batchdetails where batch_id="+str(batch.id)+" and label_id=s.label_id limit 1) is null"      
        
        cur.execute(s)
        cnt=cnt+cur.rowcount

    cur.execute("update logistics.inventory_batchdetails set err='标签错误'  where batch_id="+b_id+" and label_id is null")
    



    #2022-05-11
    #当前扫码记录里，同一箱扫了顶标又扫侧标；扫了防伪码又扫物流码；扫了A标又扫B标；或同一码扫了多次 
    #标记重复箱码
    s="update inventory_batchdetails d set err='号码重复' from ("+\
            "select min(id) id,label_pk_id from inventory_batchdetails where batch_id="+b_id+" "+\
            "and label_pkg=3 group by label_pk_id"+\
        ") u "+\
        "where batch_id="+b_id+" and d.label_pkg=3 "+\
        "and d.label_pk_id=u.label_pk_id and d.id<>u.id"
    cur.execute(s)
    #标记重复瓶码
    s="update inventory_batchdetails d set err='号码重复' from ("+\
            "select min(id) id,label_id from inventory_batchdetails where batch_id="+b_id+" "+\
            "group by label_id"+\
        ") u "+\
        "where batch_id="+b_id+" and d.label_pkg=1 "+\
        "and d.label_id=u.label_id and d.id<>u.id"
    cur.execute(s)




    
    #2020-11-09,内参小程序新模式：扫了瓶标，可以扫箱标，置换出瓶标(数据检查已在小程序端完成)    
    if batch.ancestor_id==1644 and is_app:
        pass
    elif vch_id in [1,2,7]:        
        rmk=voucher.remark  
        s=''
        #if vch_id==2:
        #2022-01-14
        if vch_id in (2,7):
            if not force:  
                #2022-02-16 最后一条是退货的标签可以出库
                s="update logistics.inventory_batchdetails b set err='此标签已于'||("+\
                    "select to_char(tm,'yyyy-mm-dd HH24:MI:SS') from logistics.inventory_stkdetails where "+\
                        "vtype_id="+str(vch_id)+" and company_id="+str(c.id)+\
                        " and label_code=b.label_code order by id desc limit 1)||'"+rmk+"' "+\
                    " where batch_id="+b_id+" and err is null and "\
                    "coalesce((select max(id) from logistics.inventory_stkdetails where vtype_id="+str(vch_id)+\
                        " and company_id="+str(c.id)+" and label_code=b.label_code),0)"+\
                    ">coalesce("+\
                    "(select max(id) from logistics.inventory_stkdetails where vtype_id=4 "+\
                        " and company_id="+str(c.id)+" and label_code=b.label_code),0)"                
        elif vch_id==1:
            #2020-11-25    酒鬼扫码非实时上传，再次入库可能早于标签退库，先不做重复入库检查   
            #2021-07-09 是否允许重复入库，由cfg控制
            if not bDuplication_inboud:   
                #扫了同一个箱码,一箱上的两个箱码，或箱上的A标和B标
                #s="update logistics.inventory_batchdetails b set err='此标签已于'||("+\
                #        "select to_char(tm,'yyyy-mm-dd HH24:MI:SS') from logistics.inventory_stkdetails where "+\
                #        "vtype_id="+str(vch_id)+" and company_id="+str(c.id)+\
                #        " and label_id=b.label_id order by id desc limit 1)||'"+rmk+"' "+\
                #    " where batch_id="+b_id+" and err is null "\
                #    " and (select tm from logistics.inventory_stkdetails where "+\
                #        "vtype_id="+str(vch_id)+" and company_id="+str(c.id)+\
                #        " and label_id=b.label_id and is_delete=false limit 1) is not null "
                
                # 2022-07-25 # 酒鬼现在做法：先产线扫箱码，再做一遍标签扫码入库，防止遗漏。要求第二次的扫码，如果是同一箱另一个标签，也不写入入库明细                
                s="update logistics.inventory_batchdetails b set err='此标签已于'||("+\
                        "select to_char(tm,'yyyy-mm-dd HH24:MI:SS') from logistics.inventory_stkdetails where "+\
                        "vtype_id="+str(vch_id)+" and company_id="+str(c.id)+\
                        " and is_delete=false and label_pk_id=b.label_pk_id "+\
                        " order by id desc limit 1)||'"+rmk+"' "+\
                    " where batch_id="+b_id+" and err is null "\
                    " and (select tm from logistics.inventory_stkdetails where "+\
                        "vtype_id="+str(vch_id)+" and company_id="+str(c.id)+\
                        " and label_pk_id=b.label_pk_id and is_delete=false limit 1) is not null "
                                    
        if s:
            cur.execute(s)


    #2021-01-16,如果所有标签已有相同物流记录,直接返回,不再写入进出存明细,避免了内参返利重复计算
    if batch.ancestor_id==1644 and is_app:        
        #先不考虑退货后再发货
        s="select count(a.label_code) from "+\
            "(select label_code,company_id,(select vtype_id from inventory_batch where id="+b_id+") vtype_id "+\
                "from inventory_batchdetails where batch_id="+b_id+\
            ") a "+\
            "where a.label_code in (select label_code from inventory_stkdetails where company_id="+str(c.id)+" and vtype_id=a.vtype_id)"  
        cur.execute(s)
        r=cur.fetchone()
        if r[0]==cnt:
            return JsonResponse(data)


    # 写入进出存明细
    #if vch_id == 2:     # 销售出库单
    #2022-01-14
    elif vch_id in  (2,7):       # 销售出库 礼品出库
        sql = "INSERT INTO logistics.inventory_stkdetails(company_to_id,is_delete,dt,label_code,batch_id,stack_id," + \
            "company_id,product_id,store_fr_id,store_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select " + \
            str(batch.company_to_id) + "," + d + ",'" + vch_dt + "',label_code,"+b_id+",stack_id," + \
            str(c.id) + ", product_id," + store + "," + store + ",label_id," + \
            "label_pkg,"+str(vch_id)+",label_pk_id,"+str(c.ancestor_id)+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
            " and product_id is not null and err is null"
    elif vch_id==3:     # 成品转库
        sql = "INSERT INTO logistics.inventory_stkdetails (is_delete,dt,label_code,batch_id," + \
            "company_id,product_id,store_fr_id,store_id,store_to_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select " + \
            d + ",'" + vch_dt + "',label_code,"+b_id+"," +\
            str(c.id) + "," + product + "," + store_fr + "," +store + "," +  store + ",label_id," + \
            "label_pkg,"+str(vch_id)+",label_pk_id,"+str(c.ancestor_id)+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
            " and " + product + " is not null and " +  store + " is not null" + label_unique + " and err is null"
    
    elif vch_id==5:
        sql = "INSERT INTO logistics.inventory_stkdetails (is_delete,dt,label_code,batch_id," + \
            "company_id,product_id,store_fr_id,store_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select " + \
            "true,'" + vch_dt + "',label_code,"+b_id+"," +\
            str(c.id) + "," + product + "," + store + "," +  store + ",label_id," + \
            "label_pkg,"+str(vch_id)+",label_pk_id,"+str(c.ancestor_id)+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
            " and " + product + " is not null " +  label_unique   + " and err is null"
     #2021-12-27 下级换货单 换货入库方明细也写入来源方ID 
    elif vch_id in (4,20):   
        sql = "INSERT INTO logistics.inventory_stkdetails (is_delete,dt,label_code,batch_id," + \
            "company_id,product_id,store_fr_id,store_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id,from_agent_id) select " + \
            "false,'" + vch_dt + "',label_code,"+b_id+"," +\
            str(c.id) + "," + product + "," + store + "," +  store + ",label_id," + \
            "label_pkg,"+str(batch.vtype_id)+",label_pk_id,"+str(c.ancestor_id)+",from_agent_id from logistics.inventory_batchdetails a where batch_id=" + b_id + \
            " and " + product + " is not null " +  label_unique   + " and err is null"
    else:
        sql = "INSERT INTO logistics.inventory_stkdetails(is_delete,dt,label_code,batch_id,stack_id," + \
            "company_id,product_id,store_fr_id,store_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select " + \
            d + ",'" + vch_dt + "',label_code,"+b_id+",stack_id," +\
            str(c.id) + ",product_id," + store + "," +  store + ",label_id," + \
            "label_pkg,"+str(vch_id)+",label_pk_id,"+str(c.ancestor_id)+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
            "  and product_id>0 " + label_unique + " and err is null"

    #f=open('d:\\test_update.txt','w')
    #f.write(sql)
    #f.close()


    cur.execute(sql)
    #if rec_cnt == cur.rowcount:
    #2021-01-04
    if rec_cnt >1:
        batch.dt_handled = timezone.now()
        batch.tm_handled = timezone.now()
        batch.save()
    data['cnt'] = cnt
    
    
    #if vch_id==2:
    #2022-01-14
    
    if vch_id in (2,7):
        if cmp_id==1 and vch_id==2: 
            #2021-01-29 酒鬼发货,检查是否发送给透云，改为查表，不再使用SETTINGS里的定义
            agent_id=batch.company_to_id
            #2021-08-28 
            #s='select products @> '+"'"+'[{"id":"'+str(batch.product_id)+'"}]'+"',"+\
            #    'agents @> '+"'"+'[{"id":"'+str(agent_id)+'"}]'+"' "+\
            #    "from thirdparty_vendor where company_id=1 and code='HD'"             
            
            # 2022-07-15 
            s='select products @> '+"'"+'[{"id":"'+str(batch.product_id)+'"}]'+"',"+\
                'agents @> '+"'"+'[{"id":"'+str(agent_id)+'"}]'+"' "+\
                "from thirdparty_redirect where company_id=1 and code='HD'" 

           
            

            cur.execute(s)
            r=cur.fetchone() 
            
            

            if r: 
                if r[0]:  
                    tm=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')      
                    
                    if tm>'2021-12-01 00:00:00':      
                        #异步任务服务器发送 汉得
                        result=tasks.post_hand.delay({
                            'batch':{'id':batch.id,'code':batch.code},
                            'actions':['relations','delivery']
                        })
        elif cmp_id==1644:
            # nc_sm_test 扫码测试
            if usr_id!=12962:
                #内参，异步任务服务器发送 博智
                result=tasks.post_bz.delay({
                    'batch':{'id':batch.id,'code':batch.code},
                    'actions':['delivery']
                })
                       
    #入库退标，对原入库标签做删除标记(一箱可能贴2个标签，即入库扫的是一枚标，退库时可能是同一箱的另一枚)
    elif vch_id==5:                 
        s="update inventory_stkdetails set is_delete=true where vtype_id=1 and "+\
            "label_pk_id in (select label_pk_id from logistics.inventory_batchdetails where batch_id="+b_id+")"
        cur.execute(s)    
        

        '''
        #2020-05-01 酒鬼酒公司:红坛酒退标，删除19.9跳转和奖项记录
        if cmp_id==1 and batch.id in settings.JG_HT_GR:          
            bts=[]
            s="select left(label_code,4) from inventory_stkdetails where batch_id="+b_id+"group by left(label_code,4)"
            cur.execute(s)
            rs00=cur.fetchall()
            for r00 in rs00:
                cur.execute("select code from label.t"+r00[0]+" where package_id=1 and parent_id in  ("+\
                    "select label_pk_id from inventory_stkdetails where batch_id="+b_id+")")
                for r000 in cur.fetchall():
                    bts.append("'"+r000[0]+"'")
            if bts:
                cn_al=pyodbc.connect(settings.CN_AL)  
                cn_xa=pyodbc.connect(settings.CN_XA)
                cur_al=cn_al.cursor()
                cur_xa=cn_xa.cursor()
                #跳转                
                cur_al.execute("delete from TJ_JG_Activity where labelcode in ("+",".join(bts)+")")       
                cn_al.commit()
                #奖项
                cur_xa.execute("delete from  TB_BaseLabelInfo where LabelCode in ("+",".join(bts)+")") 
                cn_xa.commit()

                cur_al.close()
                cn_al.close()
                cur_xa.close()            
                cn_xa.close()
        '''

    #2021-12-20 销售退库
    elif vch_id==4:
        if c.id==1: #酒鬼销售退库发送给汉得
            s='select products @> '+"'"+'[{"id":"'+str(batch.product_id)+'"}]'+"' "+\
                "from thirdparty_vendor where company_id=1 and code='HD'"   
            cur.execute(s)
            r=cur.fetchone()    
            if r: 
                if r[0]:
                    tm=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')               
                    if tm>'2021-12-01 00:00:00':
                        #try:
                        result=tasks.post_hand.delay({
                            'batch':{'id':batch.id,'code':batch.code},
                            'actions':['return']
                        })  
        #2021-12-24
        #elif c.level_id>1:
        else:
            #二批、终端退货经销商，退货方自动生成退货出库单 
            s="select from_agent_id from inventory_stkdetails where batch_id="+b_id+" group by from_agent_id"
            cur.execute(s)
            for rt in cur.fetchall():
                agts=Company.objects.filter(id=rt[0])                
                if agts:
                    agt=agts[0]
                    bt=Batch(vtype_id=40,level_id=agt.level_id,hierarchy_id=agt.hierarchy_id,version=1,company_id=rt[0],code=batch.code,user_id=int(usr_id),ancestor_id=agt.ancestor_id)
                    bt.save()
                    s="INSERT INTO inventory_stkdetails(label_code,batch_id,company_id,product_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id,from_agent_id) select " + \
                        "label_code,"+str(bt.id)+","+str(agt.id)+",product_id,label_id,label_pkg,40,label_pk_id,"+str(agt.ancestor_id)+",from_agent_id "+\
                        "from inventory_stkdetails where batch_id="+str(batch.id)+" and from_agent_id="+str(agt.id)
                    cur.execute(s)
    #2021-12-27 下级转货单
    elif vch_id==20:
        #自动生成转出方 转货出库单
        #9;"GXI";"换货入库";1;"换货入库"  #10;"GXO";"换货出库";-1;"换货出库" 
        agt=Company.objects.get(id=batch.company_fr_id)
        bt=Batch(vtype_id=10,level_id=agt.level_id,hierarchy_id=agt.hierarchy_id,version=1,company_id=agt.id,code=batch.code,user_id=int(usr_id),ancestor_id=agt.ancestor_id)
        bt.save()
        s="INSERT INTO inventory_stkdetails(label_code,batch_id,company_id,product_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id,company_to_id) select " + \
            "label_code,"+str(bt.id)+","+str(agt.id)+",product_id,label_id,label_pkg,10,label_pk_id,"+str(agt.ancestor_id)+","+str(batch.company_id)+" "+\
            "from inventory_stkdetails where batch_id="+str(batch.id)
        cur.execute(s)

    

    #2022-04-27 要求使用前端传过来的单据时间
    if tm_crucial:
        cur.execute("update inventory_batch set dt='"+dt0+"',tm='"+tm0+"' where id="+b_id)
        cur.execute("update inventory_stkdetails set dt='"+dt0+"',tm='"+tm0+"' where batch_id="+b_id)

    #2022-06-14 更新明细记录parent_id
    try:
        cur.execute("update inventory_stkdetails set parent_id="+c_parent_id+" where batch_id="+b_id)
    except Exception:
        pass


    
    #2021-12-24                    
    #下级是否自动人库                    
    if vch_id==2:     
        #内参发货一级经销商，发货直接作为一级经销商入库
        #if c.id==1644:
        #2020-04-25修改为
        #公司发货一级经销商，发货直接作为一级经销商入库(酒鬼除外）

        #2020-07-17
        #cfgs=CompanyCfg.objects.filter(company_id=c.id)
        auto_inbound=False    

        #2021-01-19 杨盖:内参有直接发货给二级,不做自动入库
        cur.execute("select level_id from company_company where id="+str(agt_id))
        r=cur.fetchone()
        agt_lv_id=r[0]

        if cfgs:        
            cfg=cfgs[0]
            if agt_lv_id==2:
                if cfg.inbound_auto_lv1:
                    auto_inbound=True  
            #elif agt_lv_id==4:
            #    if cfg.inbound_auto_lv2:
            #        auto_inbound=True 
            #2021-12-20 Jonathan:三级经销商也自动入库，即lvevel_id=4(二级) 到 level_id=13(零售) 
            #11013;"零售";13
            #11014;"团购";14
            elif agt_lv_id>1 and agt_lv_id<13:
                if cfg.inbound_auto_lv2:
                    #如果设置了二级自动入库，三级、四级。。全部自动入库
                    auto_inbound=True   
        #酒鬼公司发给内参，发货直接作为内参入库
        if c.id==1 and agt_id==7212:    
            sto=None
            if int(sto_id)==37:
                sto=45
            elif int(sto_id)==47:
                sto=46
            else:
                #默认吉首仓库
                sto=45
            #batch
            b=Batch(vtype_id=1,level_id=1,hierarchy_id=1,version=1,company_id=1644,company_fr_id=1,store_fr_id=sto,
                code=batch.code,product_id=batch.product_id,user_id=int(usr_id),ancestor_id=1644)
            b.save()           
            #batchdetails
            sql="insert into logistics.inventory_batchdetails(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id) "+\
                "select "+str(b.id)+",label_code,label_id,label_pkg,label_pk_id,company_id from logistics.inventory_batchdetails where batch_id="+b_id
            cur.execute(sql)
            
            #stkdetails
            if not sto:
                sto='null'
            else:
                sto=str(sto)
            sql = "INSERT INTO logistics.inventory_stkdetails (dt,label_code,batch_id," + \
                "company_id,product_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id,store_id,store_fr_id) select '" + \
                vch_dt + "',label_code,"+str(b.id)+",1644,"+\
                "coalesce((select nc_id from z_jg_nc_product where jg_id=product_id limit 1),product_id),"+\
                "label_id,label_pkg,1,label_pk_id,1644,"+sto+","+sto+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
                " and label_id is not null and err is null"         
            cur.execute(sql)
            b.dt_handled = timezone.now()
            b.tm_handled = timezone.now()
            b.save()   
        elif auto_inbound: 
            #2021-01-19 杨盖:内参有直接发货给二级,不做自动入库           
            if c.id==1644 and agt_lv_id==4:
                pass
            else:
                #batch
                b=Batch(vtype_id=1,level_id=agt_lv_id,hierarchy_id=1,version=1,company_id=int(agt_id),company_fr_id=c.id,code=batch.code,
                    reference_id=batch.id, product_id=batch.product_id,user_id=int(usr_id),ancestor_id=c.ancestor_id)                  
                b.save()
                #batchdetails
                sql="insert into logistics.inventory_batchdetails(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id,ancestor_id) select "+\
                    str(b.id)+",label_code,label_id,label_pkg,label_pk_id,"+str(agt_id)+",company_id from logistics.inventory_batchdetails where batch_id="+b_id                       
                cur.execute(sql)
                #stkdetails      
                sql = "INSERT INTO logistics.inventory_stkdetails (dt,label_code,batch_id," + \
                    "company_id,product_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select '" + \
                    vch_dt + "',label_code,"+str(b.id)+"," + str(agt_id) + "," + product + ", label_id," + \
                    "label_pkg,1,label_pk_id,"+str(c.ancestor_id)+" from inventory_batchdetails a where batch_id="+b_id+\
                    " and label_id is not null and err is null"            
                
                cur.execute(sql)
                b.dt_handled = timezone.now()
                b.tm_handled = timezone.now()
                b.save()  

                #2022-04-27 要求使用前端传过来的单据时间
                if tm_crucial:
                    cur.execute("update inventory_batch set dt='"+dt0+"',tm='"+tm0+"' where id="+str(b.id))
                    cur.execute("update inventory_stkdetails set dt='"+dt0+"',tm='"+tm0+"' where batch_id="+str(b.id))


        #2020-06-10，取消直营店自动补入库，改为先入库再出库
        #扫码出库时，若直营店未扫码入库，系统补一笔入库 level_id:1,公司；2,平台商，4：终端店（直营店）
        #elif c.level_id>2 and STRICT==False:            
        #    s="select id from inventory_stkdetails a where batch_id="+str(batch.id)+" and (select id from inventory_stkdetails"+\
        #        " where company_id="+str(c.id)+" and vtype_id=1 and label_code=a.label_code) is null limit 1"  
        #    cur.execute(s)
        #    rs_add=cur.fetchone()
        #    if rs_add:  
        #        b=Batch(vtype_id=1,level_id=c.level_id,hierarchy_id=c.hierarchy_id,version=0,company_id=c.id,company_fr_id=c.parent_id,
        #            code=batch.code,product_id=batch.product_id,user_id=int(usr_id),ancestor_id=c.ancestor_id)
        #        b.save()                
        #        a_id=str(c.ancestor_id)
        #        p_id=str(c.parent_id)
        #        c_id=str(c.id)
        #        #batchdetails
        #        sql="insert into inventory_batchdetails(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id,ancestor_id) select "+\
        #            str(b.id)+",label_code,label_id,label_pkg,label_pk_id,"+c_id+","+a_id+" from inventory_batchdetails a "+\
        #            "where batch_id="+b_id+" and (select id from inventory_stkdetails where "+\
        #                " company_id="+c_id+" and vtype_id=1 and label_code=a.label_code) is null"
        #        cur.execute(sql)
        #        #stkdetails
        #        sql = "INSERT INTO logistics.inventory_stkdetails (dt,label_code,batch_id," + \
        #            "company_id,product_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id) select '" + \
        #            vch_dt+"',label_code,"+str(b.id)+","+c_id+","+product+",label_id,label_pkg,1,label_pk_id,"+a_id+\
        #            " from inventory_batchdetails a where batch_id="+str(b.id)+" and label_id is not null"                             
        #        cur.execute(sql)
        #        b.dt_handled = timezone.now()
        #        b.tm_handled = timezone.now()
        #        b.save()   
        #酒鬼公司发给内参，发货直接作为内参入库
        #elif c.id==1 and agt_id==7212:    
        #    sto=None
        #    if int(sto_id)==37:
        #        sto=45
        #    elif int(sto_id)==47:
        #        sto=46
        #    else:
        #        #默认吉首仓库
        #        sto=45
        #    #batch
        #    b=Batch(vtype_id=1,level_id=1,hierarchy_id=1,version=1,company_id=1644,company_fr_id=1,store_fr_id=sto,
        #        code=batch.code,product_id=batch.product_id,user_id=int(usr_id),ancestor_id=1644)
        #    b.save()           
        #    #batchdetails
        #    sql="insert into logistics.inventory_batchdetails(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id) "+\
        #        "select "+str(b.id)+",label_code,label_id,label_pkg,label_pk_id,company_id from logistics.inventory_batchdetails where batch_id="+b_id
        #    cur.execute(sql)
            
        #    #stkdetails
        #    if not sto:
        #        sto='null'
        #    else:
        #        sto=str(sto)
        #    sql = "INSERT INTO logistics.inventory_stkdetails (dt,label_code,batch_id," + \
        #        "company_id,product_id,label_id,label_pkg,vtype_id,label_pk_id,ancestor_id,store_id,store_fr_id) select '" + \
        #        vch_dt + "',label_code,"+str(b.id)+",1644,"+\
        #        "coalesce((select nc_id from z_jg_nc_product where jg_id=product_id limit 1),product_id),"+\
        #        "label_id,label_pkg,1,label_pk_id,1644,"+sto+","+sto+" from logistics.inventory_batchdetails a where batch_id=" + b_id + \
        #        " and label_id is not null"         
        #    cur.execute(sql)
        #    b.dt_handled = timezone.now()
        #    b.tm_handled = timezone.now()
        #    b.save()   

    
    
    
    #2021-04-01 垛标数据处理
    if stacks:
        s=''
        if vch_id==1:
            s="INSERT INTO inventory_stackdetails(product_id,label_pk_id,label_id,label_pkg,label_code,tm,stack_id) "+\
                "select product_id,label_pk_id,label_id,label_pkg,label_code,now(),stack_id "+\
                "from inventory_stkdetails where batch_id="+str(batch.id)+" and stack_id>0 "+\
                "on CONFLICT(stack_id,label_pk_id) do nothing"
        elif vch_id==2:
            s="delete from inventory_stackdetails a where "+\
                "(select id from inventory_stkdetails where batch_id="+str(batch.id)+" and  label_pk_id=a.label_pk_id limit 1)>0"
        if s:
            cur.execute(s)
    
    
    
    #2020-09-16 层级返利
    if c.level.sn>0 and is_app:      
        #try:    
            data['rebate']=channel_rebate(batch)            
        #except:
        #    pass
    if batch.ancestor_id == 19257 or batch.ancestor_id == 16687 : 

        if vch_id == 2 and c.level.sn>=1:
            brands_agent_level_update(batch.ancestor_id,batch.company_id)
            sale_task_agent_update(batch.ancestor_id,batch.company_id)

        ssql = ("update company_agentorderbatch set tm_complete = now() where id in ("
                "SELECT id from company_agentorderbatch WHERE batch_code in (SELECT  "
	            "(SELECT code from inventory_batch where id = batch_id) "
	            "FROM inventory_stkdetails WHERE "
            	"label_code in (SELECT label_code from inventory_stkdetails where batch_id = "+b_id+") )"
                "and tm_complete is null)")
        cur.execute(ssql)    

    return JsonResponse(data) 

































@csrf_exempt
def legacy_delivery(request):
    data = {'e': '', 'cnt': 0}
    # 2019-05-25,发货机器人有时发空请求过来
    if not request.body:
        return JsonResponse(data)
    try:
        r = json.loads(request.body)
    except Exception:
        return JsonResponse(data)
    k = sK
    fh_tm = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    pro_id = r['product_id']
    if 'fh_time' in r:
        fh_tm = r['fh_time']
    type_id = r['type']
    usr_id = r['user_id']
    sto_id = r['store_id']
    fr_cid = r['fr_company_id']
    to_cid = r['to_company_id']
    pici = r['fhpici']
    fhkey = r['fhkey']
    cnt = str(r['xiang'])
    codes = r['codes']
    if not codes:
        return JsonResponse(data)
    beizhu = 'null'
    khdd = 'null'
    gpsinfo = 'null'
    sclocal = 'null'
    if r['beizhu']:
        beizhu = "'" + r['beizhu'] + "'"
    if r['sclocal']:
        sclocal = "'" + r['sclocal'] + "'"
    if r['gpsinfo']:
        gpsinfo = "'" + r['gpsinfo'] + "'"
    if r['khdd']:
        khdd = "'" + r['khdd'] + "'"
    rec_cnt = len(codes)
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    if int(type_id) not in (2, 4):
        data['e'] = '单据类别只能是销售出库单或销售退库单'
        return JsonResponse(data)    
    cur = connection.cursor()
    cur.execute("insert into logistics.delivery_summary (fhpici,fhkey,gpsinfo,khddh,proid,stid,fhuserid,compid," +
                "agentid,xiangnumber,voucher_id,beizhu,sclocal,fhdate" +
        ") values (" +
            "'" + pici + "','" + fhkey + "'," + gpsinfo + "," + khdd + "," + str(pro_id)+"," + str(sto_id) + "," +
            str(usr_id) + "," + str(fr_cid) + "," + str(to_cid) + "," + str(cnt) + "," + str(type_id) + "," +
            beizhu + "," + sclocal + ",'" + fh_tm + "') returning id")
    r = cur.fetchone()
    sum_id = str(r[0])
    cur1 = connection.cursor()
    cur1.execute("create temp table codes (label_code character varying(20),tb character varying(20),label_id bigint)")
    a = []
    for code in codes:
        a.append("('" + code + "','" + code[:4] + "')")
    cur1.execute("insert into codes (label_code,tb) values " + ",".join(a))
    cur1.execute("select tb from codes group by tb")
    rs = cur1.fetchall()
    for r in rs:
        cur.execute("select to_regclass('label.t" + r[0] + "')")
        r0 = cur.fetchone()
        if r0[0]:
            cur1.execute("update codes set label_id=" +
                         "(select id from label.t" + r[0] + " where code=label_code) where tb='" + r[0] + "'")    
    s = "insert into delivery_details(summary_id,label_code,label_id) select " + \
        sum_id + ",label_code,coalesce(label_id,0) from codes"
    cur.execute(s)
    data['cnt'] = cur.rowcount   
    return JsonResponse(data)




#2019-11-16 出人库列表    
#@login_required
@tj_login_required
def stock_list(request,company_id=None):
    if not company_id:
        company_id=str(request.user.company.id)
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('date_fr', dt)
    dt_to = request.GET.get('date_to', dt)
    dt_max = max(dt_fr, dt_to)
    dt_min = min(dt_fr, dt_to)
    dt_fr = dt_min
    dt_to = dt_max
    store_id = request.GET.get("store_id", "")
    product_id = request.GET.get("product_id", "")
    store_label = request.GET.get("store_label", "")
    product_label = request.GET.get("product_label", "")
    params = {
        'dt_fr': dt_fr,
        'dt_to': dt_to,
        'store_id': store_id,
        'product_id': product_id,
        'store_label': store_label,
        'product_label': product_label
    }
    sStore = ""
    sProduct = ""
    sFsto=""
    if store_id:
        sFsto = " and store_to_id=" + str(store_id)
        sStore = " and store_fr_id=" + str(store_id)
    if product_id:
        sProduct = " and product_id=" + str(product_id)
    sWhere = " where company_id=" + company_id + " and (dt between '" + dt_fr + "' and '" + dt_to + "')"
    data = {'e': '', 'data': [], 'stores': [], 'products': []}
    cur = connection.cursor()
    for o in Storehouse.objects.filter(company_id=int(company_id)).order_by('name'):
        data['stores'].append({'label': o.name, 'value': o.id})
    for o in Product.objects.filter(company_id=int(company_id)).order_by('name'):
        data['products'].append({'label': o.name, 'value': o.id})
    """
    单据类别：voucher id
    1;"成品入库单";"GRN";1
    2;"销售出库单";"GDN";-1
    3;"成品转库单";"GTN";0
    4;"销售退库单";"GWN";1
    5;"入库单退库";"GCN";-1
    """
    s = "select (select name from logistics.inventory_storehouse where id=l.store_id) store," + \
        "coalesce((select name from logistics.product_product where id=l.product_id),'') product," + \
        "coalesce(grn.qty,0),coalesce(gcn.qty,0),coalesce(gtn_to.qty,0)," + \
        "coalesce(gtn_fr.qty,0),coalesce(gdn.qty,0),coalesce(gwn.qty,0) from " + \
        "(select a.product_id product_id,a.store_id store_id from (" + \
            "select product_id,store_fr_id store_id from logistics.inventory_batch " + sWhere + sStore + sProduct + \
                " and store_fr_id is not null group by product_id,store_fr_id"+\
            " union " + \
            "select product_id,store_to_id store_id from logistics.inventory_batch" + sWhere + sFsto + sProduct + \
                " and store_to_id is not null group by product_id,store_to_id) a) l " + \
        "left outer join " +\
        "(select product_id,store_id,count(*) qty from logistics.inventory_stkdetails" + sWhere + sStore + sProduct + \
            " and vtype_id=1  and is_delete=false group by product_id,store_id) as grn " + \
        "on l.product_id=grn.product_id and l.store_id=grn.store_id " + \
        "left outer join " + \
        "(select product_id,store_id,count(*) qty from logistics.inventory_stkdetails" + sWhere + sStore + sProduct + \
            " and vtype_id=2 group by product_id,store_id) as gdn " + \
        "on l.product_id=gdn.product_id and l.store_id=gdn.store_id " + \
        "left outer join " + \
        "(select product_id,store_id,count(*) qty from logistics.inventory_stkdetails" + sWhere + sStore + sProduct + \
            " and vtype_id=5 group by product_id,store_id) as gcn " + \
        "on l.product_id=gcn.product_id and l.store_id=gcn.store_id " + \
        "left outer join " + \
        "(select product_id,store_id,count(*) qty from logistics.inventory_stkdetails" + sWhere + sStore + sProduct + \
            " and vtype_id=4 group by product_id,store_id) as gwn " + \
        "on l.product_id=gwn.product_id and l.store_id=gwn.store_id " + \
        "left outer join " + \
        "(select product_id,store_to_id store_id,count(*) qty from logistics.inventory_stkdetails" + sWhere + sFsto + sProduct + \
            " and vtype_id=3 and store_to_id is not null group by product_id,store_to_id) as gtn_to " + \
        "on l.product_id=gtn_to.product_id and l.store_id=gtn_to.store_id " + \
        "left outer join " + \
        "(select product_id,store_fr_id store_id,count(*) qty from logistics.inventory_stkdetails" + sWhere + sStore + sProduct +\
            " and vtype_id=3 and store_fr_id is not null group by product_id,store_fr_id) as gtn_fr " + \
        "on l.product_id=gtn_fr.product_id and l.store_id=gtn_fr.store_id"   


    
    cur.execute(s)
    for r in cur.fetchall():
        data['data'].append([r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7],])    
    
    return render(request, 'inventory/stock/stock_list.html', {        
        'stores': SafeString(data['stores']),
        'products': SafeString(data['products']),
        'data':SafeString(data['data']),
        'e': data['e'],
        'params': params
    })

@tj_login_required
def stkclosing_list(request,company_id=None):
    if not company_id:
        company_id=str(request.user.company.id)
    
    ancestor_id = str(request.user.company.id)
    cur = connection.cursor()
    cur.execute("select stkclosing_id from inventory_stkclosingcurrent where ancestor_id = "+ancestor_id)
    r = cur.fetchone()
    data = []
    package_units = get_package_name(ancestor_id)
    if r:
        stkclosing_id = str(r[0])
        s=f"""
            SELECT
            ( SELECT NAME FROM company_company WHERE ID = company_id ),
            ( SELECT NAME FROM product_product WHERE ID = product_id ),
            case when label_pkg = 3 then '{package_units[2]}' when label_pkg = 2 then '{package_units[1]}' else '{package_units[0]}' end,
            count(*)

            FROM
                "inventory_stkclosingdetails" 
            WHERE
                stkclosing_id = {stkclosing_id} 
            GROUP BY
                product_id,
                company_id,
                label_pkg
        """
        cur.execute(s)
        rs = cur.fetchall()
        for r in rs:
            data.append([
                r[0],
                r[1],
                r[2],
                r[3]
            ])
        
    periods = []    
    cur.execute("select id,yr,mn from inventory_stkclosingperiod where ancestor_id = "+ancestor_id)
    rs = cur.fetchall()
    for r in rs:
        periods.append({
            'id':r[0],
            'name': str(r[1])+'年-'+str(r[2])+'月'
        })
    return render(request, 'inventory/stkclosing_list.html', { 
        'data':SafeString(data),
        'periods':SafeString(periods)
    })
    
@csrf_exempt
def ajax_stkclosing_list(request):
    data = {
        'e':''
    }
    company_id = request.GET.get('company_id','')
    if company_id:
        c = Company.objects.get(id=int(company_id))
        ancestor_id = str(c.ancestor_id)
        cur = connection.cursor()
        cur.execute("select stkclosing_id from inventory_stkclosingcurrent where ancestor_id = "+ancestor_id)
        r = cur.fetchone()
        ls = []
        if r:
            stkclosing_id = str(r[0])
            s=f"""
                SELECT
                ( SELECT NAME FROM product_product WHERE ID = product_id ),
                case when label_pkg = 3 then '箱' else '瓶' end,
                count(*),
                product_id

                FROM
                    "inventory_stkclosingdetails" 
                WHERE
                    stkclosing_id = {stkclosing_id} 
                    and company_id = {company_id}
                GROUP BY
                    product_id,
                    label_pkg
            """
            cur.execute(s)
            rs = cur.fetchall()
            for r in rs:
                ls.append({
                    'product':r[0],
                    'label_pkg':r[1],
                    'qty':r[2],
                    'product_id':r[3]
                })
        data['list'] = ls
    else:
        data['e'] = '数据丢失'
    return JsonResponse(data,safe=False)

#2019-11-16 入库，销售，转库，退库，退标    
#@login_required
@login_required
def batch_list(request,obj,company_id=None):
    if not company_id:
        company_id=str(request.user.company.id)
    ancestor_id = request.user.ancestor_id
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('date_fr', dt)
    dt_to = request.GET.get('date_to', dt)
    if request.user.company.id == 19257: 
        dt_fr = request.GET.get(
            'date_fr', (datetime.datetime.now() + datetime.timedelta(days=-7)).strftime('%Y-%m-%d'))
    dt_max = max(dt_fr, dt_to)
    dt_min = min(dt_fr, dt_to)
    dt_fr = dt_min
    dt_to = dt_max    
    
    product_id = request.GET.get("product_id", "")   
    product_label=request.GET.get('product_label','')
    agent_id=request.GET.get("agent_id","")  
    agent_label=request.GET.get('agent_label','')
    code=request.GET.get('code','')
    params = {
        'dt_fr': dt_fr,
        'dt_to': dt_to,
        'agent_id': agent_id,     
        'agent_label':agent_label,
        'product_id': product_id, 
        'product_label':product_label,
        'code':code,
    }     
    v=None
    #sStore=""
    e=""
    sProduct=""
    sAgent=""
    sCode=""
    #if store_id:
    #    sStore=" and store_fr_id="+store_id
    if product_id:
        sProduct=" and product_id="+product_id
    if agent_id:
        sAgent=" and company_to_id="+agent_id
    if code:
        sCode=" and code='"+code+"'"

    #2022-05-12 酒鬼需要显示扫码上传数量和写入数量的对比
    show_compare=False
    if request.user.company.id in [1]:
        show_compare=True
    
    
    vs=Voucher.objects.filter(code=obj.upper())
    data=[]
    stores=[]
    products=[]
    if not vs:
        e=_('单据类别错误')
    else:
        #2020-12-01
        saldiv_rpt=False
        try:
            if request.user.company.cfg_company:
                saldiv_rpt=request.user.company.cfg_company.saldiv_report
        except Exception:
            pass
        v=vs[0]
        vid=str(v.id)
        sWhere=" where company_id="+company_id+" and vtype_id="+vid+\
            " and (dt between '"+dt_fr+"' and '"+dt_to+"')"      
        
        package_units = get_package_name(ancestor_id,'数')
        
        #2022-05-10
        clmns=[]
        if vid=='1':    #入库
            if show_compare:
                clmns=['上传时间','生产批次','产品名称','质检','仓库名称','操作人','扫码量','箱数','盒数','瓶数']
                if company_id=='100425': #山西成兆兴酒业有限公司
                    clmns=['上传时间','生产批次','产品名称','工厂','车间','产线','班组','仓库名称','操作人','扫码量','箱数','盒数','瓶数']  
                elif company_id=='16716':    #"湖北裕贡酒业销售有限公司"
                    clmns=['上传时间','生产批次','产品名称','工厂','仓库名称','操作人','扫码量','箱数','盒数','瓶数']
            else:
                if request.user.company.is_manufacturing:
                    clmns=['上传时间','生产批次','产品名称','质检员','仓库名称','操作人','箱数','盒数','瓶数']
                else:
                    clmns=['上传时间','生产批次','产品名称','仓库名称','操作人',package_units[2],package_units[1],package_units[0]]
                if company_id=='100425': #山西成兆兴酒业有限公司
                    clmns=['上传时间','生产批次','产品名称','工厂','车间','产线','班组','仓库名称','操作人','箱数','盒数','瓶数']  
                elif company_id=='16716':    #"湖北裕贡酒业销售有限公司"
                    clmns=['上传时间','生产批次','产品名称','工厂','仓库名称','操作人','箱数','盒数','瓶数']
            

        elif vid=='2':  #出库
            #2022-06-18 特定公司跳转到os销售出库列表
            if company_id in os_cids:
                cid=os_cids[company_id]
                return  redirect('/inventory/os/outbound/'+cid+'/list/')
            #需要需要显示战区分区
            if saldiv_rpt:
                clmns=['上传时间','单据编号','客户名称','战区','分区','产品名称','仓库名称','操作人','箱数','盒数','瓶数']
                if show_compare:
                    clmns=['上传时间','单据编号','客户名称','战区','分区','产品名称','仓库名称','操作人','扫码量','箱数','盒数','瓶数']                
            else:
                clmns=['上传时间','单据编号','客户名称','产品名称','仓库名称','操作人',package_units[2],package_units[1],package_units[0]]              
                if show_compare:
                    clmns=['上传时间','单据编号','客户名称','产品名称','仓库名称','操作人','扫码量','箱数','盒数','瓶数']
            if company_id=='19257':
                clmns.append('客户上级')
            elif company_id=='20445':
                clmns.append("品牌推荐")                
        elif vid=='3':  #转库
            clmns=['上传时间','单据编号','产品名称','转入','转出','操作人',package_units[2],package_units[1],package_units[0]]
            if show_compare:
                clmns=['上传时间','单据编号','产品名称','转入','转出','操作人','扫码量','箱数','盒数','瓶数']

        elif vid=='4':  #销售退库
            clmns=['上传时间','单据编号','退货客户','产品名称','仓库名称','操作人',package_units[2],package_units[1],package_units[0]]
            if show_compare:
                clmns=['上传时间','单据编号','退货客户','产品名称','仓库名称','操作人','扫码量','箱数','盒数','瓶数']

        elif vid=='7':  #礼品出库
            clmns=['上传时间','单据编号','客户名称','战区','分区','产品名称','仓库名称','操作人','箱数','盒数','瓶数']
            if show_compare:
                clmns=['上传时间','单据编号','客户名称','战区','分区','产品名称','仓库名称','操作人','扫码量','箱数','盒数','瓶数']
            if company_id=='19257':                
                clmns.append("客户上级")
            elif company_id=='20445':                
                clmns.append('品牌推荐')     
        elif vid=='5': #"标签退库"
            if show_compare:
                clmns=['上传时间','单据编号','产品名称','仓库名称','操作人','扫码量','箱数','盒数','瓶数']
            else:
                clmns=['上传时间','单据编号','产品名称','仓库名称','操作人',package_units[2],package_units[1],package_units[0]]


        sDel=''
        #2022-06-08 以下两行注释掉，入库后又做的标签退库(is_delete=true),不应该影响当前的本次入库数量 
        #if v.id==1:            
        #    sDel=" and is_delete=false"

        dataset=[]       
        #for o in Storehouse.objects.filter(company_id=int(company_id)).order_by('name'):
        #    stores.append({'label': o.name, 'value': o.id})
        #for o in Product.objects.filter(company_id=int(company_id)).order_by('name'):
        #    products.append({'label': o.name, 'value': o.id})   

        #2022-05-16 成义烧坊，销售出库，显示修改单据时添加的客户姓名，地址
        sRmk="''"
        if company_id in ['100424']:
            #sRmk="case when rmk_address is null then coalesce(rmk_name,'') "+\
            #    "else  coalesce(rmk_name,'')||coalesce(rmk_address,'') end"
            sRmk="case when rmk_address is null then "+\
                    "case when rmk_name is null then '' else ' ['||rmk_name||']' end "+\
                "else  "+\
                    "case when rmk_name is null then ' ['||rmk_address||']' else ' ['||rmk_name||' '||rmk_address||']' end "+\
                "end"

        s="select b.tm,b.code,"+\
            "coalesce((select name from product_product where id=b.product_id),''),"+\
            "coalesce((select name from inventory_storehouse where id=b.store_fr_id),''),"+\
            "coalesce((select username from company_user where id=b.user_id),''),"+\
            "coalesce(d.x,0),coalesce(d.h,0),coalesce(d.p,0),"+\
            "case when b.customer_company is null then coalesce((select name from company_company where id=b.company_to_id)||"+sRmk+",'')"+\
                " else '团购('||customer_name||' '||b.customer_phone||' '||b.customer_company||')' end,"+\
            "coalesce((select name from inventory_storehouse where id=b.store_to_id),''),"+\
            "b.id,"+\
            "coalesce((select name from company_prdplant where id=b.prd_plant_id),''), "+\
            "coalesce(b.qc_name,''), "+\
            "coalesce((SELECT name from company_company where id = (SELECT parent_id from company_company WHERE id = b.company_to_id)),''), "+\
            "coalesce((SELECT name from company_brandrecommender where id=recommender_id),''),"+\
            "coalesce((select name from company_prdworkshop where id=b.prd_workshop_id),''), "+\
            "coalesce((select name from company_prdline where id=b.prd_line_id),''), "+\
            "coalesce((select name from company_prdteam where id=b.prd_team_id),''), "+\
            "case when d.qty_batch=(select count(*) from inventory_stkdetails where batch_id=b.id) "+\
                "then ''||d.qty_batch else "+\
                "'<span class=\"r\" >'||(select count(*) from inventory_batchdetails where batch_id=b.id)||'</span>' "+\
            "end "+\
            "from "+\
            "(select id,tm,coalesce(code,'') code,user_id,product_id,store_fr_id,store_to_id,company_to_id,prd_plant_id,rmk_name,rmk_address,"\
                "customer_company,customer_phone,customer_name,qc_name,recommender_id,prd_workshop_id,prd_line_id,prd_team_id "+\
                "from inventory_batch "+sWhere+sProduct+sAgent+sCode+") b "+\
            "left outer join "+\
            "(select a.batch_id,sum(a.x) x,sum(a.h) h,sum(a.p) p,"+\
                "(select count(*) from inventory_batchdetails where batch_id=a.batch_id) qty_batch "+\
                "from "+\
                "(select batch_id,"+\
                    "case when label_pkg in (3,4) then 1 else 0 end x,"+\
                    "case when label_pkg=2        then 1 else 0 end h,"+\
                    "case when label_pkg=1        then 1 else 0 end p "+\
                    "from inventory_stkdetails "+sWhere+sProduct+sAgent+sDel+\
                ") a group by a.batch_id"+\
            ") d "+\
            "on b.id=d.batch_id"     
        #如内参公司，销售出库要显示战区分区
        if vid in ['2','7'] and saldiv_rpt:
            s="select b.tm,b.code,"+\
                "coalesce((select name from product_product where id=b.product_id),''),"+\
                "coalesce((select name from inventory_storehouse where id=b.store_fr_id),''),"+\
                "coalesce((select username from company_user where id=b.user_id),''),"+\
                "coalesce(d.x,0),coalesce(d.h,0),coalesce(d.p,0),"+\
                "case when b.customer_company is null then coalesce((select name from company_company where id=b.company_to_id),'')"+\
                    " else '团购('||customer_name||' '||b.customer_phone||' '||b.customer_company||')' end,"+\
                "coalesce((select name from inventory_storehouse where id=b.store_to_id),''),"+\
                "b.id,"+\
                "coalesce((select name from company_prdplant where id=b.prd_plant_id),''), "+\
                "b.qc_name, "+\
                "coalesce((select name from company_salesdivision where id=c.division_id),''),"+\
                "coalesce((select name from company_subsaldivision where id=c.sub_division_id),''), "+\
                "coalesce((SELECT name from company_brandrecommender where id=recommender_id),''),"+\
                "d.qty_batch "+\
                "from "+\
                "(select id,tm,coalesce(case when dn_number='' then  null else dn_number end, code) code,user_id,product_id,store_fr_id,store_to_id,company_to_id,prd_plant_id,"\
                    "customer_company,customer_phone,customer_name,qc_name,recommender_id from inventory_batch "+sWhere+sProduct+sAgent+sCode+") b "+\
                "left outer join "+\
                "(select a.batch_id,sum(a.x) x,sum(a.h) h,sum(a.p) p,"\
                    "(select count(*) from inventory_batchdetails where  batch_id=a.batch_id) qty_batch "+\
                    "from "+\
                    "(select batch_id,"+\
                        "case when label_pkg in (3,4) then 1 else 0 end x,"+\
                        "case when label_pkg=2        then 1 else 0 end h,"+\
                        "case when label_pkg=1        then 1 else 0 end p "+\
                        "from inventory_stkdetails"+sWhere+sProduct+sAgent+sDel+\
                    ") a group by a.batch_id"+\
                ") d "+\
                "on b.id=d.batch_id "+\
                "left outer join "+\
                "(select id,name,division_id,sub_division_id from company_company) c "\
                "on b.company_to_id=c.id"
            
        cur=connection.cursor()
        cur.execute(s)
        """
        单据类别：voucher id
        1;"成品入库单";"GRN";1
        2;"销售出库单";"GDN";-1
        3;"成品转库单";"GTN";0
        4;"销售退库单";"GWN";1
        5;"入库单退库";"GCN";-1
        """           
        for r in cur.fetchall():
            tm="<a href='/inventory/batch/details/"+str(r[10])+"/' target='_blank'>"+\
                r[0].strftime('%Y-%m-%d %H:%M:%S')+"</a>"
            if vid=='1':
                if request.user.company.is_manufacturing:
                    if show_compare:
                        #16716;"湖北裕贡酒业销售有限公司"
                        if company_id=='16716': 
                            data.append([tm, r[1],r[2],r[11],r[3],r[4],r[18],r[5],r[6],r[7] ])
                        #100425;山西成兆兴酒业有限公司
                        elif company_id=='100425':
                            data.append([tm, r[1],r[2],  r[11],r[15],r[16],r[17],  r[3],r[4],r[18],r[5],r[6],r[7] ])
                        else:
                            data.append([tm, r[1],r[2],r[12],r[3],r[4],r[18],r[5],r[6],r[7] ])
                    else:
                        #16716;"湖北裕贡酒业销售有限公司"
                        if company_id=='16716': 
                            data.append([tm, r[1],r[2],r[11],r[3],r[4],r[5],r[6],r[7] ])
                        #100425;山西成兆兴酒业有限公司
                        elif company_id=='100425':
                            data.append([tm, r[1],r[2],  r[11],r[15],r[16],r[17],  r[3],r[4],r[5],r[6],r[7] ])
                        else:
                            data.append([tm, r[1],r[2],r[12],r[3],r[4],r[5],r[6],r[7] ])
                else:
                    data.append([tm, r[1],r[2],r[3],r[4],r[5],r[6],r[7] ])
            elif vid in ['2','7']:      
                if show_compare:
                    if saldiv_rpt:
                        if request.user.company_id==19257:      #茗酒荟显是上级
                            data.append([tm,r[1],r[8],r[13],r[14],r[2],r[3],r[4],r[16],r[5],r[6],r[7],r[15] ])
                        elif request.user.company_id==20445:    #求真显示品牌推荐官
                            data.append([tm,r[1],r[8],r[13],r[14],r[2],r[3],r[4],r[16],r[5],r[6],r[7],r[16] ])
                        else:
                            data.append([tm,r[1],r[8],r[13],r[14],r[2],r[3],r[4],r[16],r[5],r[6],r[7] ])
                    else:
                        data.append([tm, r[1],r[8],r[2],r[3],r[4],r[18],r[5],r[6],r[7],r[13] ])
                else:
                    if saldiv_rpt:
                        if request.user.company_id==19257:      #茗酒荟显是上级
                            data.append([tm,r[1],r[8],r[13],r[14],r[2],r[3],r[4],r[5],r[6],r[7],r[15] ])
                        elif request.user.company_id==20445:    #求真显示品牌推荐官
                            data.append([tm,r[1],r[8],r[13],r[14],r[2],r[3],r[4],r[5],r[6],r[7],r[16] ])
                        else:
                            data.append([tm,r[1],r[8],r[13],r[14],r[2],r[3],r[4],r[5],r[6],r[7] ])
                    else:
                        data.append([tm, r[1],r[8],r[2],r[3],r[4],r[5],r[6],r[7],r[13] ])
            elif vid=='3':
                if show_compare:
                    data.append([tm, r[1],r[2],r[9],r[3],r[4],r[18],r[5],r[6],r[7] ]) 
                else:
                    data.append([tm, r[1],r[2],r[9],r[3],r[4],      r[5],r[6],r[7] ])
            elif vid=='4':
                if show_compare:
                    data.append([tm, r[1],r[8],r[2],r[3],r[4],r[18],r[5],r[6],r[7] ])
                else:
                    data.append([tm, r[1],r[8],r[2],r[3],r[4],      r[5],r[6],r[7] ])
            elif vid=='5':
                if show_compare:
                    data.append([tm, r[1],r[2],r[3],r[4],r[18],r[5],r[6],r[7] ])  
                else:
                    data.append([tm, r[1],r[2],r[3],r[4],      r[5],r[6],r[7] ])   

                
   


    return render(request, 'inventory/stock/batch_list.html', {          
        'data':SafeString(data),
        'clmns':clmns,
        'e': e,
        'voucher':v,
        'params': params
    })


@tj_login_required
def delete_obj(request,obj_name='',id='0'):
    data={'e':''}
    if request.user.id in [1,2,3214, 3891]: #admin,罗秋吉,tj_nc_admin
        if obj_name=='batch':
            bs=Batch.objects.filter(id=int(id))    
            if bs:
                b=bs[0]
                b.delete()
            else:
                data['e']=_('batch id err')
        else:
            data['e']='unexpected obj name'
    else:
        data['e']='permission denyed'
    return JsonResponse(data)



#2019-11-17 标签明细
@tj_login_required
def batch_details(request,id):
    data={'e':'','batch':{},'dataset':[],'del_perm':False}
    u=request.user
    if u.id in [1,2,3214,2864, 3891]: #admin,罗秋吉，百得信,lv1test,tj_nc_admin
        data['del_perm']=True

    #2022-05-11 如酒鬼，需要显示扫码时的原始标签号（如扫了箱顶标又扫侧标；扫了物流码又扫防伪码）
    show_orig=False
    if u.company.id in [1]:
        show_orig=True

    cur=connection.cursor()
    qty='0'    
    code=request.GET.get('code','')
    vtype_id=request.GET.get('vtype_id','')
    label_code=request.GET.get('label_code','')
    if id=='0':
        s="select product_id,storehouse_id,customer_id,id from jiugui_local.stk_details "+\
            "where code='"+code+"'and vtype_id="+vtype_id+" and label_code='"+label_code+"' limit 1"
        cur.execute(s)
        r=cur.fetchone()
        if r:
            cid=str(r[2])
            pid=str(r[0])
            sid=str(r[1])        
            t="tm_outbound"
            v="'销售出库'"
            sWhere="where code='"+code+"' and vtype_id="+vtype_id+" and "+\
                "product_id="+pid+" and customer_id="+cid+" and storehouse_id="+sid
            s="select "+t+",code,"+v+","+\
                "coalesce((select name from jiugui_local.product where id=product_id),''),"+\
                "coalesce((select name from jiugui_local.storehouse where id=storehouse_id),''),"+\
                "'' store_to,"+\
                "'' username,"+\
                "coalesce((select name from jiugui_local.customer where id=customer_id),''),"+\
                " "+vtype_id+" vtype_id,"+\
                "'' plant,"+\
                "'' vtype_code , "+\
                "(select count(*) FROM jiugui_local.stk_details "+sWhere+"),"+\
                "(select count(*) FROM jiugui_local.stk_details "+sWhere+") "+\
                "FROM jiugui_local.stk_details where id="+str(r[3])       
    else:
        s="select tm,coalesce(code,''),"+\
            "coalesce((select name from inventory_voucher where id=vtype_id),''),"+\
            "coalesce((select name from product_product where id=product_id),''),"+\
            "coalesce((select name from inventory_storehouse where id=store_fr_id),''),"+\
            "coalesce((select name from inventory_storehouse where id=store_to_id),''),"+\
            "coalesce((select username from company_user where id=user_id),''),"+\
            "coalesce((select name from company_company where id=company_to_id),''),"+\
            "vtype_id,"+\
            "coalesce((select name from company_prdplant where id=prd_plant_id),''),"+\
            "coalesce((select code from inventory_voucher where id=vtype_id),''), "+\
            "(select count(*) from inventory_stkdetails where batch_id=b.id),"+\
            "(select count(*) from inventory_batchdetails where batch_id=b.id) "+\
            "from inventory_batch b where id="+id 
    cur.execute(s)
    r=cur.fetchone()
    if r:
        #2022-01-10
        if r[11]:
            qty=str(r[11])
            if r[12]:
                qty=qty+"/"+str(r[12])
        data['batch']={'time':r[0].strftime('%Y-%m-%d %H:%M:%S'),'code':r[1],'voucher':r[2],'id':id,'product':r[3],
            'store_fr':r[4],'store_to':r[5],'user':r[6],'customer':r[7],'vid':r[8],'plant':r[9],'vcode':r[10],'qty':qty
        }          
        #2022-05-10 
        if show_orig:
            clmns=['扫码标签','写入标签','标签类型','产品名称']
        else:
            clmns=['标签号码','标签类型','产品名称']       


        if id=='0':
            code=request.GET.get('code','')
            vtype_id=request.GET.get('vtype_id','')
            if vtype_id=='1':
                t="tm_inbound"
                v="'入库'"
            else:
                t="tm_outbound"
                v="'出库'"
            s="select label_code,label_code,'箱标',"+\
                "coalesce((select name from jiugui_local.product where id=product_id),''),'' "+\
                "FROM jiugui_local.stk_details "+sWhere            
        else:
            s="select coalesce(a.label_code0,a.label_code),"+\
                "coalesce(b.label_code,a.label_code0,a.label_code,''),"+\
                "coalesce((SELECT name FROM label.lbl_package where id=a.label_pkg),a.err,'错误'),"+\
                "coalesce(a.err,(select name from product_product where id=b.product_id),''), "+\
                "coalesce((select label_code_out from company_third_party_label_bind where label_code=b.label_code ORDER BY id desc limit 1 ),'') "+\
                " from "+\
                "(select label_code,label_pkg,err,label_code0 from inventory_batchdetails where batch_id="+id+") a "+\
                "left outer join "+\
                "(select label_code,label_pkg,product_id from inventory_stkdetails where batch_id="+id+") b "+\
                "on a.label_code=b.label_code"           

        cur.execute(s)
        if request.user.company.id == 19257:
            clmns.append('第三方标签')
            for r in cur.fetchall():
                if show_orig:
                    data['dataset'].append([ r[0],r[1],r[2],r[3],r[4] ])
                else:
                    data['dataset'].append([ r[1],r[2],r[3],r[4] ])
        else:
            for r in cur.fetchall():
                if show_orig:
                    data['dataset'].append([ r[0],r[1],r[2],r[3] ])
                else:
                    data['dataset'].append([ r[1],r[2],r[3] ])
        cur.close()
    data['dataset']=SafeString(data['dataset'])
    data['clmns']=clmns        
    return render(request, 'inventory/stock/batch_details.html', data)    



#2019-11-24
@tj_login_required
@csrf_exempt
def batch_edit(request,id):
    if request.method=='GET':
        data={'e':'','batch':{},'store_fr':[],'store_to':[],'product':[],'company_to':[]}     
        company_id=request.user.company.id
        for o in Storehouse.objects.filter(company_id=company_id).order_by('name'):       
            data['store_fr'].append({'label': o.name, 'value': o.id})
            data['store_to'].append({'label': o.name, 'value': o.id})

        #for o in Product.objects.filter(company_id=company_id).order_by('name'):
        #    data['product'].append({'label': o.name, 'value': o.id}) 

        cur=connection.cursor()    
        cur.execute("select (select username from company_user where id=user_id),"+\
            "(select name from inventory_voucher where id=vtype_id),"+\
            "tm,vtype_id,coalesce(code,''),product_id,"+\
            "coalesce(company_to_id,0),coalesce(store_fr_id,0),coalesce(store_to_id,0),"+\
            "coalesce((select name from product_product where id=product_id),''),"+\
            "coalesce((select name from company_company where id=company_to_id),''),"+\
            "coalesce((select name from inventory_storehouse where id=store_fr_id),''),"+\
            "coalesce((select name from inventory_storehouse where id=store_to_id),''),"+\
            "coalesce(qc_name,''),"+\
            "inbound_ticket_id,coalesce((select pici from inventory_inboundtickets where id=inbound_ticket_id),''),"+\
            "coalesce(rmk_name,''),"+\
            "coalesce(rmk_address,'') "+\
            "from inventory_batch where id="+id)
        r=cur.fetchone()
        if r:
            data['batch']={'user':r[0],'voucher':r[1],'tm':r[2].strftime('%Y-%m-%d %H:%M:%S'),'vtype_id':r[3],
                'code':r[4],'product_id':r[5],'company_to_id':r[6],'store_fr_id':r[7],'store_to_id':r[8],
                'product':r[9],'company_to':r[10],'store_fr':r[11],'store_to':r[12],'qc_name':r[13],
                'inbound_ticket':{'id':r[14],'pici':r[15]},
                'rmk_name':r[16],'rmk_address':r[17]
            }      
            #if r[3] in [2,4]:
            #    for o in Company.objects.filter(parent_id=company_id).order_by('name'):
            #        data['company_to'].append({'label': o.name, 'value': o.id})  
            
        return render(request, 'inventory/stock/batch_edit.html', data) 
    else:
        a=[]
        cur=connection.cursor() 
        b=Batch.objects.get(id=int(id)) 
        #2020-06-11 为修改平台商入库信息，保存原信息
        check_inbound=False
        if b.vtype_id==2:            
            check_inbound=True     
        product_id=request.POST.get('product_id','')
        company_to_id=request.POST.get('company_to_id','')
        store_fr_id=request.POST.get('store_fr_id','')
        store_to_id=request.POST.get('store_to_id','')
        code=request.POST.get('code','')
        inbound_ticket_id=request.POST.get('inbound_ticket_id','')


        #2022-05-17
        rmk_name=request.POST.get('rmk_name','')
        rmk_address=request.POST.get('rmk_address','')        
        if rmk_name:
            b.rmk_name=rmk_name
        else:
            b.rmk_name=None
        if rmk_address:
            b.rmk_address=rmk_address
        else:
            b.rmk_address=None
        
        #2020-11-12
        if b.vtype_id==1:            
            qc_name=request.POST.get('qc_name','')
            if qc_name:
                b.qc_name=qc_name

        if inbound_ticket_id:
            b.inbound_ticket_id=int(inbound_ticket_id)
        b.code=code       
        b.product_id=int(product_id)
        a.append('product_id='+str(product_id))
       
        if b.vtype_id==2:
            b.company_to_id=int(company_to_id)        
            a.append('company_to_id='+str(company_to_id))
        if store_fr_id == '0':
            store_fr_id = 'null'
        else: 
            b.store_fr_id=int(store_fr_id)

        a.append('store_id='+str(store_fr_id))
        a.append('store_fr_id='+str(store_fr_id))
        if store_to_id:
            b.store_to_id=int(store_to_id)
            a.append('store_to_id='+str(store_to_id))
        s="update inventory_stkdetails set "+",".join(a)+" where batch_id="+id
        cur.execute(s) 
        b.save()
        #2020-06-06若为发货，且有经销商对应入库记录，则要修改相应入库信息
        if check_inbound:   
            #2020-07-11
            bs=Batch.objects.filter(reference_id=b.id)
            if len(bs)==1:
                b1=bs[0]
                b1.code=code
                b1.product_id=product_id
                b1.company_id=company_to_id                          
                s="update inventory_stkdetails set "+\
                    "product_id="+product_id+",company_id="+company_to_id+\
                    " where batch_id="+str(b1.id)
                cur.execute(s)
                b1.save()   
        #2020-08-15        
        log=ChangeLog(company_id=b.company_id,ancestor_id=b.ancestor_id,obj_name='Batch',obj_id=int(id),user_id=request.user.id)
        log.save()


        #2020-08-25 酒鬼酒修改需要发送透云数据时（？原客户ID为临时客户代码17741）需要重发
        #if b.company_id==1 and b.vtype_id==2 and b.product_id in settings.TY_PRODUCTS_ID:
        #    # is_test=True or False
        #    delivery_ty(b.id, False)


        #2021-08-28 酒鬼酒修改发货信息,检查是否发送给透云
        #if b.company_id==1 and b.vtype_id==2 and b.dt.strftime('%Y-%m-%d')>='2021-08-28':
        #if b.company_id==1 and b.vtype_id==2 and  '一物一码' not in b.code:           
        #    s='select products @> '+"'"+'[{"id":"'+str(b.product_id)+'"}]'+"' "+\
        #        "from thirdparty_vendor where company_id=1 and code='TY'"  
        #    cur.execute(s)
        #    r=cur.fetchone()
        #    if r:            
        #        if r[0] :
        #            try:
        #                delivery_ty(b.id,False)
        #            except Exception:
        #                pass

        if b.company_id==1:
            if b.vtype_id==2: 
                agent_id=b.company_to_id
                #2021-08-28 
                s='select products @> '+"'"+'[{"id":"'+str(b.product_id)+'"}]'+"',"+\
                    'agents @> '+"'"+'[{"id":"'+str(agent_id)+'"}]'+"' "+\
                    "from thirdparty_vendor where company_id=1 and code='HD'"   
                # 2022-07-15 
                s='select products @> '+"'"+'[{"id":"'+str(b.product_id)+'"}]'+"',"+\
                    'agents @> '+"'"+'[{"id":"'+str(agent_id)+'"}]'+"' "+\
                    "from thirdparty_redirect where company_id=1 and code='HD'" 

                
                
                cur.execute(s)
                r=cur.fetchone()

               
                
                if r: 
                    if r[0]:                                     
                        #2021-12-14                
                        result=tasks.post_hand.delay({
                            'batch':{'id':b.id,'code':b.code},
                            'actions':['relations','delivery']
                        })     
            elif b.vtype_id==4:     #酒鬼销售退库发送给汉得
                s='select products @> '+"'"+'[{"id":"'+str(b.product_id)+'"}]'+"' "+\
                    "from thirdparty_vendor where company_id=1 and code='HD'"   
                cur.execute(s)
                r=cur.fetchone()    
                if r: 
                    if r[0]:
                        tm=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')               
                        if tm>'2021-12-01 00:00:00':
                            #try:
                            result=tasks.post_hand.delay({
                                'batch':{'id':b.id,'code':b.code},
                                'actions':['return']
                            })   
        elif b.company_id==1644:
            
            #print(b.vtype_id)
            
            if b.vtype_id==2:
                #异步任务服务器发送 博智
                result=tasks.post_bz.delay({
                    'batch':{'id':b.id,'code':b.code},
                    'actions':['delivery']
                })

                #print(result)
                
        #return  redirect('/inventory/batch/gdn/')
        cur.execute("select code from inventory_voucher where id="+str(b.vtype_id))
        nt='gdn'
        r=cur.fetchone()
        nt=r[0]
        return  redirect('/inventory/batch/'+nt+'/')



#查询订单中的标签信息 Jonathan
@tj_login_required
@csrf_exempt
def batch_query(request):
    data={
        'e':'',
        'batch':[],
        'dataset':[]
    }  
    code = request.GET.get('code','')
    batch_id = request.GET.get('batch_id','')
    cur = connection.cursor()
    if code:  
        cur.execute("SELECT id,tm,(select name from company_company where id = company_fr_id),"+
	    "(select name from company_company where id = company_to_id),"+ 
	    "level_id,(select name from inventory_voucher where id = vtype_id) FROM inventory_batch where code ='"+code+"' ")
        rs = cur.fetchall()
        if rs:
            for r in rs:
                data['batch'].append({
                    'id':r[0],
                    'tm':r[1].strftime("%Y-%m-%d %H:%M:%S"),
                    'comp_fr':r[2],
                    'comp_to':r[3], 
                    'level_id':r[4],
                    'vtype':r[5]
                })   
        else:
            data['e'] = '查询不到订单'
    elif batch_id:
        cur.execute("select count(*) from inventory_stkdetails where batch_id = "+batch_id +" and label_pkg = 3")
        r = cur.fetchone()
        data['box_num'] = r[0]
        cur.execute("select count(*) from label.labelinfo where parent_id in (SELECT label_id from inventory_stkdetails WHERE batch_id = "+batch_id+") and package_id=1");
        r = cur.fetchone()
        data['bottle_num'] = r[0]
        #data['bottle_num'] = 12


    else:
        data['e'] = '数据丢失' 
    
    return JsonResponse(data)  



#@login_required
@login_required
def inventory_html(request, what):    
    if what == 'label_query':
        #if request.user.id in [1]:
        #    h = 'inventory/label_infor.html'
        #else:
        #    h = 'inventory/label_query.html'
        h = 'inventory/label_infor.html'
    elif what == 'label_replace':
        h = 'inventory/label_replace.html'  
    return render(request, h)


#@login_required
@tj_login_required
def get_label_info(request, code):   
    u = request.user    
    if u.is_staff:       
        d = label_info(code, True, None,u)     

        #2020-04-24
        if u.username=='品控部':            
            dd=json.loads(d.content)
            dd['stock_dev']=[]
            dd['product']=''
            return JsonResponse(dd)
    else:
        #2020-04-28 酒鬼罗工，未入库套标查询
        if u.username=='罗秋吉' or (u.company_id==1 and u.groups.all().filter(id__in=[6,2])):        
            d = label_info(code) 
        else:
            d = label_info(code, False, u.company_id,u)      
    return d


# 手机APP窜货查询接口
def app_label_info(request, company_id, code):
    return label_info(code, False, company_id)





def label_info(code, is_staff=False, company_id=None,user=None):
    data = {
        'e': '',
        'code': code,
        'product': '',
        'package': '',
        'company': '',
        'replace': '',
        'boxes': {'pk': '', 'related': []},
        'packets': [],
        'bottles': [],
        'bottlecaps':[],
        'stock_dev': [],
        'replace':'',
        'product_info':{}
    }
    if code[:1]=='4':
        r = requests.request('GET', 'http://www.china315net.com:35088/jg/fw_wl/'+code+'/')
        d = json.loads(r.text)
        if d['wl']:
            code=d['wl']
            data['code']=d['wl']
        else:
            data['e']='获取物流码失败'
            return JsonResponse(data)
    cur = connection.cursor()
    s_company = ''
    a_company_id=0      
    code0=code   
    product_contents=''


    #2022-03-17 小圆标、瓶盖码
    if code[:1] in ('g','h'):
        #2022-03-14 酒鬼小圆标也有替换
        s="select code0,code from label.lbl_replace_details "+\
            "where code='"+code+"' order by id desc limit 1"
        cur.execute(s)
        r=cur.fetchone()
        if r:
            code=r[0]
        d_code=decrypt_11h(code)
        if d_code:                 
            cur.execute("select bottle from label.bottlecap where  label='"+code+"' "+\
                " union all "+\
                "select bottle from z_bottlecap_binding where  label='"+code+"' "
            )
            r=cur.fetchone()
            if r:
                code=r[0]                    
            else:
                #2021-09-13 是否为小圆标活动码
                code=d_code 
                code0=code
    

    if company_id:
        cur.execute("select ancestor_id from logistics.company_company where id="+str(company_id))        
        r=cur.fetchone()
        if r:
            a_company_id=r[0]
        s_company = " and company_id=" + str(company_id)
        #2020-04-09 酒鬼市场稽查人员，先不分酒鬼和内参
        if int(company_id)==1: 
            s_company = " and ancestor_id in (1,1644)"
        else:
            s_company = " and ancestor_id="+ str(a_company_id)
            #else:
            #s_company = " and company_id=" + str(company_id)
    

    #2020-04-30 有标签要查BA表 "湖北裕贡酒业销售有限公司"
    #if not company_id or a_company_id in [16716]:
    cur.execute("select code_a,code_b FROM label.lbl_abcode where code_b='"+code+"'")
    r=cur.fetchone()
    if r:
        code=r[0]
        code0=code     

   
    
   

    #2020-07-27 是否跨段动态绑定
    tb = 'label.t' + code[:4]
    cur.execute("select tbname from label.lbl_tbcross where segment='"+code[:4]+"'")
    rrr=cur.fetchone()
    if rrr:
        tb='label.'+rrr[0] 
    else:
        #2021-01-19 酒鬼/内参:一箱上的两枚标不成套, 用了跨段的两枚新标
        cur.execute("select id from label.lbl_binding_jg where code='"+code+"'") 
        rrr=cur.fetchone()
        if rrr:
            tb='label.lbl_binding_jg'

    # 有标签被替换的情况，
    s="select code0,code,dt from label.lbl_replace_details where code='" + code + "'"+\
        " or code0='"+code+"' order by id desc limit 1"  
    cur.execute(s)
   
    rr=cur.fetchone()
    if rr:
        data['replace']=u"此标签有替换记录 "+rr[2].strftime('%Y-%m-%d')+": "+rr[0]+"->"+rr[1]
        code0=rr[0]
        tb='label.t' + code0[:4]           
    

    try:
        s="select id,package_id,parent_id," + \
            "(select parent_id from " +tb+ " where id=a.parent_id)," + \
            "(select code from " +tb+ " where id=a.parent_id) "+\
            "from " +tb+ " a where code='" + code0 +"' "+\
            "order by id desc limit 1"             
        

        cur.execute(s)
        r = cur.fetchone()
        if not r:
            data['e'] = _('标签号码异常')
            return JsonResponse(data)
    except Exception as e:
        data['e'] = _('标签号码异常')
        return JsonResponse(data)
    
    

    # 非天鉴职员查询
    parent_id='0'
    if company_id:
        #parent_id='null'
        if r[2]:
            parent_id=str(r[2])
            if r[3]:
                parent_id=str(r[3])
        s="select (select name from logistics.product_product where id=product_id) "\
            "from logistics.inventory_stkdetails "+\
                "where vtype_id in (1,2) and is_delete=false " + \
                "and label_pk_id in ("+str(r[0])+","+parent_id+")"+s_company+" order by vtype_id limit 1"
        

        #print(s)


        
        
        cur.execute(s)
        r99=cur.fetchone()
        if r99:
            data['product']=r99[0]
        else:
            if int(company_id)==1:
                if r[1] == 3:
                    data['package']=_('箱标')
                else:
                    data['package']=_('瓶标')
                c = code
                if r[4]:
                    c = r[4]

                #r = jiugui_local_info(c)
                #2020-04-06
                #r = jiugui_local116(c)

                #2022-03-17
                r=get_jiugui_local(parent_id)                
                

                if not r['e']:
                    for dev in  r['stock_dev']:
                        data['stock_dev'].append(dev)
                        if not data['product']:
                            data['product'] = dev['product']
                        
                    #data['product'] = r['product']
                    #data['stock_dev'] = r['stock_dev']
                    #if r['boxes']['pk']:
                    #    data['boxes']= r['boxes']
                    #if r['bottles']:
                    #    data['bottles'] = r['bottles']
                # data['e'] = r['e']
                return JsonResponse(data)
            else:
                data['e'] = _('标签号码未激活')
            return JsonResponse(data)
        
    #company_id=None,酒鬼酒
    # 主箱标ID
    id = 0
    #tb = 'label.t' + code[:4]
    
    




    # 箱标
    if r[1] == 3:
        data['package'] = _('箱标')
        if r[2]:
            id = r[2]
        else:
            id = r[0]
    # 盒标
    elif r[1] == 2:
        data['package'] = _('盒标')
        s = "select coalesce((select parent_id from " + tb + " where id=a.parent_id),parent_id) " + \
            "from " + tb + " a where id=" + str(r[0])
        cur.execute(s)
        id = cur.fetchone()[0]
    # 瓶标
    elif r[1] == 1:
        if not company_id:
            data['package'] = _('瓶标')
        elif int(company_id)==16716:
            data['package'] = _('盒标')
        else:
            data['package'] = _('瓶标')
        s = "select package_id," + \
            "coalesce((select parent_id from " + tb + " where id=a.parent_id),parent_id) " + \
            "from " + tb + " a where id=" + str(r[0])
        cur.execute(s)
        r1 = cur.fetchone()
        # 箱瓶二级对应
        if r1[0] != 3:
            id = r1[1]
        # 箱盒瓶三级对应
        else:
            if r1[1]:
                s="select coalesce((select parent_id from "+tb+" where id=a.parent_id),parent_id) from "+tb+" a where id="+str(r1[1])
                cur.execute(s)
                r2 = cur.fetchone()
                id = r2[0]
    # 单枚标
    elif r[1] == 4:
        data['package'] = _('单枚标')
        data['boxes']['pk'] = code
    # 套标
    if id:
        id = str(id)
        # 箱标数据
        # s = "select code,array_to_string(array(select code from " + tb + " where parent_id=" + id + \
        #    " and package_id=3),',') from " + tb + " where id=" + id + " order by code"

        #2021-01-21
        code_pk=code
        cur.execute("select code from "+tb+" where id="+id)
        r=cur.fetchone()
        if r:
            code_pk=r[0]


        s = "select code,array_to_string(array(select coalesce(" +\
            "(select code from label.lbl_replace_details where code0=a.code),a.code) from " + \
            tb + " a where parent_id=" + id + \
            " and package_id=3),',') from " + tb + " where id=" + id + " order by code"        
        s = "select "+\
            "coalesce((select code_b from label.lbl_abcode where code_a='"+code_pk+"'),'"+code_pk+"'),"+\
            "array_to_string(array(select coalesce(" +\
            "(select code from label.lbl_replace_details where code0=a.code),a.code) from " + \
            tb + " a where parent_id=" + id + \
            " and package_id=3),',') from " + tb + " where id=" + id + " order by code"       


        cur.execute(s)
        r = cur.fetchone()
        data['boxes']['pk'] = r[0]
        if r[1]:
            data['boxes']['related'] = r[1].split(',')
        #cur.execute("select coalesce((select code from label.lbl_replace_details where code0=a.code),a.code) " +\
        #            "from " + tb + " a where parent_id=" + id + " and package_id=1 order by code")
        cur.execute("select coalesce((select code from label.lbl_replace_details where code0=a.code order by id desc limit 1),"+\
            "coalesce((select code_b from label.lbl_abcode where code_a=a.code order by id desc limit 1),a.code)) " +\
            "from " + tb + " a where parent_id=" + id + " and package_id=1 order by code")
        rs = cur.fetchall()
        
        #2020-10-17
        bottlecaps={}

        # 箱瓶二级对应
        if rs:
            for r in rs:
                data['bottles'].append(r[0])
            
            #2020-10-17
            if data['bottles']:
                cur.execute("select label,code,bottle from label.bottlecap where bottle in ('"+"','".join(data['bottles'])+"')")
                for rrr in cur.fetchall():
                    #bottlecaps.append({rrr[2]:rrr[1]})
                    bottlecaps[rrr[2]]=rrr[1]   


        # 箱盒瓶三级对应
        else:
            #cur.execute("select id,coalesce((select code from label.lbl_replace_details where code0=a.code),a.code) " +\
            #    "from " + tb + " a where parent_id=" + id + " and package_id=2 order by code")
            cur.execute("select id,coalesce((select code from label.lbl_replace_details where code0=a.code),"+\
               "coalesce((select code_b from label.lbl_abcode where code_a=a.code),a.code)) " +\
                "from " + tb + " a where parent_id=" + id + " and package_id=2 order by code")
            rs = cur.fetchall()
            for r in rs:
                a = []
                #cur.execute("select coalesce((select code from label.lbl_replace_details where code0=a.code),a.code) " +\
                #    "from " + tb + " a where parent_id=" + str(r[0]) + " order by code")
                cur.execute("select coalesce((select code from label.lbl_replace_details where code0=a.code),"+\
                    "coalesce((select code_b from label.lbl_abcode where code_a=a.code),a.code)) " +\
                    "from " + tb + " a where parent_id=" + str(r[0]) + " order by code")
                for r1 in cur.fetchall():
                    a.append(r1[0])
                data['packets'].append({'code': r[1], 'bottles': a})
                
                #2020-10-17
                if a:
                    cur.execute("select label,code,bottle from label.bottlecap where bottle in ('"+"','".join(a)+"')")
                    for rrr in cur.fetchall():
                        #bottlecaps.append({rrr[2]:rrr[1]})
                        bottlecaps[rrr[2]]=rrr[1]
        data['bottlecaps']=bottlecaps
    else:
        # pass
        id = r[0]
        data['boxes']['pk'] = code    








    #2021-05-03 酒鬼酷客白在线绑定
    if not data['bottles']:  
        cur.execute("select array_to_string(array(select "+\
            "coalesce((select code from label.lbl_replace_details where code0=a.bottle),a.bottle) "+\
            "from label.bottlecap a where label_pk_id="+str(id)+"),',')")
        r=cur.fetchone()
        data['bottles']=r[0].split(',')
                

            


    s="select label_code,(select name from inventory_voucher where id=vtype_id),"+\
        "(select code from inventory_batch where id=batch_id),tm,"+\
        "(select username from company_user where id="+\
            "(select user_id from inventory_batch where id=batch_id)),"+\
        "(select name from product_product where id=product_id),"+\
        "(select name from inventory_storehouse where id=store_id),"+\
        "coalesce((select name from inventory_storehouse where id=store_fr_id),''),"+\
        "(select name from label.lbl_package where id=label_pkg),"+\
        "coalesce((select name from company_company where id=company_to_id),'') "+\
        "from inventory_stkdetails where label_id="+str(id) +" or "+\
            "label_code='"+code+"' order by tm"
    #2020-03-24
    s="select label_code,(select name from inventory_voucher where id=vtype_id),"+\
        "(select code from inventory_batch where id=batch_id),tm,"+\
        "(select username from company_user where id="+\
            "(select user_id from inventory_batch where id=batch_id)),"+\
        "(select name from product_product where id=product_id),"+\
        "(select name from inventory_storehouse where id=store_id),"+\
        "coalesce((select name from inventory_storehouse where id=store_fr_id),''),"+\
        "(select name from label.lbl_package where id=label_pkg),"+\
        "coalesce((select name from company_company where id=company_to_id),''),vtype_id "+\
        "from inventory_stkdetails where label_pk_id in "+\
        "("+str(id)+",coalesce((select coalesce(parent_id,id) from label.t"+code[:4]+" where code='"+code+"'),0)) "+\
        "order by dt,vtype_id"
    #2021-01-19
    s="select coalesce((select code_b from label.lbl_abcode where code_a=label_code),label_code),"+\
        "(select name from inventory_voucher where id=vtype_id),"+\
        "(select code from inventory_batch where id=batch_id),tm,"+\
        "(select username from company_user where id="+\
            "(select user_id from inventory_batch where id=batch_id)),"+\
        "(select name from product_product where id=product_id),"+\
        "(select name from inventory_storehouse where id=store_id),"+\
        "coalesce((select name from inventory_storehouse where id=store_fr_id),''),"+\
        "(select name from label.lbl_package where id=label_pkg),"+\
        "coalesce((select name from company_company where id=company_to_id),''),vtype_id,product_id,is_delete,"+\
        "(select name from company_company where id=company_id) "+\
        "from inventory_stkdetails where ancestor_id="+company_id+" and label_pk_id in "+\
        "("+str(id)+",coalesce((select coalesce(parent_id,id) from label.t"+code[:4]+" where code='"+code+"'),0)) "+\
        "order by id"

    #2022-01-14 酒鬼罗工:酒鬼可以查内参物流
    sComp=" where ancestor_id="+company_id
    if company_id=='1':
        sComp=" where ancestor_id in (1,1644)"
    s="select coalesce((select code_b from label.lbl_abcode where code_a=label_code),label_code),"+\
        "(select name from inventory_voucher where id=vtype_id),"+\
        "(select code from inventory_batch where id=batch_id),"+\
        "tm,"+\
        "(select username from company_user where id="+\
            "(select user_id from inventory_batch where id=batch_id)),"+\
        "(select name from product_product where id=product_id),"+\
        "coalesce((select name from inventory_storehouse where id=store_id),''),"+\
        "coalesce((select name from inventory_storehouse where id=store_fr_id),''),"+\
        "(select name from label.lbl_package where id=label_pkg),"+\
        "coalesce((select name from company_company where id=company_to_id),''),"+\
        "vtype_id,"+\
        "product_id,"+\
        "is_delete,"+\
        "(select name from company_company where id=company_id) "+\
        "from inventory_stkdetails "+sComp+" and label_pk_id in "+\
        "("+str(id)+",coalesce((select coalesce(parent_id,id) from label.t"+code[:4]+" where code='"+code+"'),0)) "+\
        "order by id"
    
    has_outbound=False
    cur.execute(s)
    product_id=None
    for r in cur.fetchall():
        if r[10]==1:
            if r[12]==False:
                product_id=str(r[11])
        elif r[10]==2 and not product_id:
            product_id=str(r[11])
        store_fr=r[6]
        store_to=r[7]
        if r[10]==2:
            has_outbound=True
        if r[1]!='成品转库单':
            store_to=''
        data['stock_dev'].append({
            'label_code': r[0],
            'voucher_type': r[1],
            'voucher_no': r[2],
            'time': r[3].strftime('%Y-%m-%d %H:%M'),
            'user': r[4],
            'product': r[5],
            'store': store_fr,
            'store_fr': store_to,
            'package': r[8],
            'to_company': r[9],
            'fr_company':r[13],
        })

    
    

    if product_id:
        #'product': r[5],

        #2021-06-26 产品信息
        s="select coalesce(c.value,'') val,g.name,g.desc_cn,g.unit,"+\
            "(select coalesce(remark,'') from product_product where id="+product_id+") "+\
            "from "+\
            "(SELECT * FROM product_prdprops where product_id="+product_id+") p "+\
            "left outer join "+\
            "(SELECT * FROM product_productprop where company_id="+str(a_company_id)+") c "+\
            "on p.prd_property_id=c.id "+\
            "left outer join "+\
            "(select * from company_categoryprop) g "+\
            "on c.categoryprop_id=g.id"
        cur.execute(s)
        for r in cur.fetchall():
            data['product_info'][r[1]]={'desc_cn':r[2],'unit':r[3],'value':r[0],'remark':r[4]}
        #2021-08-04
        cur.execute("select coalesce(contents,'') from product_product where id="+product_id)
        r99=cur.fetchone()
        if r99[0]:
            product_contents=urllib.parse.quote(r99[0])
        data['product_info']['contents']=product_contents
    
    
    """
    if int(company_id)==1 and not data['stock_dev']:
        #r = jiugui_local_info(data['boxes']['pk'])
        #2020-04-06
        #r = jiugui_local116(data['boxes']['pk'])

        #2022-03-17
        r=get_jiugui_local(parent_id)

        

        if not r['e']:
            data['product'] = r['product']
            data['stock_dev'] = r['stock_dev']
            if r['boxes']['related']:
                data['boxes'] = r['boxes']
            if r['bottles']:
                data['bottles'] = r['bottles']
        # data['e'] = r['e']
    else:
        if has_outbound==False:
            #d=jiugui_delivery(data['boxes']['pk'])
            #2022-03-17
            d=get_jiugui_local(parent_id)  
            for dev in  d['stock_dev']:
                
                data['stock_dev'].append(dev) 
    """
    if int(company_id)==1:
        if not data['stock_dev']:       
            r=get_jiugui_local(parent_id)            

            if not r['e'] and r[stock_dev]:
                data['product'] = r['product']
                data['stock_dev'] = r['stock_dev']
                if r['boxes']['related']:
                    data['boxes'] = r['boxes']
                if r['bottles']:
                    data['bottles'] = r['bottles']        
        else:
            if has_outbound==False:           
                d=get_jiugui_local(parent_id)  
                for dev in  d['stock_dev']:                
                    data['stock_dev'].append(dev) 
    elif company_id in os_cids:
        d=os_label_outbound(os_cids[company_id],box_code)


    '''
    if not data['stock_dev'] and is_staff:
        #r = jiugui_local_info(data['boxes']['pk'])
        #2020-04-06
        r = jiugui_local116(data['boxes']['pk'])



        if not r['e']:
            data['product'] = r['product']
            data['stock_dev'] = r['stock_dev']
            if r['boxes']['related']:
                data['boxes'] = r['boxes']
            if r['bottles']:
                data['bottles'] = r['bottles']
        # data['e'] = r['e']
    '''
    cur.close()

   
    
    return JsonResponse(data)


def period_close(yr, mn, is_initial=False):
    yr = str(yr)
    mn = str(mn)
    cur = connection.cursor()
    if not is_initial:
        for c in Company.objects.filter(inv_mgt=True):
            cur.execute("delete from logistics.inventory_stk0 where " +
                        "company_id=" + str(c.id) + " and yr=" + yr + " and mn=" + mn)
    s = "insert into logistics.inventory_stk0(company_id,product_id,store_id,yr,mn) " + \
        ""



#2020-05-13
@csrf_exempt
def app_label_replace(request):
    data = {'e': '', 'cnt': 0}
    k = sK    
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    codes=[]
    rs=json.loads(request.body)
    u_id=str(rs['user_id'])
    c_id=str(rs['company_id'])
    for r in rs['codes']:
        codes.append("('"+r[0]+"','"+r[1]+"')")
    cur=connection.cursor()
    cur.execute("create temp table tmp(code0 character varying(20),code character varying(20))")
    cur.execute("insert into tmp(code0,code) values "+",".join(codes))
    # 写入BATCH
    s = "insert into label.lbl_replace_batch(user_id,company_id,txt_file) values " + \
            "(" + u_id + "," + c_id + ",'扫码枪上传') returning id"
    cur.execute(s)
    id = str(cur.fetchone()[0])

    #写入LOG
    s = "INSERT INTO label.lbl_replace_log(code0, code, batch_id, company_id, label_id) " + \
        "select code0,code," + id + "," + c_id + ",null from tmp" 
    cur.execute(s)
    

    #2021-09-16 标签检查，如果是AB标，统一改为A标
    s="update tmp set "+\
        "code0=coalesce((select code_a from label.lbl_abcode where code_b=code0),code0),"+\
        "code= coalesce((select code_a from label.lbl_abcode where code_b=code),code)"
    cur.execute(s)

    #2021-09-18 标签替换明细内，不写入标签ID及父ID，如AB标的单枚标只有code_a code_b映射，没有基础数据
    #cur.execute("select left(code0,4) from tmp group by left(code0,4)")
    #rs = cur.fetchall()
    #for r in rs:
    #    cur.execute("select to_regclass('label.t" + r[0] + "')")
    #    r0 = cur.fetchone()
    #    if r0[0]:            
    #        s = "INSERT INTO label.lbl_replace_details(code0, code, batch_id, company_id, label_id,parent_id) " + \
    #            "select code0,code," + id + "," + c_id + "," + \
    #            "(select id from label.t" + r[0] + " where left(code0,4)='" + r[0] + "' and code=code0)," + \
    #            "(select parent_id from label.t" + r[0] + " where left(code0,4)='" + r[0] + "' and code=code0) " + \
    #            "from tmp on conflict (code0) do update set "+\
    #            "code=EXCLUDED.code,batch_id=EXCLUDED.batch_id,company_id=EXCLUDED.company_id,label_id=EXCLUDED.label_id,parent_id=EXCLUDED.parent_id"    
    #        cur.execute(s)
    #        data['cnt']=data['cnt']+cur.rowcount 
    s="INSERT INTO label.lbl_replace_details(code0,code,batch_id,company_id) select code0,code,"+id+","+c_id+" from tmp"
    cur.execute(s)
    data['cnt']=data['cnt']+cur.rowcount 
    return JsonResponse(data)    



#@login_required
@tj_login_required
@csrf_exempt
def upload_label_replace(request):
    data = {'files': [], 'e': ''}
    dt = datetime.datetime.now()
    u_id = str(request.user.id)
    c = request.user.company
    c_name = c.name
    p = settings.MEDIA_ROOT + '/' + c_name + '/txt/label_replace/' +  \
        str(dt.year) + str(dt.month).zfill(2) + str(dt.day).zfill(2)
    if not os.path.exists(p):
        os.makedirs(p)
    c_id = str(c.id)
    files = request.FILES.getlist('files')
    cur = connection.cursor()
    cur.execute("create temp table tmp(code0 character varying(20),code character varying(20))")
    #2019-12-23
    #替换要改成一行行读取
    for f in files:
        fn = f.name
        with open(p + '/' + fn, 'wb+') as destination:
            for chunk in f.chunks():
                destination.write(chunk)
        f.seek(0)
        
        cur.execute("truncate table tmp")
        cur.copy_from(f, 'tmp', sep=',', null='')
        # 写入BATCH
        s = "insert into label.lbl_replace_batch(user_id,company_id,txt_file) values " + \
            "(" + u_id + "," + c_id + ",'" + fn + "') returning id"
        cur.execute(s)
        id = str(cur.fetchone()[0])
        cur.execute("select left(code0,4) from tmp group by left(code0,4)")
        rs = cur.fetchall()
        for r in rs:
            cur.execute("select to_regclass('label.t" + r[0] + "')")
            r0 = cur.fetchone()
            if r0[0]:
                s = "INSERT INTO label.lbl_replace_log(code0, code, batch_id, company_id, label_id) " + \
                    "select code0,code," + id + "," + c_id + "," + \
                    "(select id from label.t" + r[0] + "  where left(code0,4)='" + r[0]+"' and code=code0) " + \
                    "from tmp"
                cur.execute(s)
                s = "INSERT INTO label.lbl_replace_details(code0, code, batch_id, company_id, label_id,parent_id) " + \
                    "select code0,code," + id + "," + c_id + "," + \
                    "(select id from label.t" + r[0] + " where left(code0,4)='" + r[0] + "' and code=code0)," + \
                    "(select parent_id from label.t" + r[0] + " where left(code0,4)='" + r[0] + "' and code=code0) " + \
                    "from tmp" 

                    #"from tmp on conflict (code0) do update set code=excluded.code,batch_id=" + id
                cur.execute(s)

        s = "select count(*)," + \
            "(select count(*) from label.lbl_replace_log where label_id is not null and batch_id=" + id + ") from tmp"
        cur.execute(s)
        r = cur.fetchone()
        tt = r[0]
        ok = r[1]
        s = ''
        if tt == ok:
            s = ",tm_handled=now()"
        cur.execute("update label.lbl_replace_batch set cnt_tt=" + str(tt) + ",cnt_ok=" + str(ok) + s + " where id="+id)
        data['files'].append({'txt_name': fn, 'total': tt, 'ok': ok})


        #2022-03-16 发送任务到异步任务服务器 这部分代码有问题，先停用
        #try:
        #    result=tasks.jiugui_replace.delay(id)
        #except Exception:
        #    pass

    return JsonResponse(data)



def list_unhandled_batch(request, company_id):
    data = []
    cur = connection.cursor()
    s = "select a.code,a.batch_no,a.tm,"+\
        "(select username from logistics.company_user where id=a.user_id)," + \
        "(select name from logistics.product_product where id=a.product_id)," + \
        "(select name from logistics.inventory_storehouse where id=a.store_fr_id)," + \
        "(select name from logistics.inventory_storehouse where id=a.store_to_id)," + \
        "(select name from logistics.company_company where id=a.company_to_id)," + \
        "(select name from logistics.inventory_voucher where id=a.voucher_id)," + \
        "(select count(*) from logistics.inventory_batchdetails where batch_id=a.id)," + \
        "a.id from " + \
        "(select code,batch_no,product_id,store_fr_id,store_to_id,voucher_id,company_to_id,tm,id,user_id " + \
            "from logistics.inventory_batch where company_fr_id=" + company_id + " and tm_handled is null) a"
    cur.execute(s)
    for r in cur.fetchall():
        data.append({
            'bill_number': r[0],
            'time': r[2].strftime('%Y-%m-%d %H:%M:%S'),
            'user': r[3],
            'product': r[4],
            'store': r[5],
            'agent': r[7],
            'bill_type': r[8],
            'records_count': r[9],
            'id':r[10]
        })
    return render(request, 'inventory/inventory_unhandled.html',{'data':data})


@tj_login_required
def handle_batch(request,batch_id):
    data={'e':'','cnt':0}
    bths=Batch.objects.filter(id=str(batch_id))
    if not bths:
        data['e']='BATCH ID:'+batch_id+'  不存在'
        return JsonResponse(data) 
    b=bths[0]

    



    #标签是否已有基础数据
    cur=connection.cursor()
    tt=0
    e_tt=0
    
    #2021-05-10 是否有垛标数据
    if b.stacks and b.vtype_id==2:
        s="insert into inventory_batchdetails(batch_id,label_code,label_id,label_pkg,tm,label_pk_id,company_id,ancestor_id,err,product_id,stack_id) " +\
            "select "+str(b.id)+",label_code,label_id,label_pkg,now(),label_pk_id,"+str(b.company_id)+","+str(b.ancestor_id)+",null,product_id,stack_id from inventory_stackdetails s "+\
            "where stack_id in (select id from inventory_stack s where code in ('"+"','".join(b.stacks)+"')) "+\
            "and (select id from inventory_batchdetails where batch_id="+str(b.id)+" and label_id=s.label_id limit 1) is null"
        cur.execute(s) 

    # 2022-08-08 如酒鬼酒，标签替换（返工，两个箱标全部替换），取原箱码
    s="update inventory_batchdetails set label_code=coalesce("+\
            "(select code0 from label.lbl_replace_details where code=label_code order by id desc limit 1),label_code) "+\
        "where batch_id="+batch_id
    cur.execute(s)


    #cur.execute("select coaleace((select tbname from label.lbl_tbcross where segment=left(label_code,4)),left(label_code,4)),"+\
    #    "count(*) from logistics.inventory_batchdetails where batch_id="+batch_id+" group by left(label_code,4)")
    s="select coalesce((select tbname from label.lbl_tbcross where segment=a.rg),'t'||a.rg),a.cnt,a.rg from "+\
        "(select left(label_code,4) rg,count(*) cnt from  logistics.inventory_batchdetails "+\
            "where batch_id="+batch_id+" group by left(label_code,4)) a"
    cur.execute(s)



    rs = cur.fetchall()
    for r in rs:
        cur.execute("select to_regclass('label." + r[0] + "')")
        r0 = cur.fetchone()
        if r0[0]:
            tt=tt+r[1]
            s="update logistics.inventory_batchdetails c set "+\
                "label_id=b.id,"+\
                "label_pk_id=coalesce(b.parent_id,b.id),"+\
                "label_pkg=b.package_id "+\
                "from "+\
                "(select id,label_code from logistics.inventory_batchdetails where "+\
                    "batch_id="+batch_id+" and left(label_code,4)='"+r[2]+"') a "+\
                "left outer join "+\
                "label."+r[0]+" as b "+\
                "on b.code=a.label_code "+\
                "where c.id=a.id"            
            cur.execute(s)



    s="select count(*) from logistics.inventory_batchdetails "+\
        "where batch_id="+batch_id+" and label_id is null" 
    cur.execute(s)  
    r=cur.fetchone()
    e_tt=r[0]   
    if e_tt:
        data['e']=str(e_tt)+'条记录缺少标签基础数据（记录总数'+str(tt)+'）'   
    
    #删除已有记录
    cur.execute("delete from logistics.inventory_stkdetails where batch_id="+batch_id)


    if b.vtype_id==5:
        sql = "INSERT INTO inventory_stkdetails (vtype_id,batch_id,company_to_id,company_id,"+\
            "label_code,label_id,label_pkg,product_id,store_fr_id,store_to_id,store_id,dt,tm,is_delete,label_pk_id,ancestor_id) "+\
            "select a.vtype_id,a.id,a.company_to_id,company_id,b.label_code,b.label_id,"+\
            "b.label_pkg,"+\
            "(select product_id from inventory_stkdetails where vtype_id=1 and label_pk_id=b.label_pk_id limit 1),"+\
            "a.store_fr_id,a.store_to_id,a.store_fr_id,a.dt,a.tm,true,b.label_pk_id,b.ancestor_id from "+\
            "(select batch_id,label_id,label_code,label_pkg,label_pk_id,ancestor_id from inventory_batchdetails "+\
                "where batch_id="+batch_id+" and label_id is not null "+\
            ") b "+\
            "left outer join "+\
            "(select * from inventory_batch where id="+batch_id+") a "+\
            "on b.batch_id=a.id "+\
            "where (select product_id from inventory_stkdetails where vtype_id=1 and label_pk_id=b.label_pk_id limit 1) is not null"
    else:
        sql = "INSERT INTO inventory_stkdetails (vtype_id,batch_id,company_to_id,company_id,"+\
            "label_code,label_id,label_pkg,product_id,store_fr_id,store_to_id,store_id,dt,tm,label_pk_id,ancestor_id) "+\
            "select a.vtype_id,a.id,a.company_to_id,company_id,b.label_code,b.label_id,b.label_pkg,"+\
            "coalesce(b.product_id,(select product_id from inventory_batch where id=a.id)),"+\
            "a.store_fr_id,a.store_to_id,a.store_fr_id,a.dt,a.tm,b.label_pk_id,b.ancestor_id from "+\
            "(select batch_id,label_id,label_code,label_pkg,label_pk_id,product_id,ancestor_id from inventory_batchdetails "+\
                "where batch_id="+batch_id+" and label_id is not null "+\
            ") b "+\
            "left outer join "+\
            "(select * from inventory_batch where id="+batch_id+") a "+\
            "on b.batch_id=a.id" 
    
    cur.execute(sql+" returning id")
    data['cnt']=cur.rowcount
    if not e_tt:
        b.tm_handled=datetime.datetime.now()
        b.dt_handled=datetime.datetime.now()
        b.save()


    #入库退标，对原入库标签做删除标记(一箱可能贴2个标签，即入库扫的是一枚标，退库时可能是同一箱的另一枚)
    if b.vtype_id==5:      
        s="update inventory_stkdetails set is_delete=true where vtype_id=1 and "+\
            "label_pk_id in (select label_pk_id from logistics.inventory_batchdetails where batch_id="+batch_id+")"
        cur.execute(s)
    return JsonResponse(data)    


#保存到旧物流，透云取数
def delivery_ty(batch_id,is_test=False): 
    data={'summary':0,'details':0}
    cur=connection.cursor()
    cn_ty=psycopg2.connect(settings.TY_WULIU_STR)
    cur_ty=cn_ty.cursor()
    bs=Batch.objects.filter(id=batch_id)
    if bs:
        b=bs[0]
        yr=str(b.tm.year)
        agt=Company.objects.get(id=b.company_to_id)        
        cur_ty.execute("select id from customer_company where name='" + agt.name + "' and parent_id=7 and parent_compid=99")
        r=cur_ty.fetchone()
        if not r:
            ty_agent('add', agt)
        cur_ty.execute("select id from customer_company where name='" + agt.name + "' and parent_id=7 and parent_compid=99")
        r=cur_ty.fetchone()
        if r:
            cid=str(r[0])
            #pid=str(settings.TY_PRODUCTS_ID[b.product_id]['wl_id'])
            #2021-02-03

            cur.execute("select wl_product_id from logistics.z_jgty_product where product_id="+str(b.product_id))
            r=cur.fetchone()
            pid=str(r[0])  
            
            
            s="select count(*) from inventory_batchdetails where batch_id="+str(b.id)
            cur.execute(s)
            r=cur.fetchone()
            tt='0'
            if r:
                tt=str(r[0])   
                data['summary']=r[0]
            if is_test:
                tm="'2019-01-01 00:00:00'"
            else:
                tm='now()'
            bno="null"
            if b.code:
                bno="'"+b.code+"'"
            s="INSERT INTO public.y"+yr+"("+\
                "userid,fhpici,fhkey,xiangnumber,lqty,fhtypeid,tm,frcompid,frstoid,pid,tocompid,bill_no) VALUES ("+\
                "178,'000','000',"+tt+","+tt+",3,"+tm+",99,238,"+pid+","+cid+","+bno+\
            ") returning id"
            cur_ty.execute(s)
            r=cur_ty.fetchone()
            sid=str(r[0])
            cn_ty.commit()
                        



            s="select left(label_code,4) from inventory_stkdetails where batch_id="+str(b.id)+\
                " group by left(label_code,4)"
            cur.execute(s)
            a=[]
            rs=cur.fetchall()
            for r in rs:
                #2021-05-22 扫码枪误读 可能会有不存在的号段
                s="select count(*) from information_schema.tables where table_schema='public' and table_type='BASE TABLE' and table_name='z"+r[0]+"'"                
                #print(s)                
                cur_ty.execute(s)
                rr=cur_ty.fetchone()  
                if rr[0]:
                    cur.execute("select label_code from inventory_stkdetails where "+\
                        "batch_id="+str(b.id)+" and left(label_code,4)='"+r[0]+"'")
                    rs1=cur.fetchall()
                    for r1 in rs1:
                        a.append("("+sid+",(select id from z"+r[0]+" where code='"+r1[0]+"'),'"+r1[0]+"')")
            if a:
                s="insert into delivery_details(summary_id,label_id,label_code)"+\
                    " values "+",".join(a) 
                cur_ty.execute(s)
                cn_ty.commit()
                cur_ty.execute("select count(*) from delivery_details where summary_id="+sid)
                r=cur_ty.fetchone()
                data['details']=r[0]
    return data



@login_required
def send_to_wuliu(request,batch_id):
    #def delivery_ty(batch_id,is_test=False):  

    return JsonResponse(delivery_ty(batch_id))


#2020-01-07
@csrf_exempt
def app_label_check(request):
    data={'e':'','code':'','package_id':0,'label_pk_id':0,'err_code':0,'product_id':0,'product_name':''}
    if request.method=='GET':
        data['e']='invalid method'
        data['err_code']=10003
        return JsonResponse(data)
    
    STRICT=True #只有上级发过货才可以入库，只有入库后才可以扫码出库    
    #2020-04-23
    c=request.POST.get('code','')
    company_id=request.POST.get('company_id','')
    vtype_id=str(request.POST.get('vtype_id',''))  
    user_id=request.POST.get('user_id','')    
    
    #2020-04-23
    data['code']=c
    if not c or not company_id or not vtype_id:
        data['e']='parameter missing'
        data['err_code']=10000
        return JsonResponse(data)    
    

    companys=Company.objects.filter(id=int(company_id))
    if not companys:
        data['e']='invalid company id'
        data['err_code']=10000
        return JsonResponse(data)
    company=companys[0]   

    cfgs=CompanyCfg.objects.filter(company_id=company.ancestor_id)
    if not cfgs:
        data['e']='company configurations missing'
        data['err_code']=10000
        return JsonResponse(data)
    cfg=cfgs[0]    
    cur=connection.cursor()



    #2020-07-15
    s="select parent_id,ancestor_id,"+\
        "coalesce((select name from company_company where id=a.parent_id),''),"+\
        "coalesce((select name from company_company where id=a.ancestor_id),'') "+\
        "from company_company a where id="+company_id
    cur.execute(s)
    r=cur.fetchone()
    #a_id=str(company.ancestor_id) 
    #p_id=str(company.parent_id)
    p_id=str(r[0])
    a_id=str(r[1]) 
    p_name=r[2]
    a_name=r[3]
    c_id=str(company_id)       

    #2020-05-30
    #内参6月份活动，只要内参给父级发过货，终端店就可以扫码入库
    #dt=datetime.datetime.now().strftime('%Y-%m-%d')
    #if dt[:7]=='2020-06' and a_id=='1644':
    #    STRICT=False


    """
    #主箱标ID
    lbl_pk_id=0
    #酒鬼防伪码以40开头
    if c[:2]=='40':        
        cur.execute("SELECT wl_code FROM label.lbl_fw_wl where fw_code='"+c+"'")
        r=cur.fetchone()
        if r:
            c=r[0]
        else:
            r=requests.get('http://china315net.com:35222/wuliu/47/fw/wuliu/?fw_code='+c)
            d=r.json()
            if d['wl']:
                c=d['wl']
    data['code']=c   

    #2021-02-19 BA表对应
    cur.execute("select coalesce((select code_a FROM label.lbl_abcode where code_b='"+c+"'),'"+c+"')")
    r=cur.fetchone()
    c=r[0]

    tb='label.t'+c[:4]
    #2020-07-27 是否跨段动态绑定,是否为第三方标签
    s="select 'label.'||tbname from label.lbl_tbcross where segment='"+c[:4]+"' "+\
        "union all "+\
        "select 'label.thirdparty' from label.thirdparty where code='"+c+"'"

    #cur.execute("select tbname from label.lbl_tbcross where segment='"+c[:4]+"'")
    cur.execute(s)
    rrr=cur.fetchone()
    if rrr:
        #tb='label.'+rrr[0]  
        tb=rrr[0]

    s="select package_id,coalesce(parent_id,id) from "+tb+" where code='"+c+"'"   
    try:
        cur.execute(s)
        r=cur.fetchone()
        if not r[0]:
            data['e']=_('标签号码未激活')
            data['err_code']=20001
            return JsonResponse(data)
        else:
            data['package_id']=r[0]
            data['label_pk_id']=r[1]
            lbl_pk_id=str(r[1])
            
    except Exception:
        data['e']=_('标签号码错误')
        data['err_code']=20000
        return JsonResponse(data)     

    """

    #2022-06-14
    q=LabelQuery(company_id,c)
    if not q.infor['label_pk_id']:
        data['e']='标签号码错误'
        return JsonResponse(data)
   

    data['package_id']=q.package['id'] 
    data['label_pk_id']=q.infor['label_pk_id']
    lbl_pk_id=str(q.infor['label_pk_id'])


    #2022-03-17 如果已有主箱标ID，取出对应产品名称
    #取标签产品ID
    s="select product_id,"+\
        "(select name from product_product where id=product_id) from inventory_stkdetails where label_pk_id="+lbl_pk_id+\
            " and company_id="+a_id+" and is_delete=false and vtype_id in (1,2) order by vtype_id limit 1"
    cur.execute(s)
    r=cur.fetchone()
    if r:
        data['product_id']=r[0]
        data['product_name']=r[1]




    if vtype_id in ['1','2']:
        #箱标,瓶标同一标签都只能入/出一次
        s="select label_pkg,tm from inventory_stkdetails where vtype_id="+vtype_id+\
            " and label_code='"+c+"' and company_id="+c_id
        s="select label_pkg,tm,"+\
            "(select vtype_id from inventory_stkdetails where company_id="+c_id+" and label_code='"+c+"' order by id desc limit 1) "+\
            "from inventory_stkdetails where vtype_id="+vtype_id+\
            " and label_code='"+c+"' and company_id="+c_id

        cur.execute(s)
        r=cur.fetchone()
        if r:
            #最后一次不是销售退库,也不是标签退库
            if r[2] not in [4,5,9]:
                t1=''
                if vtype_id=='1':
                    t1=_('此标签已入库')
                elif vtype_id=='2':
                    t1=_('此标签已出库')
                data['err_code']=10001
                data['e']=t1+'('+r[1].strftime('%Y-%m-%d %H:%M:%S')+')'
                return JsonResponse(data)

        #2021-07-29 工厂用小程序入库出库标签检查
        if company.level.sn==0:
            #取标签产品ID
            #s="select product_id,"+\
            #    "(select name from product_product where id=product_id) from inventory_stkdetails where label_pk_id="+lbl_pk_id+\
            #    " and company_id="+a_id+" and is_delete=false and vtype_id in (1,2) order by vtype_id limit 1"
            #cur.execute(s)
            #r=cur.fetchone()
            #if r:
            #    data['product_id']=r[0]
            #    data['product_name']=r[1]
            
            cur.close()
            return JsonResponse(data)



        #瓶标
        if data['package_id']==1:
            if vtype_id=='1':
                if cfg.lv1_pkg_split==0:
                    data['e']=_('请扫描箱标入库')
                    data['err_code']=10002
                    return JsonResponse(data)
            elif vtype_id=='2':
                if company.level_id==2: #1级经销商
                    if cfg.lv1_pkg_split==0:
                        data['e']=_('请扫描箱标出库')
                        data['err_code']=10002
                        return JsonResponse(data)
                s="select id from inventory_stkdetails where vtype_id=1 and label_pk_id="+lbl_pk_id+" and company_id="+c_id
                cur.execute(s)
                r=cur.fetchone()
                if cfg.outbound_cretiria_lv2==0:
                    if not r:
                        #if cfg.lv1_pkg_split==0:
                            data['e']=_('此瓶所在箱没有入库记录')
                            data['err_code']=10002
                            return JsonResponse(data)
                #所在箱是否出过库
                cur.execute("select label_code,tm from inventory_stkdetails where vtype_id=2 and label_pkg=3 and label_pk_id="+lbl_pk_id+" and company_id="+c_id)
                r=cur.fetchone()
                if r:
                    data['e']=_('包含此瓶的箱标已出库')+'('+r[0]+":"+r[1].strftime('%Y-%m-%d %H:%M:%S')+')'
                    data['err_code']=10001
                    return JsonResponse(data)
        #箱标,单枚标
        elif data['package_id'] in (3,4):
            #关联箱标出/入库检查
            s="select label_pkg,tm,"+\
                "(select vtype_id from inventory_stkdetails where company_id="+c_id+" and label_pk_id="+lbl_pk_id+" order by id desc limit 1) "+\
                " from inventory_stkdetails where vtype_id="+vtype_id+" and label_pk_id="+lbl_pk_id+" and company_id="+c_id

            cur.execute(s)
            r=cur.fetchone()
            if r:
                #最后一次不是销售退库,也不是标签退库
                if r[2] not in [4,5]:

                    t1=''
                    if vtype_id=='1':
                        t1=_('此箱已入库')
                    elif vtype_id=='2':
                        t1=_('此箱已出库')
                    data['err_code']=10001
                    data['e']=t1+'('+r[1].strftime('%Y-%m-%d %H:%M:%S')+')'
                    return JsonResponse(data)

            if vtype_id=='1':
                #inbound_cretiria_lv1 一级经销入库规则:
                #(0, _('严格(工厂有发货)')),
                #(1, _('中等(工厂有入库)')),
                #(2, _('不限制')),),default=0)

                #inbound_cretiria_lv2 二级经销入库规则:
                #(0, _('严格(父级有发货)')),
                #(1, _('中等(父级有入库)')),
                #(2, _('宽松(工厂有发货)')),
                #(3, _('超宽松(工厂有入库)')),
                #(4, _('不限制')),),default=0)

                if company.level.id==2:     #一级经销商入库
                    if cfg.inbound_cretiria_lv1==0:
                        sErr='未查询到 "'+a_name+'" 发货记录'
                        s="select id from inventory_stkdetails where vtype_id=2 and company_id="+a_id+" and company_to_id="+c_id+" and label_pk_id="+lbl_pk_id+" limit 1"
                    elif cfg.inbound_cretiria_lv1==1:
                        sErr='未查询到 "'+a_name+'" 入库记录'
                        s="select id from inventory_stkdetails where vtype_id=1 and company_id="+a_id+" and label_pk_id="+lbl_pk_id+" limit 1"
                    else:
                        sErr=''
                        s="select 1"
                else:                       #二级以上经销商入库
                    if cfg.inbound_cretiria_lv2==0:
                        sErr='未查询到 "'+p_name+'" 或总部 发货记录'
                        #s="select id from inventory_stkdetails where vtype_id=2 and company_id="+p_id+" and company_to_id="+c_id+" and label_pk_id="+lbl_pk_id+" limit 1"
                        
                        #2022-05-24
                        s="select id from inventory_stkdetails where vtype_id=2 and company_to_id="+c_id+"  "+\
                             "and company_id in ("+p_id+","+a_id+") and label_pk_id="+lbl_pk_id+" limit 1"
                    elif cfg.inbound_cretiria_lv2==1:
                        sErr='未查询到 "'+p_name+'" 入库记录'
                        s="select id from inventory_stkdetails where vtype_id=1 and company_id="+p_id+" and label_pk_id="+lbl_pk_id+" limit 1"
                    elif cfg.inbound_cretiria_lv2==2:
                        sErr='未查询到 "'+a_name+'" 发货记录'
                        s="select id from inventory_stkdetails where vtype_id=2 and company_id="+a_id+" and label_pk_id="+lbl_pk_id+" limit 1"
                    elif cfg.inbound_cretiria_lv2==3:
                        sErr='未查询到 "'+a_name+'" 入库记录'
                        s="select id from inventory_stkdetails where vtype_id=1 and company_id="+a_id+" and label_pk_id="+lbl_pk_id+" limit 1"
                    else:
                        sErr=''
                        s="select 1"
                #一级经销商系统已自动做入库
                #if STRICT:
                #    if company.level==2:
                #        sErr='未查询到 "'+a_name+'" 发货记录'
                #    else:
                #        sErr='未查询到 "'+p_name+'" 发货记录'
                #    s="select id from inventory_stkdetails where vtype_id=2 and company_id="+p_id+" and company_to_id="+c_id+" and label_pk_id="+lbl_pk_id+" limit 1"
                #else:
                #    #工厂给一级的发货，系统已自动做了一级入库,一级没有入库操作      #工厂是否给一级发过货
                #    sErr='未查询到 "'+a_name+'" 到 "'+p_name+'" 的发货记录'
                #    s="select id from inventory_stkdetails where vtype_id=2 and company_id="+a_id+" and company_to_id="+p_id+" and label_pk_id="+lbl_pk_id+" limit 1"

                cur.execute(s)
                r=cur.fetchone()
                if not r:
                    data['e']=sErr
                    data['err_code']=10001
                    return JsonResponse(data)
            elif vtype_id=='2':
                #outbound_cretiria_lv2=models.SmallIntegerField(_('二级经销出库库规则'),choices=(
                #    (0, _('严格(入库后才能出库)')),
                #    (1, _('中等(父级有发货)')),
                #    (2, _('宽松(工厂有发货)')),
                #    (4, _('不限制')),),default=0)
                #是否已入库
                s="select id from inventory_stkdetails where vtype_id=1 and label_pk_id="+lbl_pk_id+" and company_id="+c_id
                cur.execute(s)
                r=cur.fetchone()
                if not r:
                    #2020-11-03
                    if company.level_id==2:
                        #if cfg.inbound_cretiria_lv1==0:
                        #2021-02-07
                        if cfg.outbound_cretiria_lv1==0:
                            data['e']=_('请先将此箱标入库后再扫码出库')
                    else:
                        if cfg.outbound_cretiria_lv2==0:
                            data['e']=_('请先将此箱标入库后再扫码出库')
                        #data['err_code']=10004
                    if data['e']:
                        return JsonResponse(data)
                #是否出过库
                #s="select label_code,tm,label_pkg,"+\
                #    "(select vtype_id from inventory_stkdetails where company_id="+c_id+" and label_pk_id="+lbl_pk_id+" order by id desc limit 1) "+\
                #    "from inventory_stkdetails where vtype_id=2 and label_pk_id="+lbl_pk_id+" and company_id="+c_id
                #cur.execute(s) 
                #2021-12-27 最后一笔记录的单据性质
                s="select b.label_code,b.tm,b.label_pkg,v.direction,v.name from "+\
                    "(select label_code,tm,label_pkg,vtype_id from inventory_stkdetails where label_pk_id="+lbl_pk_id+\
                        "and company_id="+c_id+" order by id desc limit 1) b "+\
                    "left outer join "+\
                    "(select id,name,direction from inventory_voucher) v "+\
                    "on b.vtype_id=v.id"
                cur.execute(s)
                r=cur.fetchone()
                if r:                   
                    if r[3]<0:
                        if r[2] in (3,4):
                            t1='此箱已做'+r[4]
                        else:
                            t1='此箱已被拆箱'+r[4]
                        data['e']=t1+'('+r[0]+":"+r[1].strftime('%Y-%m-%d %H:%M:%S')+')'
                        data['err_code']=10000
                        return JsonResponse(data)
    elif vtype_id=='4': #2021-12-23
        data['from_agent_id']=0
        agent_id=request.POST.get('agent_id','0')        
        cur.execute("select coalesce((select name from company_company where id="+str(agent_id)+"),'未知门店')")
        r=cur.fetchone()        
        agent_name=r[0]
        #首先判断是否已有退货记录               
        s="select a.id,a.label_code,a.label_pkg,to_char(a.tm,'yyyy-mm-dd HH24:MI:SS'),"+\
            "(select max(id) from inventory_stkdetails where company_id="+c_id+" and vtype_id=2 and is_delete=false) "+\
            "from "+\
            "(select id,tm,label_pkg,label_code,company_to_id from inventory_stkdetails where company_id="+c_id+" and vtype_id=4 "+\
                "and label_pk_id="+lbl_pk_id+" and is_delete=false order by id desc limit 1"+\
            ") a"                
        cur.execute(s)
        r=cur.fetchone()        
        if r:
            if r[0]>r[4]:
                #有退货
                if data['package_id']==1:
                    if r[2]==1:
                        if r[1]==c:
                            data['e']='此瓶已于'+r[3]+"退货"
                            return JsonResponse(data)
                        elif r[2]==3:
                            data['e']='此瓶所在箱已于'+r[3]+"退货"
                            return JsonResponse(data)
                elif data['package_id'] in (3,4): #箱标，单枚标  
                    if r[2] in (3,4):
                        data['e']='此箱已于'+r[3]+"退货"
                        return JsonResponse(data)
                    elif r[2]==1:
                        data['e']='此箱已有瓶标于'+r[3]+"退货"
                        return JsonResponse(data)   
        #(0, _('严格(必须是发给当前终端的产品)')),
        #(1, _('中等(经销商有发货记录)')), 
        #(2, _('不限制')),),default=2) 
        err=''
        if data['package_id']==1:
            p='瓶'
        else:
            p='箱'
        if cfg.terminal_return==0: 
            err='此'+p+'没有给'+agent_name+'的发货记录'
            s="select tm from inventory_stkdetails where company_id="+c_id+" and vtype_id=2 "+\
                "and label_pk_id="+lbl_pk_id+" and company_to_id="+str(agent_id)
        elif cfg.terminal_return==1:
            err='没有此'+p+'的发货记录'
            s="select tm from inventory_stkdetails where company_id="+c_id+" and vtype_id=2 "+\
                "and label_pk_id="+lbl_pk_id
        else:
            s="select 1"
        cur.execute(s)
        r=cur.fetchone()
        if not r:
            data['e']=err
            return JsonResponse(data) 
        #2021-12-24 取最后一次发货经销
        s="select company_to_id from inventory_stkdetails where label_pk_id="+lbl_pk_id+\
            " and company_id="+c_id+" and vtype_id=2 order by id desc limit 1"      
        cur.execute(s)
        r=cur.fetchone()
        if r:
            if r[0]:
                data['from_agent_id']=r[0]

    #2020-10-19 取标签产品ID
    s="select product_id,"+\
        "(select name from product_product where id=product_id) from inventory_stkdetails where label_pk_id="+lbl_pk_id+\
        " and company_id="+a_id+" and vtype_id in (1,2) order by vtype_id limit 1"      
    cur.execute(s)
    r=cur.fetchone()
    if r:
        data['product_id']=r[0]
        data['product_name']=r[1]
    

    return JsonResponse(data)          
    
    


def app_stock(request,company_id):
    data={'e':'','stock':[]}
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data) 
    aids=request.GET.get('agent_ids','')
    cur=connection.cursor()

    if aids:
        pass
    else:
        sWhere=" where company_id="+company_id    
        s="select (select name from product_product where id=b.product_id),"+\
            "b.x,b.h,b.p,b.product_id from "+\
            "(select a.product_id,sum(a.x) x,sum(a.h) h,sum(a.p) p from "+\
                "(select product_id,"+\
                    "case when label_pkg in (3,4) then "+\
                        "case when vtype_id in (2,5) then -1 else 1 end "+\
                    "else 0 end x,"+\
                    "case when label_pkg=2 then "+\
                        "case when vtype_id in (2,5) then -1 else 1 end "+\
                    "else 0 end h,"+\
                    "case when label_pkg=1 then "+\
                        "case when vtype_id in (2,5) then -1 else 1 end "+\
                    "else 0 end p "+\
                    "from inventory_stkdetails"+sWhere+\
                ") a "+\
            "group by a.product_id) b "+\
            "order by name"   
        #2021-12-27
        s="select (select name from product_product where id=b.product_id),"+\
            "b.x,b.h,b.p,b.product_id from "+\
            "(select a.product_id,sum(a.x) x,sum(a.h) h,sum(a.p) p from "+\
                "(select product_id,"+\
                    "case when label_pkg in (3,4) then "+\
                        "(select direction from inventory_voucher where id=vtype_id) "+\
                    "else 0 end x,"+\
                    "case when label_pkg=2 then "+\
                        "(select direction from inventory_voucher where id=vtype_id) "+\
                    "else 0 end h,"+\
                    "case when label_pkg=1 then "+\
                         "(select direction from inventory_voucher where id=vtype_id) "+\
                    "else 0 end p "+\
                    "from inventory_stkdetails"+sWhere+\
                ") a "+\
            "group by a.product_id) b "+\
            "order by name"  
    
        cur.execute(s)
    
        for r in cur.fetchall():
            qty=''
            a=[]
            if r[1]:
                a.append(str(r[1])+'箱')
            if r[2]:
                a.append(str(r[2])+'盒')
            if r[3]:
                a.append(str(r[3])+'瓶')
            if a:
                qty=",".join(a)        
            data['stock'].append({
                "product":r[0],
                "qty_x":r[1],
                "qty_h":r[2],
                "qty_p":r[3],
                "qty":qty,
                "product_id":r[4]
            })
    cur.close()
    return JsonResponse(data)


@login_required
def children_stock(request):
    data={'e':'','stock':[]}
    cs=Company.objects.filter(id=str(request.user.company.id))
    if not cs:
        data['e']=_('无效帐号')
    else:
        c=cs[0]
        if c.level.sn==0:
            sWhere=" where ancestor_id="+str(c.ancestor_id)+" and  company_id<>"+str(c.id)
        else:
            sWhere=" where company_id in (select id from company_company where id="+str(c.id)+" or parent_id="+str(c.id)+")"
    s="select (select name from company_company where id=b.company_id) company,"+\
        "(select name from product_product where id=b.product_id) product,"+\
        "b.x,b.h,b.p,b.company_id,b.product_id,"+\
        "(select name from company_level where id=(select level_id from company_company where id=b.company_id)) "+\
        " from (select a.product_id,a.company_id,sum(a.x) x,sum(a.h) h,sum(a.p) p from "+\
            "(select product_id,company_id,"+\
                "case when label_pkg in (3,4) then "+\
                    "case when vtype_id in (2,5) then -1 else 1 end "+\
                "else 0 end x,"+\
                "case when label_pkg=2 then "+\
                    "case when vtype_id in (2,5) then -1 else 1 end "+\
                "else 0 end h,"+\
                "case when label_pkg=1 then "+\
                    "case when vtype_id in (2,5) then -1 else 1 end "+\
                "else 0 end p "+\
                "from inventory_stkdetails"+sWhere+\
            ") a "+\
        "group by a.product_id,a.company_id) b "+\
        "order by company,product"
    #2022-01-04
    s="select (select name from company_company where id=b.company_id) company,"+\
        "(select name from product_product where id=b.product_id) product,"+\
        "b.x,b.h,b.p,b.company_id,b.product_id,"+\
        "(select name from company_level where id=(select level_id from company_company where id=b.company_id)) "+\
        " from (select a.product_id,a.company_id,sum(a.x) x,sum(a.h) h,sum(a.p) p from "+\
            "(select product_id,company_id,"+\
                "case when label_pkg in (3,4) then "+\
                    "(select direction FROM inventory_voucher where id=vtype_id) "+\
                "else 0 end x,"+\
                "case when label_pkg=2 then "+\
                    "(select direction FROM inventory_voucher where id=vtype_id) "+\
                "else 0 end h,"+\
                "case when label_pkg=1 then "+\
                    "(select direction FROM inventory_voucher where id=vtype_id) "+\
                "else 0 end p "+\
                "from inventory_stkdetails"+sWhere+\
            ") a "+\
        "group by a.product_id,a.company_id) b "+\
        "order by company,product"


    ancestor_id = request.user.ancestor_id
    package_units = get_package_name(ancestor_id)
    cur=connection.cursor()
    cur.execute(s)    
    for r in cur.fetchall():
        qty=''
        a=[]
        if r[2]:
            a.append(str(r[2])+package_units[2])
        if r[3]:
            a.append(str(r[3])+package_units[1])
        if r[4]:
            a.append(str(r[4])+package_units[0])
        if a:
            qty=",".join(a)   
      
        data['stock'].append([            
            "<a href='/inventory/stock/agent/"+str(r[5])+"/'>"+r[0]+"</a>", #agent
            r[7],                                                           #level
            r[1],                                                           #product           
            qty                                                             #qty            
        ])
       
    return render(request, 'inventory/stock/agents_stock.html',data)
    

@login_required
def agent_stock(request,agt_id):
    data={'e':'','data':[],'company':''}
    cs=Company.objects.filter(id=str(request.user.company.id))
    if not cs:
        data['e']=_('无效帐号')
    else:
        c=cs[0]
        if c.level.id>int(agt_id):
            data['e']=_('帐号层级错误')
            return JsonResponse(data)
        agts=Company.objects.filter(id=int(agt_id))
        if agts:
            data['company']=agts[0].name
    sWhere=" where company_id="+agt_id
    s="select b.tm,(select name from inventory_voucher where id=b.vtype_id),b.code,"+\
            "coalesce((select name from product_product where id=b.product_id),''),"+\
            "coalesce((select name from company_company where id=b.company_to_id),''),"+\
            "coalesce((select username from company_user where id=b.user_id),''),"+\
            "coalesce(d.x,0),coalesce(d.h,0),coalesce(d.p,0),b.id from "+\
            "(select id,tm,coalesce(code,'') code,user_id,product_id,company_to_id,vtype_id "\
                "from inventory_batch "+sWhere+") b "+\
            "left outer join "+\
            "(select a.batch_id,sum(a.x) x,sum(a.h) h,sum(a.p) p from "+\
                "(select batch_id,"+\
                    "case when label_pkg in (3,4) then 1 else 0 end x,"+\
                    "case when label_pkg=2        then 1 else 0 end h,"+\
                    "case when label_pkg=1        then 1 else 0 end p "+\
                    "from inventory_stkdetails"+sWhere+\
                ") a group by a.batch_id"+\
            ") d "+\
            "on b.id=d.batch_id"
    cur=connection.cursor()
    cur.execute(s)
    #"<a href='/inventory/batch/details/"+str(r[9])+"/'>"+r[0].strftime('%Y-%m-%d %H:%M:%S')+"</a>", #时间 
    for r in cur.fetchall():
        data['data'].append([
            r[0].strftime('%Y-%m-%d %H:%M:%S'), #时间 
            r[1],                               #单据类别
            r[2],                               #单据编号
            r[3],                               #产品名称
            r[4],                               #客户名称
            r[5],                               #操作人
            r[6],                               #箱
            r[7],                               #盒
            r[8]                                #瓶

        ])
    return render(request, 'inventory/stock/agent_stock.html',data)


def jg_label_segment(request):
    data={}
    r = requests.get('http://www.china315net.com:35088/jg/label/segment/') 
    data=r.json()
    return JsonResponse(data)


#红坛 高度柔和
def ht_gdrh_upload(request,batch_id):
    batch=Batch.objects.get(id=int(batch_id))
    pids=settings.JG_HT_GR
    data={'total':0,'cnt_direct':0,'cnt_bonus':0}
    if not batch.product_id in pids:
        return JsonResponse(data)
    d=pids[batch.product_id]    
    cn_al=pyodbc.connect(settings.CN_AL)  
    cn_xa=pyodbc.connect(settings.CN_XA)

    #测试
    postfix='_test'  
    postfix=''
    cur_xa= cn_xa.cursor()
    cur_al= cn_al.cursor()
    cur_al.execute("create table #temp (code varchar (20)) ")
    cn_al.commit()
    cur_xa.execute("create table #temp (code varchar (20)) ")
    cn_xa.commit()    
    cur=connection.cursor()
    s="select left(label_code,4),count(*) from inventory_stkdetails where batch_id="+str(batch.id)+"group by left(label_code,4)"
    cur.execute(s)
    rs=cur.fetchall()       
    for r in rs:        
        data['total']=data['total']+r[1]        
        tb="t"+r[0]
        #2020-08-21 后绑定红坛跨段
        cur.execute("select tbname FROM label.lbl_tbcross where segment='"+r[0]+"'")
        rr=cur.fetchone()
        if rr:
            tb=rr[0]
        s="select code from label."+tb+" where package_id=1 and parent_id in  ("+\
            "select label_pk_id from inventory_stkdetails where batch_id="+str(batch.id)+")"
        cur.execute(s)
        while True:
            bts=[]
            cs=cur.fetchmany(1000)
            if  cs:
                for c in cs:
                    bts.append("('"+c[0]+"')")
            else:
                break
            if bts:
                s="insert into #temp (code) values "+",".join(bts)
                cur_xa.execute(s)                   
                cn_xa.commit()
                cur_al.execute(s)
                cn_al.commit()  
    #跳转
    s="insert into TJ_JG_Activity"+postfix+" (labelcode,flag,tm,upload_by_jiugui) "+\
        "select a.code,'"+d['code']+"',getdate(),1 from "+\
        "(select code from #temp "+\
            "where (select labelcode from TJ_JG_Activity"+postfix+" where labelcode=code) is null "+\
            "group by code"+\
        ") a"
    
    cur_al.execute(s)
    cnt_direct=cur_al.rowcount
    data['cnt_direct']=cnt_direct
    cn_al.commit()
    #奖项
    s="insert into TB_BaseLabelInfo"+postfix+\
        "(LabelCode,YanZhengMa,JXID,JXName,Compid,DJFlag,Remarks,time,PID,upload_by_jiugui,jgflag) SELECT "+\
        "a.code,'000000',"+d['jxid']+",'"+d['jxname']+"',99,0,'"+str(batch.id)+"',convert(varchar(100),getdate(),120),'"+d['pid']+"',1,"+d['jgflag']+\
        " from (select code from #temp "+\
            "where (select labelcode from TB_BaseLabelInfo"+postfix+" where labelcode=code) is null "+\
            "group by code"+\
        ") a"
    
    cur_xa.execute(s)  
    cnt_bonus=cur_xa.rowcount
    data['cnt_bonus']=cnt_bonus
    cn_xa.commit()   
    batch.tm_bonus=datetime.datetime.now()
    batch.save()
    return JsonResponse(data)    



def app_childcompany(request,company_id):
    data={'e':'','children':[]}
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data) 
    cs=Company.objects.filter(parent_id=int(company_id)).order_by('name')
    for c in cs:
        data['children'].append({
            'id':c.id,
            'name':c.name.split(' ')[0]
        })
    cs=Company.objects.filter(parent_id=None,ancestor_id=None)
    for c in cs:
        data['children'].append({
            'id':c.id,
            'name':c.name.split(' ')[0]
        })
    return JsonResponse(data)






#2020-03-27
@tj_login_required
def stk_err_list(request,company_id=None):    
    if not company_id:
        company_id=str(request.user.company.id)
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('date_fr', dt)
    dt_to = request.GET.get('date_to', dt)
    dt_max = max(dt_fr, dt_to)
    dt_min = min(dt_fr, dt_to)
    dt_fr = dt_min
    dt_to = dt_max
    data={'e':'','data':[],'params': {'dt_fr': dt_fr, 'dt_to': dt_to }}
   

    sWhere=" where company_id="+company_id+" and (dt between '"+dt_fr+"' and '"+dt_to+"')" 
    s="select b.tm,b.code,b.cnt_batch,b.cnt_stk,"+\
            "(select name from inventory_voucher where id=b.vtype_id),"+\
            "coalesce((select name from product_product where id=b.product_id),''),"+\
            "coalesce((select name from company_company where id=b.company_to_id),''),"+\
            "coalesce((select name from inventory_storehouse where id=b.store_fr_id),''),"+\
            "coalesce((select username from company_user where id=b.user_id),''),"+\
            "b.id from "+\
            "(select id,tm,coalesce(code,'') code,user_id,product_id,company_to_id,vtype_id,store_fr_id,"\
                "(select count(*) from inventory_batchdetails where batch_id=a.id) cnt_batch,"+\
                "(select count(*) from inventory_stkdetails where   batch_id=a.id) cnt_stk "+\
                "from inventory_batch a "+sWhere+" and "+\
                    "(select count(*) from inventory_batchdetails where   batch_id=a.id)>"+\
                    "(select count(*) from inventory_stkdetails where   batch_id=a.id)"+\
            ") b order by b.tm"            
    cur=connection.cursor()
    cur.execute(s)    
    for r in cur.fetchall():
        data['data'].append([
            "<a href='/inventory/batch/details/"+str(r[9])+"/'>"+r[0].strftime('%Y-%m-%d %H:%M:%S')+"<a/>", #时间 
            r[4],                               #单据类别
            r[1],                               #单据编号
            r[5],                               #产品名称
            r[6],                               #客户名称
            #r[8],                               #操作人
            r[7],                               #仓库
            r[2],                               #batch_cnt
            #r[3],                               #stk_cnt
            r[2]-r[3]                           #差异
        ])    
    return render(request, 'inventory/stock/error_list.html',data)


#2020-03-27
@tj_login_required
def stk_err_json(request,company_id=None):    
    if not company_id:
        company_id=str(request.user.company.id)
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('date_fr', dt)
    dt_to = request.GET.get('date_to', dt)
    dt_max = max(dt_fr, dt_to)
    dt_min = min(dt_fr, dt_to)
    dt_fr = dt_min
    dt_to = dt_max
    data={'e':'','data':[]}

    sWhere=" where company_id="+company_id+" and (dt between '"+dt_fr+"' and '"+dt_to+"')" 
    s="select b.tm,b.code,b.cnt_batch,b.cnt_stk,"+\
            "(select name from inventory_voucher where id=b.vtype_id),"+\
            "coalesce((select name from product_product where id=b.product_id),''),"+\
            "coalesce((select name from company_company where id=b.company_to_id),''),"+\
            "coalesce((select name from inventory_storehouse where id=b.store_fr_id),''),"+\
            "coalesce((select username from company_user where id=b.user_id),''),"+\
            "b.id from "+\
            "(select id,tm,coalesce(code,'') code,user_id,product_id,company_to_id,vtype_id,store_fr_id,"\
                "(select count(*) from inventory_batchdetails where batch_id=a.id) cnt_batch,"+\
                "(select count(*) from inventory_stkdetails where   batch_id=a.id) cnt_stk "+\
                "from inventory_batch a "+sWhere+" and "+\
                    "(select count(*) from inventory_batchdetails where   batch_id=a.id)>"+\
                    "(select count(*) from inventory_stkdetails where   batch_id=a.id)"+\
            ") b order by b.tm"            
    cur=connection.cursor()
    cur.execute(s)    
    for r in cur.fetchall():
        data['data'].append([
            "<a href='/inventory/batch/details/"+str(r[9])+"/'>"+r[0].strftime('%Y-%m-%d %H:%M:%S')+"<a/>", #时间 
            r[4],                               #单据类别
            r[1],                               #单据编号
            r[5],                               #产品名称
            r[6],                               #客户名称
            #r[8],                               #操作人
            r[7],                               #仓库
            r[2],                               #batch_cnt
            #r[3],                               #stk_cnt
            r[2]-r[3]                           #差异
        ])    
    return JsonResponse(data)



#2020-06-19
@tj_login_required
def stk_product_err(request):    
    company_id=str(request.user.company.id)
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('date_fr', dt)
    dt_to = request.GET.get('date_to', dt)
    dt_max = max(dt_fr, dt_to)
    dt_min = min(dt_fr, dt_to)
    dt_fr = dt_min
    dt_to = dt_max    
    return render(request, 'inventory/stock/product_error_list.html',{'dt_fr': dt_fr, 'dt_to': dt_to})


#2020-06-19
@tj_login_required
def stk_product_err_ajax(request):
    data=[]
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('date_fr', dt)
    dt_to = request.GET.get('date_to', dt)
    dt_max = max(dt_fr, dt_to)
    dt_min = min(dt_fr, dt_to)
    dt_fr = dt_min
    dt_to = dt_max    
    cid=str(request.user.company_id)
    cur=connection.cursor()
    s="select f.id,to_char(f.tm,'yyyy-mm-dd HH24:MI:SS'),f.code,"+\
        "(select username from company_user where id=f.user_id),"+\
        "(select name from company_company where id=f.company_to_id),"+\
        "(select count(*) from inventory_stkdetails where  batch_id=e.batch_id) cnt,"+\
        "(select count(*) from inventory_stkdetails z where  batch_id=e.batch_id and product_id<>"+\
            "(select product_id from inventory_stkdetails where label_pk_id=z.label_pk_id and company_id="+cid+" and vtype_id=1 and is_delete=false)),"+\
        "(select name from product_product where id=e.product_id_a) ck_product,"+\
        "(select name from product_product where id=e.product_id_b) rk_product "+\
        "from "+\
        "(select d.batch_id,d.product_id_a,d.product_id_b from "+\
	    "(select (select batch_id from inventory_stkdetails where company_id="+cid+" and vtype_id=2 and label_id=c.label_id),"+\
                "c.product_id_a,c.product_id_b from "+\
		"(select a.label_id,a.product_id product_id_a,b.product_id product_id_b from "+\
		    "(SELECT label_id,product_id FROM inventory_stkdetails where company_id="+cid+" and vtype_id=2 "+\
                        "and (dt between '"+dt_fr+"' and '"+dt_to+"') group by label_id,product_id) a "+\
		    "left outer join "+\
		    "(SELECT label_id,product_id  FROM inventory_stkdetails where company_id="+cid+\
                        " and vtype_id=1 and is_delete=false group by label_id,product_id) b "+\
		    "on a.label_id=b.label_id "+\
		    "where a.product_id<>b.product_id "+\
		") c "+\
	    ") d "+\
	    "group by d.batch_id,d.product_id_a,d.product_id_b "+\
        ") e "+\
        "left outer join "+\
        "(select id,tm,user_id,company_to_id,code from inventory_batch) f "+\
        "on e.batch_id=f.id"
    cur.execute(s)
    for r in cur.fetchall():
        data.append([ "<a href='/inventory/stock/err/product/batch/"+str(r[0])+"/'>"+r[1]+"</a>",r[2],r[3],r[4],r[5],r[6],r[7],r[8] ])       
    return JsonResponse(data,safe=False)


@tj_login_required
def stk_product_err_batch(request,id):
    cur=connection.cursor()
    s="select tm,coalesce(code,''),"+\
        "coalesce((select name from inventory_voucher where id=vtype_id),''),"+\
        "coalesce((select name from product_product where id=product_id),''),"+\
        "coalesce((select name from inventory_storehouse where id=store_fr_id),''),"+\
        "coalesce((select name from inventory_storehouse where id=store_to_id),''),"+\
        "coalesce((select username from company_user where id=user_id),''),"+\
        "coalesce((select name from company_company where id=company_to_id),''),"+\
        "vtype_id,"+\
        "coalesce((select name from company_prdplant where id=prd_plant_id),'') "+\
        "from inventory_batch where id="+id    
    cur.execute(s)
    r=cur.fetchone()
    if r:
        batch={'time':r[0].strftime('%Y-%m-%d %H:%M:%S'),'code':r[1],'voucher':r[2],'id':id,
                'product':r[3],'store_fr':r[4],'store_to':r[5],'user':r[6],'customer':r[7],'vid':r[8],'plant':r[9]}    
        s="SELECT b.label_code,"+\
            "(select name from product_product where id=b.pid_ck) product_ck,"+\
            "(select name from product_product where id=b.pid_rk) product_rk from "+\
            "(select label_code,label_pkg,product_id pid_ck,"+\
                "(select product_id from inventory_stkdetails where label_pk_id=a.label_pk_id and vtype_id=1 and company_id=a.company_id and is_delete=false)"+\
                " pid_rk FROM inventory_stkdetails a where batch_id="+id+" and "+\
                "product_id<>(select product_id from inventory_stkdetails where label_pk_id=a.label_pk_id and vtype_id=1 and company_id=a.company_id and is_delete=false)"+\
            ") b"
        cur.execute(s)
        dataset=[]
        for r in cur.fetchall():
            dataset.append([ r[0],r[1],r[2] ])
        
    return render(request,'inventory/stock/product_error_batch.html',{'batch':batch,'dataset':dataset})




#2020-04-27
#酒鬼瓶盖
def bottlecap(request):    
    code=request.GET.get('label','')    
    data = {
        'e': '',
        'code': code,
        'product': '',
        'package': '',
        'company': '',
        'replace': '',
        'boxes': {'pk': '', 'related': []},
        'packets': [],
        'bottles': [],
        'stock_dev': [],
        'replace':''
    }
    if not code:
        data['e']='标签不能为空'
        return JsonResponse(data) 
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data) 
    
    cur=connection.cursor()
    s="SELECT (SELECT  box  FROM jg_bottlecap.replace where code=lbl) "+\
        "FROM jg_bottlecap.binding where label='"+code+"'"
    cur.execute(s)
    r=cur.fetchone()
    if r:
        c=r[0]
    else:
        c=code
    
    if c:
        return label_info(c)    
    return JsonResponse(data)

    


#2020-04-22
#@login_required
@tj_login_required
@csrf_exempt
def upload_inv(request):
    
    data={'e':'','batch':{},'store_fr':[],'store_to':[],'product':[],'company_to':[]}     
    company_id=request.user.company.id
    #for o in Storehouse.objects.filter(company_id=company_id).order_by('name'):       
    #    data['store_fr'].append({'label': o.name, 'value': o.id})
    #    #data['store_to'].append({'label': o.name, 'value': o.id})
    #for o in Product.objects.filter(company_id=company_id).order_by('name'):
    #    data['product'].append({'label': o.name, 'value': o.id})
    #for o in Company.objects.filter(parent_id=company_id).order_by('name'):
    #for o in Company.objects.filter(ancestor_id=company_id).order_by('name'):
    #    data['company_to'].append({'label': o.name, 'value': o.id})


    return render(request, 'inventory/upload_inv_txt.html', data)    



#2020-04-22
#@login_required
@tj_login_required
def upload_inv_txt(request,is_app=False):    
    data = {'files': [], 'e': ''}  
    customer_id=request.POST.get('customer_id','0')
    product_id=request.POST.get('product_id','0')
    store_fr_id=request.POST.get('store_fr_id','0')  
    store_to_id=request.POST.get('store_to_id','0')
    v_id=request.POST.get('voucher_id','2')   
    p_id=request.POST.get('plant_id','0')   
    clmn=request.POST.get('column','5')
    
    #2021-05-06
    force=request.POST.get('force','1')
    
    u=request.user
    c = u.company
    u_id=u.id
    c_id=u.company_id    
    code=request.POST.get('code','')     
    dt = datetime.datetime.now() 
    c_name = c.name
    p = settings.MEDIA_ROOT + '/' + c_name + '/txt/inv_txt/' +  \
        str(dt.year) + str(dt.month).zfill(2) + str(dt.day).zfill(2)
    if not os.path.exists(p):
        os.makedirs(p)
    files = request.FILES.getlist('files') 
    a=[]
    for f in files:
        cnt_tt=0
        cnt_ok=0
        fn = f.name
        with open(p + '/' + fn, 'wb+') as destination:
            for chunk in f.chunks():
                destination.write(chunk)   
        a=[]        
        for l in open(p + '/' + fn,'r'):
            l=l.strip()
            if l:
                aa=l.split(',')
                l=aa[int(clmn)-1]
                a.append(l)
    
    t=dt.strftime('%Y-%m-%d %H:%M:%S')
    m2=hashlib.md5((sK+t).encode('utf8'))
    if force=='1':
        force=True
    else:
        force=False
    data={
            "bill_number":code,
            "company_id":c_id,
            "to_company_id":int(customer_id),
            "user_id":u_id,            
            "product_id":int(product_id), 
            "voucher_id":int(v_id),     
            "voucher_time":t,            
            "codes":a,
            "time":t,
            "key":m2.hexdigest(),
            "force": force,  # 2020-08-31 强制发货（不检查标签是否已有发货记录）
    }    
    if(int(v_id))==3:
        data["store_id"]=int(store_to_id)
        data["from_store_id"]=int(store_fr_id)
    else:
        data["store_id"]=int(store_fr_id) 
    request._body=json.dumps(data)
    request.META['CONTENT_TYPE']='application/json'
    return fg_update(request)
    




@tj_login_required
@csrf_exempt
def stk_transfer(request):
    customer=[]
    u=request.user
    if not u.company:
        return JsonResponse({'e':_('')})
    cur=connection.cursor()
    if request.method=='GET':
        sWhere=' where parent_id='+str(u.company.id)
        if u.company.level_id==1:
            sWhere=' where ancestor_id='+str(u.company.id)
        s="select id,name from logistics.company_company "+sWhere       
        cur.execute(s)
        for r in cur.fetchall():
            customer.append({'label': r[1], 'value': r[0]})
    else:       
        id_o=str(request.POST.get('company_id_old'))
        id_n=str(request.POST.get('company_id_new'))  
        a_s=[   
            "update logistics.inventory_batchdetails set company_id="+id_n+" where company_id="+id_o,           
            "update logistics.inventory_stkdetails set company_to_id="+id_n+" where company_to_id="+id_o,    
            "update logistics.inventory_stkdetails set company_id="+id_n+" where company_id="+id_o,
            "update logistics.inventory_batch set company_to_id="+id_n+" where company_to_id="+id_o,            
            "update logistics.inventory_batch set company_fr_id="+id_n+" where  company_fr_id="+id_o,
            "update logistics.inventory_batch set company_id="+id_n+" where company_id="+id_o
        ]
        cnt=0
        for s in a_s:
            cur.execute(s)
            cnt=max(cnt,cur.rowcount)        
        return JsonResponse({'e':'','cnt':cnt})
    return render(request, 'inventory/stk_transfer.html', {'company':customer}) 



'''
def app_stock_details(request,company_id):
    data={'e':'','stock':[]}
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data) 
    sWhere=" where company_id="+company_id    
    s="select"+\
        "(a.batch_id,sum(a.x) x,sum(a.h) h,sum(p) p from "+\        
            "(select batch_id,"+\
                "case when label_pkg in (3,4) then "+\
                    "case when vtype_id in (2,5) then -1 else 1 end "+\
                    "else 0 end x,"+\
                "case when label_pkg=2 then "+\
                    "case when vtype_id in (2,5) then -1 else 1 end "+\
                    "else 0 end h,"+\
                "case when label_pkg=1 then "+\
                    "case when vtype_id in (2,5) then -1 else 1 end "+\
                    "else 0 end p "+\
                "from inventory_stkdetails"+sWhere+\
            ") a  "+\
        "group by a.batch_id) b "+\
        "left outer join "+\
        "(select product_id,)"

        "order by name"   
    cur=connection.cursor()
    cur.execute(s)
    for r in cur.fetchall():
        data['stock'].append({
            "product":r[0],
            "qty_x":r[1],
            "qty_h":r[2],
            "qty_p":r[3]
        })
    return JsonResponse(data)






def binding_upload(request):
    data = {'files': [], 'e': ''}
    p = settings.MEDIA_ROOT
    u_id = str(request.user.id)
    c = request.user.company
    c_name = c.name
    if not os.path.exists(p + '/txt/labelbase/' + c_name):
        os.makedirs(p + '/txt/labelbase/' + c_name)
    c_id = str(c.id)
    files = request.FILES.getlist('files')
    cur = connection.cursor()
    for f in files:
        fn = f.name
        # if fn[:11].upper() == 'lbl_replace':
        with open(p + '/txt/labelbase/' + c_name + '/' + fn, 'wb+') as destination:
            for chunk in f.chunks():
                destination.write(chunk)
        f.seek(0)
        cur.execute("create temp table tmp(code0 character varying(20),code character varying(20))")
        cur.copy_from(f, 'tmp', sep=',', null='')
        # 写入BATCH
        s = "insert into label.lbl_replace_batch(user_id,company_id,txt_file) values " + \
            "(" + u_id + "," + c_id + ",'" + fn + "') returning id"
        cur.execute(s)
        id = str(cur.fetchone()[0])
        cur.execute("select left(code0,4) from tmp group by left(code0,4)")
        rs = cur.fetchall()
        for r in rs:


'''



#2020-08-12
# @login_required
@tj_login_required
@csrf_exempt
def query_label(request):
    dt_data = {'data':[],'clmns':[_('标签号码'),_('标签类型'),_('产品名称'),_('套标关系'),_('物流信息')],'e':[]}
    if request.method == 'GET':
        return render(request, 'inventory/label_txt_query_copy.html', dt_data)
    else:
        d = {'labels': [], 'e': ''}
        f = request.FILES.get('file')
        l = f.read().decode().splitlines()
        for n in l:
            d['labels'].append(n)
        for i in d['labels']:
            url = 'https://davis.china315net.com/label/app/1/' + i + '/'
            r = requests.get(url)
            dd=r.json()
            boxes=''
            #是否有关联箱标
            if dd['boxes']['related']:
                boxes="箱标:"+dd['boxes']['pk']+",关联箱标:"+",".join(dd['boxes']['related'])
            else:
                boxes="箱标:"+dd['boxes']['pk']
            cs=''
            #箱-盒-瓶 三级对应
            if dd['packets']:
                chlds=[]
                for c in dd['packets']:
                    chlds.append(c['code']+"(盒)->"+",".join(c['bottles'])+"(瓶)")
                cs=";"+",".join(chlds)
            #箱-瓶f二级对应
            elif dd['bottles']:
                cs=";瓶标："+",".join(dd['bottles'])
            wl=[]
            sal=[]
            for w in dd['stock_dev']:
                store=''
                if w['store']:
                    store=w['store']
                if w['voucher_type']=='销售出库':
                    sal.append(w['time']+"->"+w['to_company']+"(单号"+w['voucher_no']+" 操作员:"+w['user']+
                               " 标签号码"+w['label_code']+"["+w['package']+"])")
                else:
                    wl.append(w['time']+":"+w['voucher_type']+"(单号"+w['voucher_no']+";操作员:"+\
                        w['user']+";"+store+";标签号码"+w['label_code']+"["+w['package']+"]"+")"
                    )
            dt_data['data'].append([  i,dd['package'], dd['product'], boxes+cs, ";".join(sal)+";".join(wl) ])
        return JsonResponse(dt_data)



# 2020/7/24  经销商出入库查询
@tj_login_required
def agent_stk_query(request):
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('date_fr', dt)
    dt_to = request.GET.get('date_to', dt)
    data=[]
    cid = request.user.company_id
    cur = connection.cursor()
    agent_id = request.GET.get("agent_id", "")
    ancestor_id = request.user.ancestor_id
    package_units = get_package_name(ancestor_id)
    if agent_id=="":
        sWhere="where  ancestor_id  = "+str(cid) +" and (dt between '"+dt_fr+"' and '"+dt_to+"')"
        s = "select b.tm,(select name from logistics.inventory_voucher where id=b.vtype_id),b.code," + \
            "coalesce((select name from logistics.product_product where id=b.product_id),"+\
                "array_to_string(array(select name from logistics.product_product where id in "+\
                    "(select product_id from inventory_stkdetails where batch_id=b.id group by product_id)"+\
                "),','),'')," + \
            "coalesce((select name from logistics.company_company where id=b.company_id),'')," + \
            "coalesce((select name from logistics.company_company where id=b.company_to_id),'')," + \
            "coalesce((select username from logistics.company_user where id=b.user_id),'')," + \
            "coalesce(d.x,0),coalesce(d.h,0),coalesce(d.p,0),b.id from " + \
            "(select id,tm,coalesce(code,'') code,user_id,product_id,company_id,company_to_id,vtype_id " \
                "from inventory_batch " + sWhere + ") b " + \
            "left outer join " + \
            "(select a.batch_id,sum(a.x) x,sum(a.h) h,sum(a.p) p from " + \
                "(select batch_id," + \
                    "case when label_pkg in (3,4) then 1 else 0 end x," + \
                    "case when label_pkg=2        then 1 else 0 end h," + \
                    "case when label_pkg=1        then 1 else 0 end p " + \
                    "from logistics.inventory_stkdetails " + sWhere + \
                ") a group by a.batch_id" + \
            ") d " + \
            "on b.id=d.batch_id"
        cur.execute(s)
        for r in cur.fetchall():
            data.append([
                     "<a href='inventory/agent/details/" + str(r[10]) + "/'>" + str(r[0].strftime('%Y-%m-%d %H:%M:%S')) + "</a>",  # agent
                r[1],  # 单据类别
                r[2],  # 单据编号
                r[3],  # 产品名称
                r[4],
                r[5],  # 客户名称
                r[6],  # 操作人
                r[7],  # 箱
                r[8],  # 盒
                r[9],   # 瓶
             ])

        return render(request, 'inventory/agent_stk_query.html',
                      {'data': json.dumps(data),
                       'date_fr': dt_fr,
                       'date_to': dt_to,
                       'package_1':package_units[0],
                       'package_2':package_units[1],
                       'package_3':package_units[2],
                       })
    else:
        sWhere="where (company_id = "+agent_id+" or company_to_id = "+agent_id+") and (dt between '"+dt_fr+"' and '"+dt_to+"')"

        s = "select b.tm,(select name from logistics.inventory_voucher where id=b.vtype_id),b.code," + \
            "coalesce((select name from logistics.product_product where id=b.product_id),"+\
                "array_to_string(array(select name from logistics.product_product where id in "+\
                    "(select product_id from inventory_stkdetails where batch_id=b.id group by product_id)"+\
                "),','),'')," + \
            "coalesce((select name from logistics.company_company where id=b.company_id),'')," + \
            "coalesce((select name from logistics.company_company where id=b.company_to_id),'')," + \
            "coalesce((select username from logistics.company_user where id=b.user_id),'')," + \
            "coalesce(d.x,0),coalesce(d.h,0),coalesce(d.p,0),b.id from " + \
            "(select id,tm,coalesce(code,'') code,user_id,product_id,company_id,company_to_id,vtype_id " \
                "from inventory_batch " + sWhere + ") b " + \
            "left outer join " + \
            "(select a.batch_id,sum(a.x) x,sum(a.h) h,sum(a.p) p from " + \
                "(select batch_id," + \
                    "case when label_pkg in (3,4) then 1 else 0 end x," + \
                    "case when label_pkg=2        then 1 else 0 end h," + \
                    "case when label_pkg=1        then 1 else 0 end p " + \
                    "from logistics.inventory_stkdetails " + sWhere + \
                ") a group by a.batch_id" + \
            ") d " + \
            "on b.id=d.batch_id"
        cur = connection.cursor()
        #print(s)
        cur.execute(s)
        for r in cur.fetchall():
            data.append([
                     "<a href='inventory/agent/details/" + str(r[10]) + "/'>" + str(r[0].strftime('%Y-%m-%d %H:%M:%S')) + "</a>",  # agent
                r[1],  # 单据类别
                r[2],  # 单据编号
                r[3],  # 产品名称
                r[4],
                r[5],  # 客户名称
                r[6],  # 操作人
                r[7],  # 箱
                r[8],  # 盒
                r[9],   # 瓶
             ])
        cur.execute("select (select name from company_level where id=level_id),"+\
            "(select name from company_company where id=a.parent_id),name from company_company a where id = "+agent_id+"")
        r=cur.fetchone()
        parent=r[1]
        level=r[0]
        cur.close()
        return render(request, 'inventory/agent_stk_query.html',
                      {'data':json.dumps(data),
                       'date_fr': dt_fr,
                       'date_to': dt_to,
                       "level":level,
                       "parent":parent,
                       "agent_id":agent_id,
                       'agent_name':r[2],
                       'package_1':package_units[0],
                       'package_2':package_units[1],
                       'package_3':package_units[2],
                       })


#2022-05-10  经销商出入库产品汇总
@login_required
def agent_stk_product(request):
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('date_fr', dt)
    dt_to = request.GET.get('date_to', dt)    
    agent_id = request.GET.get("agent_id", "")
    data={'agent':None,'dt_fr':dt_fr,'dt_to':dt_to,'data':[],'clmns':[
            '箱','瓶',#入库
            '箱','瓶',#出库
            '箱','瓶',#退库
        ]
    }        
    if agent_id:
        agts=Company.objects.filter(id=int(agent_id))
        if agts:
            cur=connection.cursor()
            data['agent']=agts[0]
            sWhere="where (company_id = "+agent_id+" or company_to_id = "+agent_id+") and (dt between '"+dt_fr+"' and '"+dt_to+"')"    
            s="select (select name from product_product where id=p.product_id),"+\
                "coalesce(i.x,0),coalesce(i.p,0),"\
                "coalesce(o.x,0),coalesce(o.p,0),"\
                "coalesce(r.x,0),coalesce(r.p,0) "\
                "from "+\
                "(select product_id from inventory_stkdetails "+sWhere+" group by product_id) p "+\
                "left outer join "+\
                "(select a.product_id,sum(a.x) x,sum(a.p) p from " + \
                    "(select product_id," + \
                        "case when label_pkg=3 then 1 else 0 end x," + \
                        "case when label_pkg=1 then 1 else 0 end p " + \
                        "from inventory_stkdetails "+sWhere+" and vtype_id=1" \
                    ") a group by a.product_id" + \
                ") i "+\
                "on p.product_id=i.product_id "+\
                "left outer join "+\
                "(select a.product_id,sum(a.x) x,sum(a.p) p from " + \
                    "(select product_id," + \
                        "case when label_pkg=3 then 1 else 0 end x," + \
                        "case when label_pkg=1 then 1 else 0 end p " + \
                        "from inventory_stkdetails "+sWhere+" and vtype_id=2" \
                    ") a group by a.product_id" + \
                ") o "+\
                "on p.product_id=o.product_id "+\
                "left outer join "+\
                "(select a.product_id,sum(a.x) x,sum(a.p) p from " + \
                    "(select product_id," + \
                        "case when label_pkg=3 then 1 else 0 end x," + \
                        "case when label_pkg=1 then 1 else 0 end p " + \
                        "from inventory_stkdetails "+sWhere+" and vtype_id=4" \
                    ") a group by a.product_id" + \
                ") r "+\
                "on p.product_id=r.product_id"
            cur.execute(s)
            for r in cur.fetchall():
                data['data'].append([r[0], r[1],r[2], r[3],r[4], r[5],r[6] ])   
            cur.close()
    return render(request,'inventory/agent_stk_product.html',data)                      


@tj_login_required
def agent_stk_query_details(request,id):
    data = {'e': '', 'batch': {}, 'dataset': []}
    cur = connection.cursor()
    s = "select tm,coalesce(code,'')," + \
        "coalesce((select name from logistics.inventory_voucher where id=vtype_id),'')," + \
        "coalesce((select name from logistics.product_product where id=product_id),'')," + \
        "coalesce((select name from logistics.inventory_storehouse where id=store_fr_id),'')," + \
        "coalesce((select name from logistics.inventory_storehouse where id=store_to_id),'')," + \
        "coalesce((select username from logistics.company_user where id=user_id),'')," + \
        "coalesce((select name from logistics.company_company where id=company_to_id),'')," + \
        "vtype_id," + \
        "coalesce((select name from logistics.company_prdplant where id=prd_plant_id),'') " + \
        "from inventory_batch where id=" + id
    cur.execute(s)
    r = cur.fetchone()
    if r:
        data['batch'] = {'time': r[0].strftime('%Y-%m-%d %H:%M:%S'), 'code': r[1], 'voucher': r[2], 'id': id,
                         'product': r[3], 'store_fr': r[4], 'store_to': r[5], 'user': r[6], 'customer': r[7],
                         'vid': r[8], 'plant': r[9]}

        # 标签退库
        if r[8] == 5:
            s = "select a.label_code," + \
                "coalesce((SELECT name FROM logistics.label.lbl_package where id=a.label_pkg),a.err,'错误')" + \
                " from " + \
                "(select label_code,label_pkg,err from logistics.inventory_batchdetails where batch_id=" + id + ") a "

        else:
            s = "select a.label_code," + \
                "coalesce((SELECT name FROM label.lbl_package where id=b.label_pkg),a.err,'错误'),coalesce(b.product_name,'')" + \
                " from " + \
                "(select label_code,err from logistics.inventory_batchdetails where batch_id=" + id + ") a " + \
                "left outer join " + \
                "(select label_code,label_pkg,"+ \
                "coalesce((select name from logistics.product_product where id=product_id),'') as product_name"+ \
                " from logistics.inventory_stkdetails where batch_id=" + id + ") b " + \
                "on a.label_code=b.label_code"
        cur.execute(s)

        for r in cur.fetchall():
            data['dataset'].append([r[0], r[1],r[2]])
        cur.close()
    data['dataset'] = SafeString(data['dataset'])
    return render(request, "inventory/label_query_details.html", data)



#2020-09-01
@login_required
def ajax_geo(request,obj,company_id=None):
    cur=connection.cursor()
    if request.method=='GET':        
        center={'lng':116.404,'lat':39.915}        
        zoom=11        
        province_gis_id=request.GET.get('adm1_id','')
        city_gis_id=request.GET.get('adm2_id','')
        county_gis_id=request.GET.get('adm3_id','')
       
        store_geos=[]

        geo_id=''
        if county_gis_id and county_gis_id!='null':   #区/县
            zoom=14
            geo_id=county_gis_id
        elif city_gis_id and city_gis_id!='null':
            zoom=12
            geo_id=city_gis_id
        elif province_gis_id and province_gis_id!='null':
            zoom=10
            geo_id=province_gis_id
        if geo_id:
            s="select public.ST_X(public.ST_Centroid(geom)),public.ST_Y(public.ST_Centroid(geom)) FROM gis.adm where id="+geo_id            
            cur.execute(s)
            r=cur.fetchone()
            if r:
                center={'lng':r[0],'lat':r[1]}
        lng_lat=[]
        if company_id:
            cur.execute("select lng_lat from company_company where id="+company_id)
            r=cur.fetchone()
            if r:
                if r[0]:
                    lng_lat=[r[0][0],r[0][1]]
        if obj=='store':
            html='storehouse_geo.html'
            if company_id:
                c=Company.objects.get(id=int(company_id))
                cur.execute("select id,lng_lat,tm,tm_checked,"+\
                    "coalesce((select username from company_user where id=checked_by_id),'') "+\
                    "from inventory_storehousebd09 where company_id="+company_id
                )   
                for r in cur.fetchall():
                    tm_ck=''
                    if r[3]:
                        tm_ck=r[3].strftime('%Y-%m-%d %H:%M:%S')
                    store_geos.append({
                        'id':r[0],
                        'sn':str(r[0]).zfill(8),
                        'lnglat':[r[1][0],r[1][1]],
                        'tm':r[2].strftime('%Y-%m-%d %H:%M:%S'),
                        'tm_checked':tm_ck,
                        'checked_by':r[4]                        
                    })
            if store_geos:
                g=store_geos[0]
                center={'lng':g['lnglat'][0],'lat':g['lnglat'][1]}
                zoom=13
        elif obj=='agent':
            html='agent_geo.html'
            if company_id:                
                cur.execute("select id,lng_lat,tm,tm_checked,"+\
                    "coalesce((select username from company_user where id=checked_by_id),'') "+\
                    "from inventory_storehousebd09 where company_id="+company_id
                )
                for r in cur.fetchall():
                    tm_ck=''
                    if r[3]:
                        tm_ck=r[3].strftime('%Y-%m-%d %H:%M:%S')
                    store_geos.append({
                        'id':r[0],
                        'sn':str(r[0]).zfill(8),
                        'lnglat':[r[1][0],r[1][1]],
                        'tm':r[2].strftime('%Y-%m-%d %H:%M:%S'),
                        'tm_checked':tm_ck,
                        'checked_by':r[4]
                    })
        data={'obj':obj,'center':center,'zoom':zoom,'stores':store_geos,'lng_lat':lng_lat}       
        return render(request, "inventory/"+html,data)


#2021-01-03 经销商退货,核减层级返利
def channel_rebate_deduct(batch):
    bid=str(batch.id)
    cur=connection.cursor()    
    s="update sales_channelrebatedetails r "+\
        "set is_deducted=true,deduction_batch_id="+bid+" "+\
        "where deduction_batch_id=0 and label_id in (select label_id from inventory_stkdetails where batch_id="+bid+")"
    cur.execute(s)
    s="select rebate_batch_id,sum(val),sum(x),sum(p) from "+\
        "(select rebate_batch_id,val,case when label_pkg=3 then 1 else 0 end x,case when label_pkg=1 then 1 else 0 end p from sales_channelrebatedetails "+\
            "where deduction_batch_id="+bid+") a group by rebate_batch_id"
    cur.execute(s)
    rs=cur.fetchall()
    for r in rs:
        b0=ChannelRebateBatch.objects.get(id=r[0])
        b=ChannelRebateBatch(ancestor_id=b0.ancestor_id,company_id=b0.company_id,
            company_src_id=b0.company_src_id,promotion_id=b0.promotion_id,batch_id=int(bid),
            vtype_id=b0.vtype_id,level_id=b0.level_id,saldivision_id=b0.saldivision_id,
            checked_by_id=1,tm_checked=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),confirmed=True,
            val=-r[1],boxes=-r[2],bottles=-r[3])
        b.save()
        s="INSERT INTO sales_channelrebatedetails("+\
            "label_id,label_pk_id,label_code,label_pkg, val,product_id,rebate_batch_id,stk_batch_id,"+\
            "dt_delivery,company_id,vtype_id,deduction_batch_id,is_deducted) select "+\
            "label_id,label_pk_id,label_code,label_pkg,-val,product_id,"+str(b.id)+","+bid+","+\
            "dt_delivery,company_id,vtype_id,"+bid+",true "+\
            "from sales_channelrebatedetails where deduction_batch_id="+bid+" and rebate_batch_id="+str(r[0])
        cur.execute(s)     
    return         







#2020-11-19 最终版 2021-02-14
def channel_rebate(batch):
    #datum=[]
    distance='99999999.99'
    data={
        'promotion_id':0,
        'amount':0,
        'amount_neg':0,
        'distance_lmt':distance,        
    }
    #公司级扫码不计算渠道返利
    amt=0.00    
    #2020-11-08 已经扫过瓶标这次又扫了箱标 对应的返利金额（箱标会计入返利，原瓶标返利记录删除）    
    amt_neg=0.00

    c=Company.objects.get(id=batch.company_id)   
    if c.level.id==1:
        return data
    cur=connection.cursor()  
    t=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    cid=str(c.id)
    aid=str(c.ancestor_id)
    bid=str(batch.id)
    vid=str(batch.vtype_id)
    if batch.distance or batch.distance==0:
        distance=str(batch.distance)
    agt_id='0'
    saldiv_id='0'
    if c.division:
        saldiv_id=str(c.division_id)        
    subdiv_id='0'
    if c.sub_division:
        subdiv_id=str(c.sub_division_id)
    if batch.company_id:
        agt_id=str(batch.company_id)
    if batch.company_to_id:
        agt_id=str(batch.company_to_id)


    

    # 2021-02-12 # 同一笔BATCH可能有多个PRODUCT_ID,即一个BATCH可能有多个promotion_id
    
    cur.execute("SELECT product_id from inventory_stkdetails where batch_id="+bid+" group by product_id")
    rs=cur.fetchall()
    is_first=True
    for rr0 in rs:
        #distance='99999999.99'
        #data={
        #    'promotion_id':0,
        #    'amount':0,
        #    'distance_lmt':distance
        #}
        #公司级扫码不计算渠道返利
        amt=0.00    
        #2020-11-08 已经扫过瓶标这次又扫了箱标 对应的返利金额（箱标会计入返利，原瓶标返利记录删除）    
        amt_neg=0.00
        prd_id=str(rr0[0])
        s="select b.id,b.priority,a.val,a.pvals,b.package_unit,a.id,a.distance,b.products,b.dt_delivery from "+\
                "("+\
                    "SELECT val,level_id,promotion_id,pvals,id,distance FROM sales_channelpromtionsrebate "+\
                        " where level_id="+str(c.level_id)+" and vtype_id="+vid+\
                ") a "+\
                "left outer join ("+\
                    "select id,name,awardcategory_id,package_unit,priority,products,dt_delivery from sales_channelpromotions "+ \
                    "where company_id="+aid+" and ('"+t+"' between tm_start and tm_end) and status=1 "+\
                    "and case when array_length(products,1)   is null then true else ARRAY[" +prd_id  +"] <@ products end "+ \
                    "and case when array_length(agents,1)     is null then true else ARRAY[" +agt_id  +"] <@ agents end " + \
                    "and case when array_length(div_ids,1)    is null then true else ARRAY["+saldiv_id+"] <@ div_ids end "+\
                    "and case when array_length(subdiv_ids,1) is null then true else ARRAY["+subdiv_id+"] <@ subdiv_ids end"+\
                ") b "+\
                "on a.promotion_id=b.id "+\
                "where b.id is not null and a.id is not null order by b.priority desc limit 1"
        cur.execute(s)
        #print(s)
        r=cur.fetchone()

        #2020-11-06 主箱标所在箱最后一次从公司发货的日期
        cDt="(select max(dt) from inventory_stkdetails where label_pk_id=a.label_pk_id and company_id="+aid+" and vtype_id=2) "
        bBoxbottle=False
        v=0.00

        if r:
            v=float(r[2])   #单位返利金额
            u=r[4]          #计算返利的包装单位：1瓶，3箱
            rid=r[5]        #返利明细ID
            pid=r[0]        #返利活动ID
            d=r[6]          #返利扫码距离限定
            es_dt=r[8]      #最早发货时间（公司）
            data['promotion_id']=pid
            #2021-11-20,即使扫码金额为0，也要写入扫码返利明细
            #if v>0.00:
            #删除已有返利记录
            if is_first:
                for bth in ChannelRebateBatch.objects.filter(batch_id=batch.id):
                    bth.delete()
            sDt=''
            if es_dt:
                sDt=" and "+cDt+">='"+es_dt.strftime('%Y-%m-%d')+"'"
            storegeo_id='null'
            if batch.storegeo_id:
                storegeo_id=str(batch.storegeo_id)
            if not d:                           #未限定扫码距离
                checked_by='1'
                tm_checked="'"+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+"'"
                confirmed='true'
            else:                               #返利活动限定了扫码距离
                data['distance_lmt']=d
                if int(float(distance))<=d:     #扫码距离在限定范围内
                    checked_by='1'
                    tm_checked="'"+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+"'"
                    confirmed='true'
                else:                           #不在限定范围内，或未上传扫码距离
                    checked_by='null'
                    tm_checked='null'
                    confirmed='false'
            tb="tmp_details"
            #创建或清空临时表，计箱返利明细
            cur.execute("select count(*) from pg_class where relname='"+tb+"'")
            r0=cur.fetchone()
            if r0[0]>0:
                s="truncate table "+tb
            else:
                s="create temp table "+tb+"(label_code character varying(20),product_id integer,"+\
                    "label_id bigint,label_pk_id bigint,label_pkg smallint,val numeric(12,2),dt_delivery date)"
            cur.execute(s)


            ps=[]
            sProduct=" and product_id="+str(rr0[0])
            if u==1:
                pval=str(0.0+v)
                xval="coalesce((select qty_p from product_product where id=product_id),1)*"+str(0.0+v)
            elif u==3:
                pval=str(0.0+v)+"/coalesce((select qty_p from product_product where id=product_id),1)"
                xval=str(0.0+v)
            s="insert into "+tb+" (label_code,product_id,label_id,label_pk_id,label_pkg,val,dt_delivery) select "+\
                "label_code,product_id,label_id,label_pk_id,label_pkg,"+\
                "case when label_pkg=1 then "+pval+" else "+xval+" end,"+cDt+\
                "from inventory_stkdetails a where batch_id="+bid+sProduct+sDt

            cur.execute(s)
            cnt=cur.rowcount
            if cnt:
                cur.execute("select sum(val) from "+tb)
                r=cur.fetchone()
                #有距离限定的，在限定距离内
                if confirmed=='true':
                    amt=r[0]
                vals=str(r[0])
                s="insert into sales_channelrebatebatch "+\
                    "(company_id,company_src_id,promotion_id,batch_id,dt,tm,val,checked_by_id,tm_checked,confirmed,distance,storegeo_id,ancestor_id,vtype_id,boxes,bottles) values ("+\
                        cid+","+cid+","+str(pid)+","+bid+",now(),now(),"+vals+","+checked_by+","+tm_checked+","+confirmed+","+distance+","+storegeo_id+","+aid+","+vid+','+\
                        "(select count(*) from "+tb+" where label_pkg=3),"+\
                        "(select count(*) from "+tb+" where label_pkg=1) "+\
                    ")  returning id"
                cur.execute(s)
                rt=cur.fetchone()
                id=str(rt[0])

                s="INSERT INTO sales_channelrebatedetails("+\
                    "label_id,label_pk_id,label_code,label_pkg,val,product_id,rebate_batch_id,stk_batch_id,dt_delivery,company_id,vtype_id) select "+\
                    "label_id,label_pk_id,label_code,label_pkg,val,product_id,"+id+","+bid+",dt_delivery,"+cid+","+vid+\
                    " from "+tb
                cur.execute(s)

                #父级返利
                s="select recursion, val, level_id from sales_parentrebate where rebate_id="+str(rid)
                cur.execute(s)
                for r in cur.fetchall():
                    v=float(r[1])
                    p=c
                    for i in range(r[0]):
                        if p.parent:
                            p=p.parent
                    if p.level_id==r[2]:
                        #清空临时表
                        cur.execute("truncate table "+tb)

                        #2020-12-11 取销箱瓶置换
                        #cur.execute("truncate table "+tb_s)

                        if u==1:
                            pval=str(0.0+v)
                            xval="coalesce((select qty_p from product_product where id=product_id),1)*"+str(0.0+v)
                        elif u==3:
                            pval=str(0.0+v)+"/coalesce((select qty_p from product_product where id=product_id),1)"
                            xval=str(0.0+v)
                        s="insert into "+tb+" (label_code,product_id,label_id,label_pk_id,label_pkg,val,dt_delivery) select "+\
                            "label_code,product_id,label_id,label_pk_id,label_pkg,"+\
                            "case when label_pkg=1 then "+pval+" else "+xval+" end,"+cDt+\
                            "from inventory_stkdetails a where batch_id="+bid+sProduct+sDt
                        cur.execute(s)
                        cnt=cur.rowcount
                        if cnt:
                            cur.execute("select sum(val) from "+tb)
                            r=cur.fetchone()
                            vals=str(r[0])
                            s = "insert into sales_channelrebatebatch "+\
                                "(company_id,company_src_id,promotion_id,batch_id,dt,tm,val,checked_by_id,tm_checked,confirmed,distance,storegeo_id,ancestor_id,vtype_id,boxes,bottles) values (" + \
                                    str(p.id)+","+cid+","+str(pid)+","+bid+",now(),now(),"+vals+","+checked_by+","+tm_checked+","+confirmed+","+distance+","+storegeo_id+","+aid+","+vid+","+\
                                    "(select count(*) from "+tb+" where label_pkg=3),"+\
                                    "(select count(*) from "+tb+" where label_pkg=1) "+\
                                ") returning id"
                            cur.execute(s)
                            rt=cur.fetchone()
                            id=str(rt[0])
                            s="INSERT INTO sales_channelrebatedetails("+\
                                "label_id,label_pk_id,label_code,label_pkg,val,product_id,rebate_batch_id,stk_batch_id,dt_delivery,company_id,vtype_id) select "+\
                                "label_id,label_pk_id,label_code,label_pkg,val,product_id,"+id+","+bid+",dt_delivery,"+str(p.id)+","+vid+" from "+tb
                            cur.execute(s)
            #data['amount']=amt
            #data['amount_neg']=amt_neg
            data['amount']=data['amount']+amt
            data['amount_neg']=data['amount_neg']+amt_neg           
        is_first=False        
    cur.close() 
    return data





















#2020-11-19 最终版
def channel_rebate0214(batch):
    distance='99999999.99'
    data={
        'promotion_id':0,
        'amount':0,
        'distance_lmt':distance
    }
    #公司级扫码不计算渠道返利
    amt=0.00    
    #2020-11-08 已经扫过瓶标这次又扫了箱标 对应的返利金额（箱标会计入返利，原瓶标返利记录删除）    
    amt_neg=0.00

    c=Company.objects.get(id=batch.company_id)   
    if c.level.id==1:
        return data
    cur=connection.cursor()  
    t=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    cid=str(c.id)
    aid=str(c.ancestor_id)
    bid=str(batch.id)
    vid=str(batch.vtype_id)
    if batch.distance or batch.distance==0:
        distance=str(batch.distance)
    agt_id='0'
    saldiv_id='0'
    if c.division:
        saldiv_id=str(c.division_id)        
    subdiv_id='0'
    if c.sub_division:
        subdiv_id=str(c.sub_division_id)
    if batch.company_to_id:
        agt_id=str(batch.company_to_id) 
    
    if batch.vtype_id==1:
        sAgt=""
    elif batch.vtype_id==2:
        sAgt=" and case when array_length(agents,1) is null then true else ARRAY["+agt_id+"] <@ agents end"    
    
    #2020-11-19
    sProductdA="ARRAY(SELECT product_id from inventory_stkdetails where batch_id="+bid+" group by product_id)"

    s="select b.id,b.priority,a.val,a.pvals,b.package_unit,a.id,a.distance,b.products,b.dt_delivery from "+\
            "("+\
                "SELECT val,level_id,promotion_id,pvals,id,distance FROM sales_channelpromtionsrebate "+\
                    " where level_id="+str(c.level_id)+" and vtype_id="+vid+\
            ") a "+\
            "left outer join ("+\
                "select id,name,awardcategory_id,package_unit,priority,products,dt_delivery from sales_channelpromotions "+ \
                "where company_id="+aid+" and ('"+t+"' between tm_start and tm_end) and status=1 "+\
                "and case when array_length(products,1)   is null then true else ("+sProductdA+" && products) end "+\
                "and ("+\
                    "case when array_length(div_ids,1)    is null then true else ARRAY["+saldiv_id+"] <@ div_ids end "+\
                    "or "+\
                    "case when array_length(subdiv_ids,1) is null then true else ARRAY["+subdiv_id+"] <@ subdiv_ids end"+\
                ") "+\
                sAgt+\
            ") b "+\
            "on a.promotion_id=b.id "+\
            "where b.id is not null and a.id is not null order by b.priority desc limit 1"   

    
    #print(s)



    cur.execute(s)        
    r=cur.fetchone()

    #2020-11-06 主箱标所在箱最后一次从公司发货的日期
    cDt="(select max(dt) from inventory_stkdetails where label_pk_id=a.label_pk_id and company_id="+aid+" and vtype_id=2) "
    bBoxbottle=False
    v=0.00   

    if r:
        v=float(r[2])   #单位返利金额
        u=r[4]          #计算返利的包装单位：1瓶，3箱
        rid=r[5]        #返利明细ID
        pid=r[0]        #返利活动ID
        d=r[6]          #返利扫码距离限定 
        es_dt=r[8]      #最早发货时间（公司）
        data['promotion_id']=pid          
        if v>0.00:        
            #删除已有返利记录
            for bth in ChannelRebateBatch.objects.filter(batch_id=batch.id):
                bth.delete()            
            

            sDt=''
            if es_dt:
                sDt=" and "+cDt+">='"+es_dt.strftime('%Y-%m-%d')+"'"
            storegeo_id='null'
            if batch.storegeo_id:
                storegeo_id=str(batch.storegeo_id)
            if not d:                           #未限定扫码距离
                checked_by='1'
                tm_checked="'"+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+"'"
                confirmed='true'
            else:                               #返利活动限定了扫码距离
                data['distance_lmt']=d
                if int(float(distance))<=d:     #扫码距离在限定范围内
                    checked_by='1'
                    tm_checked="'"+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')+"'"
                    confirmed='true'
                else:                           #不在限定范围内，或未上传扫码距离
                    checked_by='null'
                    tm_checked='null'
                    confirmed='false'
            tb="tmp_details"
            #创建或清空临时表，计箱返利明细
            cur.execute("select count(*) from pg_class where relname='"+tb+"'")
            r0=cur.fetchone()
            if r0[0]>0:
                s="truncate table "+tb
            else:
                s="create temp table "+tb+"(label_code character varying(20),product_id integer,"+\
                    "label_id bigint,label_pk_id bigint,label_pkg smallint,val numeric(12,2),dt_delivery date)"
            cur.execute(s)


            ps=[]
            if r[7]:
                for p in r[7]:
                    ps.append(str(p))
                sProduct=" and product_id in ("+",".join(ps)+")"
            else:
                sProduct=''
            if u==1:
                pval=str(0.0+v)
                xval="coalesce((select qty_p from product_product where id=product_id),1)*"+str(0.0+v)
            elif u==3:
                pval=str(0.0+v)+"/coalesce((select qty_p from product_product where id=product_id),1)"
                xval=str(0.0+v)
            s="insert into "+tb+" (label_code,product_id,label_id,label_pk_id,label_pkg,val,dt_delivery) select "+\
                "label_code,product_id,label_id,label_pk_id,label_pkg,"+\
                "case when label_pkg=1 then "+pval+" else "+xval+" end,"+cDt+\
                "from inventory_stkdetails a where batch_id="+bid+sProduct+sDt                

            cur.execute(s)
            cnt=cur.rowcount
            if cnt:    
                cur.execute("select sum(val) from "+tb)
                r=cur.fetchone()
                #有距离限定的，在限定距离内
                if confirmed=='true':
                    amt=r[0]
                vals=str(r[0])
                s="insert into sales_channelrebatebatch "+\
                    "(company_id,company_src_id,promotion_id,batch_id,dt,tm,val,checked_by_id,tm_checked,confirmed,distance,storegeo_id,ancestor_id,vtype_id,boxes,bottles) values ("+\
                        cid+","+cid+","+str(pid)+","+bid+",now(),now(),"+vals+","+checked_by+","+tm_checked+","+confirmed+","+distance+","+storegeo_id+","+aid+","+vid+','+\
                        "(select count(*) from "+tb+" where label_pkg=3),"+\
                        "(select count(*) from "+tb+" where label_pkg=1) "+\
                    ")  returning id"
                cur.execute(s)
                rt=cur.fetchone()
                id=str(rt[0])                
                
                s="INSERT INTO sales_channelrebatedetails("+\
                    "label_id,label_pk_id,label_code,label_pkg,val,product_id,rebate_batch_id,stk_batch_id,dt_delivery,company_id,vtype_id) select "+\
                    "label_id,label_pk_id,label_code,label_pkg,val,product_id,"+id+","+bid+",dt_delivery,"+cid+","+vid+\
                    " from "+tb
                cur.execute(s)       

                #父级返利
                s="select recursion, val, level_id from sales_parentrebate where rebate_id="+str(rid)
                cur.execute(s)
                for r in cur.fetchall():
                    v=float(r[1])
                    if v>0.00:
                        p=c
                        for i in range(r[0]):
                            if p.parent:
                                p=p.parent
                        if p.level_id==r[2]:
                            #清空临时表
                            cur.execute("truncate table "+tb)
                            
                            #2020-12-11 取销箱瓶置换
                            #cur.execute("truncate table "+tb_s)
                            
                            if u==1:
                                pval=str(0.0+v)
                                xval="coalesce((select qty_p from product_product where id=product_id),1)*"+str(0.0+v)
                            elif u==3:
                                pval=str(0.0+v)+"/coalesce((select qty_p from product_product where id=product_id),1)"
                                xval=str(0.0+v)
                            s="insert into "+tb+" (label_code,product_id,label_id,label_pk_id,label_pkg,val,dt_delivery) select "+\
                                "label_code,product_id,label_id,label_pk_id,label_pkg,"+\
                                "case when label_pkg=1 then "+pval+" else "+xval+" end,"+cDt+\
                                "from inventory_stkdetails a where batch_id="+bid+sProduct+sDt
                            cur.execute(s)
                            cnt=cur.rowcount
                            if cnt:
                                cur.execute("select sum(val) from "+tb)
                                r=cur.fetchone()
                                vals=str(r[0])
                                s = "insert into sales_channelrebatebatch "+\
                                    "(company_id,company_src_id,promotion_id,batch_id,dt,tm,val,checked_by_id,tm_checked,confirmed,distance,storegeo_id,ancestor_id,vtype_id,boxes,bottles) values (" + \
                                        str(p.id)+","+cid+","+str(pid)+","+bid+",now(),now(),"+vals+","+checked_by+","+tm_checked+","+confirmed+","+distance+","+storegeo_id+","+aid+","+vid+","+\
                                        "(select count(*) from "+tb+" where label_pkg=3),"+\
                                        "(select count(*) from "+tb+" where label_pkg=1) "+\
                                    ") returning id"                                   
                                cur.execute(s)
                                rt=cur.fetchone()
                                id=str(rt[0])

                                
                                

                                s="INSERT INTO sales_channelrebatedetails("+\
                                    "label_id,label_pk_id,label_code,label_pkg,val,product_id,rebate_batch_id,stk_batch_id,dt_delivery,company_id,vtype_id) select "+\
                                    "label_id,label_pk_id,label_code,label_pkg,val,product_id,"+id+","+bid+",dt_delivery,"+str(p.id)+","+vid+" from "+tb
                                cur.execute(s)     
        data['amount']=amt
        data['amount_neg']=amt_neg   

    
    
    cur.close() 
    return data










@login_required
def check_stroegeo(request):
    c=request.user.company
    cur=connection.cursor()
    if request.method=='GET':
        data=[]
        clmns=['仓库编号','现有仓库','经销商名称','营销层级','父级','上报时间','操作']
        if c.level_id==1:        
            s="select id,tm,"+\
                "(select name from company_company where id=a.company_id),"+\
                "(select name from company_level   where id=(select level_id  from company_company where id=a.company_id)),"+\
                "(select name from company_company  where id=(select parent_id from company_company where id=a.company_id)),"+\
                "(select count(*) from inventory_storehousebd09 where company_id=a.company_id),"+\
                "company_id from inventory_storehousebd09 a "+\
                "where ancestor_id="+str(c.id)+" and checked_by_id is null"
            cur.execute(s)
            for r in cur.fetchall():
                id=str(r[0])
                data.append([ id.zfill(8),r[5],"<div class='agt'>"+r[2]+"</div>",
                    r[3],r[4],r[1].strftime('%Y-%m-%d %H:%M:%S'),
                    "<button class='btn btn-xs btn-primary btn-ck' sid='"+id+"' sn='"+id.zfill(8)+"'>核准</button>"+\
                    "<button class='btn btn-xs btn-primary btn-vw' cid='"+str(r[6])+"'>查看</button>"
                ])     
        return render(request,'inventory/check_storegeo.html',{'data':data,'clmns':clmns,'subtt':[_('经销商管理'),_('待核准仓库')]})
    else:  
        id=str(request.POST.get('id'))
        uid=str(request.user.id)
        t=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')        
        cur.execute("update inventory_storehousebd09 set tm_checked='"+t+"',checked_by_id="+uid+" where id="+id)
        return JsonResponse({'e':''})







#2020-10-27 酒鬼扫码枪瓶盖绑定接口
def bottlecap_binding(request,company_id,process_id): 
    rmk='扫码枪在线绑定'
    #rmk='测试'    
    data={'e':'','warning':'','bottles':0,'bound':0}
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    
    #瓶盖实时绑定数据存放的表名
    tb_cap='logistics.z_bottlecap_binding'
    #连接REDIS数据库,指定db10
    #rd=redis.StrictRedis(host='localhost', port=settings.RD['port'], db=10, password=settings.RD['password'], decode_responses=True) 
    # 2022-09-08
    rd = redis.StrictRedis(connection_pool=settings.BOTTLECAP_BINDING_POOL)


    #是否为盖码，是否为临时标，扫码枪已做判断，接口不再做判断
    #process_id  1:瓶盖临时标 2:盒与临时标 3:扫箱码检查       
    
    tmp=request.GET.get('temp','')
    lbl=request.GET.get('label','')
    product=request.GET.get('product','')
    
    #2020-11-11
    pid=request.GET.get('product_id','')
    
    line=request.GET.get('line','')
    user=request.GET.get('user','0')
    batch_no=request.GET.get('batch_no','').upper()

    #2021-06-21    
    store_id=request.GET.get('store_id','null')
    qc=request.GET.get('qc','null')
    if qc!='null':
        qc="'"+qc+"'"

    if process_id in ['1','2']:        
        if len(tmp)!=12 or len(lbl)!=12:
            data['e']='标签号码和临时标长度不正确'
            return JsonResponse(data)

    tm=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')    

    cur=connection.cursor()

    #只有瓶盖-临时标在REDIS设置键值对
    prfx='bottlecap_'+company_id+'_'
    tmp=prfx+tmp
    #为提高效率，不考虑套标跨段，且只有箱/瓶二级套标关系
    tb='label.t'+lbl[:4]  
    if process_id=='1':      
        #2021-03-19
        s="select to_char(tm,'yyyy-mm-dd HH24:MM:SS'),box_code,bottle,product from "+tb_cap+" where label='"+lbl+"'"
        cur.execute(s)
        r=cur.fetchone()
        if r:
            prd=''
            if r[3]:
                prd='('+r[3]+')'
            data['e']='此盖已使用,'+r[0]+'箱:'+r[1]+',盒:'+r[2]+prd
        else:
            o=rd.hgetall(tmp)        
            if o:
                if o['label']!=lbl:
                    data['warning']='此临时标已于'+o['time']+'与盖码绑定过,现绑定为新盖码'       
            rd.hmset(tmp,{'label':lbl,'product':product,'line':line,'user':user,'time':tm,'batch_no':batch_no})
    elif process_id=='2':  
        #防止把盒标扫成临时标
        if not lbl.isdigit() or lbl[:3]=='444':
            data['e']='请扫盒标'
        else:
            #2021-01-06 盒码（封口标）有可能是防伪码 (品鉴)
            if lbl[:2]=='40':
                r=requests.get('http://china315net.com:35222/wuliu/47/fw/wuliu/?fw_code='+lbl)
                d=r.json()
                if d['wl']:
                    lbl=d['wl']  
                    tb='label.t'+lbl[:4] 
            if not pid:
                pid="null"
            d=rd.hgetall(tmp)   
            if d:           
                g=d['label']
                c=decrypt_11h(g)   
                s="INSERT INTO "+tb_cap+"("+\
                    "label,code,bottle,type,remark,company_id,product,prd_line,username,label_pk_id,box_code,bottles_cnt,batch_no,product_id,qc,store_id) select "+\
                    "'"+g+"','"+c+"','"+lbl+"',999,'"+rmk+"',"+company_id+",'"+product+"','"+line+"','"+user+"',l.parent_id,"+\
                    "(select code from "+tb+" where id=l.parent_id),"+\
                    "(select count(*) from "+tb+" where package_id=1 and parent_id=l.parent_id),"+\
                    "'"+batch_no+"',"+pid+","+qc+","+store_id+" from "+\
                    "(select cast('"+lbl+"' as varchar(20)) code) a "+\
                    "left outer join "+\
                    "(select code,id,parent_id from "+tb+") l "+\
                    "on a.code=l.code returning label_pk_id"  
                try:
                    cur.execute(s)                    
                except Exception:
                    s="INSERT INTO "+tb_cap+"("+\
                        "label,code,bottle,type,remark,company_id,product,prd_line,username,label_pk_id,box_code,bottles_cnt,batch_no,product_id) values "+\
                        "('"+g+"','"+c+"','"+lbl+"',999,'"+rmk+"',"+company_id+",'"+product+"','"+line+"','"+user+"',null,"+\
                        "null,null,'"+batch_no+"',"+pid+") returning label_pk_id"      
                    cur.execute(s)
                r=cur.fetchone()
                if r[0]:
                    rd.delete(tmp)
                else:
                    data['e']='盒标 '+lbl+' 不存在'  
            else:
                data['e']='盒标 '+lbl+' 对应的临时标未与瓶盖绑定'            
    elif process_id=='3':   
        #2021-04-17 箱标有可能是防伪码 (品鉴)
        if lbl[:2]=='40':
            r=requests.get('http://china315net.com:35222/wuliu/47/fw/wuliu/?fw_code='+lbl)
            d=r.json()
            if d['wl']:
                lbl=d['wl']    
                tb='label.t'+lbl[:4] 

        #2021-11-17
        else:
            cur.execute("select package_id from label.lbl_binding_jg where code='"+lbl+"'")
            rr=cur.fetchone()
            if rr:
                if rr[0]!=3:
                    data['e']=lbl+' 请扫描箱标'
                    cur.close()
                    return JsonResponse(data)
                tb='label.lbl_binding_jg'
            else:
                tb='label.t'+lbl[:4]

        r=None
        cnt=0
        tt=0
        err='null'
        try:      
            s="select package_id,coalesce(parent_id,id),"+\
                "(select count(*) from "+tb+" where parent_id=coalesce(a.parent_id,a.id) and package_id=1) "+\
                "from "+tb+" a where code='"+lbl+"' "+\
                "union all "+\
                "select package_id,coalesce(parent_id,id),"+\
                "(select count(*) from label.lbl_binding_jg where parent_id=coalesce(a.parent_id,a.id) and package_id=1) "+\
                "from label.lbl_binding_jg a where code='"+lbl+"' "
            cur.execute(s)
            r=cur.fetchone()
        except Exception:
            pass        
        if not r:
            data['e']='箱标 '+lbl+' 不存在'
        else:
            if r[0]!=3:
                data['e']=lbl+' 请扫描箱标'
            else:
                #tt=r[2]
                data['bottles']=tt
                #s="select count(*) from ( select bottle from "+tb_cap+" where "+\
                #    "label_pk_id="+str(r[1])+" group by bottle) a"

                s="select count(*),(select bottles_cnt from "+tb_cap+" where label_pk_id="+str(r[1])+" limit 1) "+\
                    "from ( select bottle from "+tb_cap+" where "+\
                        "label_pk_id="+str(r[1])+" group by bottle) a"
                cur.execute(s)
                r=cur.fetchone()                
                
                if r[1]:
                    cnt=r[0] 
                    tt=r[1]
                    data['bottles']=tt
                    data['bound']=cnt                  
                    if r[0]<tt:
                        data['e']='箱标 '+lbl+" 绑定不完整 "+str(cnt)+"/"+str(tt)
                else:
                    data['e']='此箱标没有任何瓶盖绑定信息'
        if data['e']:
            err="'"+data['e']+"'"
        s="INSERT INTO logistics.z_bottlecap_boxcheck("+\
            "code,bottles_perbox,cnt_checked,username,product,prd_line,err) values ("+\
            "'"+lbl+"',"+str(tt)+","+str(cnt)+",'"+user+"','"+product+"','"+line+"',"+err+")"
        cur.execute(s)    



    #2021-09-22 不使用临时标，套标瓶盖码直接绑盒标
    elif process_id=='100':
        rmk='扫码枪在线绑定(套标盖码盒标直接绑定)'
        lbl=request.GET.get('bottle','')
        g=request.GET.get('cap','')
        c=decrypt_11h(g) 
        tb='label.t'+lbl[:4] 
        if lbl[:2]=='40':   #盒码（封口标）有可能是防伪码 (品鉴)
            r=requests.get('http://china315net.com:35222/wuliu/47/fw/wuliu/?fw_code='+lbl)
            d=r.json()
            if d['wl']:
                lbl=d['wl']  
                tb='label.t'+lbl[:4] 
        if not pid:
            pid="null"
        #检查盒标或瓶盖码是否已经绑定过
        s="select to_char(tm,'yyyy-mm-dd HH24:MM:SS'),coalesce(box_code,''),coalesce(bottle,''),product from "+tb_cap+" where "+\
            "bottle='"+lbl+"' or label='"+g+"'"
        cur.execute(s)
        r=cur.fetchone()
        if r:
            prd=''
            if r[3]:
                prd='('+r[3]+')'
            s="INSERT INTO z_bottlecap_binding_err(type,remark,company_id,product,prd_line,username,"+\
                "bottles_cnt,batch_no,binding_type,store_id,qc,contents)  values "+\
                "(999,'已存在绑定关系',"+company_id+",'"+prd+"','"+line+"','"+user+"',"+\
                "(select bottle_cnt from z_bottle_cap_product where id="+pid+"),"+\
                "'"+batch_no+"',2,"+store_id+",'"+qc+"','"+json.dumps({"bottle":lbl,"cap":g})+"')"
            cur.execute(s)
            data['e']='此盒标或瓶盖已有绑定记录,'+r[0]+'箱:'+r[1]+',盒:'+r[2]+prd            
            cur.close()
            return JsonResponse(data)          
        s="INSERT INTO "+tb_cap+"("+\
            "label,code,bottle,type,remark,company_id,product,prd_line,username,label_pk_id,box_code,bottles_cnt,batch_no,product_id,qc,store_id) select "+\
            "'"+g+"','"+c+"','"+lbl+"',999,'"+rmk+"',"+company_id+",'"+product+"','"+line+"','"+user+"',l.parent_id,"+\
            "(select code from "+tb+" where id=l.parent_id),"+\
            "(select count(*) from "+tb+" where package_id=1 and parent_id=l.parent_id),"+\
            "'"+batch_no+"',"+pid+","+qc+","+store_id+" from "+\
            "(select cast('"+lbl+"' as varchar(20)) code) a "+\
            "left outer join "+\
            "(select code,id,parent_id from "+tb+") l "+\
            "on a.code=l.code returning label_pk_id"  
        try:
            cur.execute(s)                    
        except Exception:
            s="INSERT INTO "+tb_cap+"("+\
                "label,code,bottle,type,remark,company_id,product,prd_line,username,label_pk_id,box_code,bottles_cnt,batch_no,product_id) values "+\
                "('"+g+"','"+c+"','"+lbl+"',999,'"+rmk+"',"+company_id+",'"+product+"','"+line+"','"+user+"',null,"+\
                "null,null,'"+batch_no+"',"+pid+") returning label_pk_id"      
            cur.execute(s)
        r=cur.fetchone()
        if r[0]:
            #rd.delete(tmp)
            pass
        else:
            data['e']='盒标 '+lbl+' 不存在'



    cur.close()
    return JsonResponse(data)


#2021-04-07
@csrf_exempt
def thirdparty_binding000(request,company_id,what):
    data={'e':'','cnt':0}
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    cnt=0
    #酷客白 独箱标(绑16个外盖码)
    if company_id=='1' and what=='box_bottle':
        cur=connection.cursor()
        r=json.loads(request.body)
        if 'bottles_cnt' not in r or 'product_id' not in r or 'product_name' not in r or 'box_code' not in r  or 'bottles' not in r or 'batch_no' not in r or 'line' not in r or 'user' not in r:
            data['e']='parameters  missing'
            return JsonResponse(data)       
        pid='null'
        try:
            cur.execute("select id from label.t"+r['box_code'][:4]+" where code='"+r['box_code']+"'")
            rr=cur.fetchone()
            if rr:
                pid=str(rr[0])
        except Exception:
            pass       

        
        a=[]
        e=[]
        sPrefix="INSERT INTO z_bottlecap_binding(label,code,bottle,type,remark,company_id,product_id,product,"+\
            "prd_line,username,box_code,bottles_cnt,batch_no,label_pk_id) values "
        for b in r['bottles']:
            e.append(b)
            a.append("(null,'"+b+"','"+b+"',999,'扫码枪在线绑定',"+company_id+","+str(r['product_id'])+",'"+r['product_name']+\
                "','"+r['line']+"',"+str(r['user'])+",'"+r['box_code']+"',"+str(r['bottles_cnt'])+",'"+r['batch_no']+"',"+pid+")"
            )
        if a:

            #瓶盖码是否已绑定过
            #s="select max(box_code),bottle,max(prd_line),to_char(max(tm),'yyyy-mm-dd HH24:MI:SS') from z_bottlecap_binding "+\
            #    "where bottle in ('"+"','".join(e)+"') group by bottle"
            #cur.execute(s)
            #err=[]
            #for r in cur.fetchall():
            #    err.append({'箱标':r[0],' 盖码':r[1],'产线':r[2],'时间':r[3]})
            #if err:
            #    data['e']=str(cur.rowcount)+'枚外盖码已绑定过'
            #    data['details']=err
            #    return JsonResponse(data)

            cur.execute(sPrefix+",".join(a))
            cnt=cur.rowcount
        cur.close()
    data['cnt']=cnt

    return JsonResponse(data)






#2021-05-19
@csrf_exempt
def thirdparty_binding(request,company_id,what):
    data={'e':'','cnt':0}
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    cnt=0
    #酷客白 独箱标(绑16个外盖码)
    if company_id=='1' and what=='box_bottle':
        is_box_err=False
        cur=connection.cursor()
        rr=json.loads(request.body)
        if 'bottles_cnt' not in rr or 'product_id' not in rr or 'product_name' not in rr or 'box_code' not in rr  or 'bottles' not in rr or 'batch_no' not in rr or 'line' not in rr or 'user' not in rr:
            data['e']='parameters  missing'
            return JsonResponse(data)       
        pid='null'        
        try:
            s="select coalesce(parent_id,id) from label.t"+rr['box_code'][:4]+" where code='"+rr['box_code']+"'"    
            cur.execute(s)
            r=cur.fetchone()
            if r:
                pid=str(r[0])
            else:                
                is_box_err=True
        except Exception:
            is_box_err=True              
        a=[]
        e=[]
        sPrefix="INSERT INTO z_bottlecap_binding(label,code,bottle,type,remark,company_id,product_id,product,"+\
            "prd_line,username,box_code,bottles_cnt,batch_no,label_pk_id,store_id,qc) values "

        #2021-06-21
        store_id='null'
        qc='null'
        if 'store_id' in rr:
            store_id=rr['store_id']
        if 'qc' in rr:
            qc="'"+rr['qc']+"'"
        
        #2021-05-19
        sPrefix_e="INSERT INTO z_bottlecap_binding_err(label,code,bottle,type,remark,company_id,product_id,product,"+\
            "prd_line,username,box_code,bottles_cnt,batch_no,label_pk_id,store_id,qc) values "

        for b in rr['bottles']:
            e.append(b)            
        is_err=False
        if rr['bottles']:            
            #箱码是否存在
            if is_box_err:
                is_err=True
                data['e']='箱标错误,'+rr['box_code']

            #箱码是否已绑定过
            s="select box_code,to_char(tm,'yyyy-mm-dd HH24:MI:SS') from z_bottlecap_binding "+\
                "where box_code='"+rr['box_code']+"' order by dt,id limit 1"            
                        
            cur.execute(s)
            r=cur.fetchone()
            if r:
                is_err=True
                data['e']=data['e']+'箱标'+r[1]+'已绑定过'    

            #瓶盖码是否已绑定过
            s="select max(box_code),bottle,max(prd_line),to_char(max(tm),'yyyy-mm-dd HH24:MI:SS') from z_bottlecap_binding "+\
                "where bottle in ('"+"','".join(e)+"') group by bottle"
            cur.execute(s)
            err=[]
            for r in cur.fetchall():
                err.append({'箱标':r[0],' 盖码':r[1],'产线':r[2],'时间':r[3]})
            if err:
                is_err=True
                data['e']=data['e']+str(cur.rowcount)+'枚外盖码已绑定过'
                data['details']=err                   
            if is_err:
                for b in rr['bottles']:            
                    a.append("(null,'"+b+"','"+b+"',999,'"+data['e'][:100]+"',"+company_id+","+str(rr['product_id'])+",'"+rr['product_name']+\
                        "','"+rr['line']+"',"+str(rr['user'])+",'"+rr['box_code']+"',"+str(rr['bottles_cnt'])+",'"+rr['batch_no']+"',"+pid+","+store_id+","+qc+")"
                    ) 
                cur.execute(sPrefix_e+",".join(a))
            else:
                for b in rr['bottles']:           
                    a.append("(null,'"+b+"','"+b+"',999,'扫码枪在线绑定',"+company_id+","+str(rr['product_id'])+",'"+rr['product_name']+\
                        "','"+rr['line']+"',"+str(rr['user'])+",'"+rr['box_code']+"',"+str(rr['bottles_cnt'])+",'"+rr['batch_no']+"',"+pid+","+store_id+","+qc+")"
                    )
                cur.execute(sPrefix+",".join(a))
            cnt=cur.rowcount
        cur.close()
    data['cnt']=cnt

    return JsonResponse(data)










def bottlecap_products(request,company_id):
    data={'e':'','data':[]}
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    if company_id=='1':
        p=[]        
        cur=connection.cursor()
        #cur.execute("select product_id,product_name,bottle_cnt FROM z_bottle_cap_product")
        cur.execute("select id,product_name,bottle_cnt,box_cnt,carton_cnt,external_product_no FROM z_bottle_cap_product")
        for r in cur.fetchall():
            #p.append({'name':r[1],'id':r[0],'bottles':r[2],'boxes':r[3],'cartons':r[4]})
            p.append({'name':r[1],'id':r[0],'code':r[5],'bottles':r[2],'boxes':r[3],'cartons':r[4]})
        data['data']=p
        cur.close()
    return JsonResponse(data)



@login_required
def bottlecap_output(request):    
    c=request.user.company
    cur=connection.cursor()
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('dt_fr', dt)
    dt_to = request.GET.get('dt_to', dt)
    data={'data':[],'clmns':['日期','产线','产品','批次','仓库','质检','瓶数','备注'],'dt_fr':dt_fr,'dt_to':dt_to}

    s="select dt,prd_line,(select product_name from z_bottle_cap_product where id=a.product_id),batch_no,cnt,"+\
        "coalesce((select name from inventory_storehouse where  id=a.store_id),''),qc from "+\
        "(select to_char(dt,'yyyy-mm-dd') dt,prd_line,product_id,batch_no,count(*) cnt,"+\
            "coalesce(store_id,0) store_id,coalesce(qc,'') qc from z_bottlecap_binding "+\
            "where label_pk_id is not null and is_scraped=false and company_id="+str(c.id)+" and dt between '"+dt_fr+"' and '"+dt_to+"' "+\
            "group by dt,prd_line,product_id,batch_no,store_id,qc,batch_no order by dt,prd_line,product_id,batch_no,store_id,qc"+\
        ") a"
    cur.execute(s)
    #print(s)
    rs=cur.fetchall()
    for r in rs:        
        rmk=''        
        s="select a.label_pk_id,box_code,a.bottles_cnt,"+\
            "array_to_string(array("+\
                "select bottle from z_bottlecap_binding where dt='"+r[0]+"' and  label_pk_id=a.label_pk_id),',') bottles,"+\
            "to_char((select min(tm) from z_bottlecap_binding where dt='"+r[0]+"' and label_pk_id=a.label_pk_id),'HH24:MI:SS') min_tm,"+\
            "to_char((select max(tm) from z_bottlecap_binding where dt='"+r[0]+"' and label_pk_id=a.label_pk_id),'HH24:MI:SS') min_tm "+\
            "from "+\
            "("+\
                "select label_pk_id,box_code,bottles_cnt,count(*) cnt from z_bottlecap_binding  "+\
                "where dt='"+r[0]+"' and product='"+r[2]+"' and prd_line='"+r[1]+"' and batch_no='"+r[3]+"' and label_pk_id is not null "+\
                "group by label_pk_id,box_code,bottles_cnt having count(*)<>bottles_cnt "+\
            ") a " 
        cur.execute(s)
        cnt=cur.rowcount
        if cnt:
            rmk="共 "+str(cnt)+"箱 绑定数据不完整"   
        html=[]
        for rr in cur.fetchall():               
            bts=rr[3].split(',')
            ul='<div>箱号：'+rr[1]+' '+\
                    '<span style="color:red;margin-left:7px;">'+str(len(bts))+'</span>'+'/'+\
                    '<span style="color:red;">'+str(rr[2])+'</span>'+\
                '<div>时间：'+rr[4]+'至'+rr[5]+'</div>' 
            for bt in bts:
                ul=ul+'<li style="margin-left:44px;" >'+bt+'</li>'                
            ul=ul+"</div>"
            html.append(ul)    
        if rmk:
            rmk="<span style='cursor:pointer' title='不完整箱号列表：'  data-container='#data-content' "+\
                "data-toggle='popover' data-content='"+"".join(html)+"' >"+rmk+"</span>"            
        data['data'].append([  r[0],r[1],r[2],r[3],r[5],r[6], r[4],rmk ])    
    return render(request, "inventory/bottlecap_output.html",data)





@csrf_exempt
def bottlecap_scrapped(request,company_id):
    data={'e':'','cnt':0}
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    guid=str(uuid.uuid1())
    a=[]
    r=json.loads(request.body)
    cur=connection.cursor()
    user=r['user']
    codes=r['codes']
    for c in codes:
        tb="label.t"+c[:4]
        a.append("('"+guid+"',"+company_id+",'"+c+"','"+user+"')")
    if a:
        cur.execute("INSERT INTO z_bottlecap_scrapped(guid,company_id,code,username) values "+  ",".join(a))        
        s="update z_bottlecap_binding set is_scraped=true where "+\
            "bottle in (select code from z_bottlecap_scrapped where guid='"+guid+"')"
        cur.execute(s)
        data['cnt']=cur.rowcount
    cur.close()   
    return JsonResponse(data)




#2020-11-04
#内参层级扫码新思路：
#一级：只做团购和零售出库扫码
#二级入库：
#1.检查公司是否给上级发过货
#2.入库后才可出库
#3.二级入库数核减一级库存
#2020-12-16
#4.同一箱/瓶，只能扫码一次
@csrf_exempt
def app_labelcheck_new(request):
    data={'e':'','code':'','package_id':0,'label_pk_id':0,'err_code':0,'product_id':0,'product_name':''}
    c=request.POST.get('code','')
    company_id=request.POST.get('company_id','')
    vtype_id=request.POST.get('vtype_id','')  
    user_id=request.POST.get('user_id','')    
    
    #2020-04-23
    data['code']=c
    if not c or not company_id or not vtype_id:
        data['e']='parameter missing'
        data['err_code']=10000
        return JsonResponse(data)  
    if request.method=='GET':
        data['e']='invalid method'
        data['err_code']=10003
        return JsonResponse(data)

    companys=Company.objects.filter(id=int(company_id))
    if not companys:
        data['e']='invalid company id'
        data['err_code']=10000
        return JsonResponse(data)
    company=companys[0]    
    lv_id=company.level_id  
    cid=company.id
    pid=company.parent_id
    aid=company.ancestor_id
    cur=connection.cursor()  
    
    #主箱标ID
    lbl_pk_id=0
    #酒鬼防伪码以40开头
    if c[:2]=='40':        
        cur.execute("SELECT wl_code FROM label.lbl_fw_wl where fw_code='"+c+"'")
        r=cur.fetchone()
        if r:
            c=r[0]
        else:  
            r=requests.get('http://china315net.com:35222/wuliu/47/fw/wuliu/?fw_code='+c)
            d=r.json()   
            if d['wl']:
                c=d['wl']
    data['code']=c
    if company.level.sn==0:
        data['e']=_('此工具只适用于经销商和门店')
        data['err_code']=10000
        return JsonResponse(data) 


    #2021-01-27 标签是否有替换    
    s="select code0,code,dt from label.lbl_replace_details where code='" + c + "'"+\
        " or code0='"+c+"' order by id desc limit 1"  
    cur.execute(s)   
    rr=cur.fetchone()    
    if rr:
        c=rr[0]       


    #print(c)
    

    tb='label.t'+c[:4]
    #2020-07-27 是否跨段动态绑定
    cur.execute("select tbname from label.lbl_tbcross where segment='"+c[:4]+"'")
    rrr=cur.fetchone()
    if rrr:
        tb='label.'+rrr[0]  
    try:
        cur.execute("select package_id,coalesce(parent_id,id) from "+tb+" where code='"+c+"'")
        r=cur.fetchone()
        if not r[0]:
            data['e']=_('标签号码未激活')
            data['err_code']=20001
            return JsonResponse(data)
        else:
            data['package_id']=r[0]
            data['label_pk_id']=r[1]
            lbl_pk_id=str(r[1])
            pkg=r[0]
    except Exception:
        data['e']=_('标签号码错误')
        data['err_code']=20000
        return JsonResponse(data)   
    

    #箱标,瓶标在同一营销层级都只能入/出一次
    #sLbl=" and label_code='"+c+"'"
    #if int(vtype_id)==3: 此处判断有误,应判断标签是否为箱标
    #if pkg==3:
    #    sLbl=" and label_pk_id="+str(lbl_pk_id)
    #s="select product_id,tm from inventory_stkdetails a where vtype_id="+vtype_id+\
    #    " and ancestor_id="+str(aid)+sLbl+\
    #    " and (select level_id from company_company where id=a.company_id)="+str(lv_id)
    #cur.execute(s)      
    #r=cur.fetchone()
    #if r:
    #    t1=''
    #    if vtype_id=='1':            
    #        t1=_('此标签已入库')
    #    elif vtype_id=='2':
    #        t1=_('此标签已出库')     
    #    data['err_code']=10001
    #    data['e']=t1+'('+r[1].strftime('%Y-%m-%d %H:%M:%S')+')'
    #    return JsonResponse(data)      


    #2021-01-01，内参层级返利规则：所有标签，只能扫码返利一次
    sLbl=" and label_code='"+c+"'"   
    if pkg==3:
        sLbl=" and label_pk_id="+str(lbl_pk_id)    
    s="select label_code,label_pkg,vtype_id,to_char(a.tm,'yyyy-mm-dd HH24:MI:SS'),"+\
        "coalesce((select name from company_company where id=a.company_id),''),"+\
        "coalesce((select name from company_company where id=(select company_to_id from inventory_batch where id=a.stk_batch_id)),'') "+\
        "from "+\
        "(select label_code,company_id,stk_batch_id,vtype_id,label_pkg,tm from sales_channelrebatedetails "+\
            "where (select ancestor_id from sales_channelrebatebatch where id=rebate_batch_id)="+str(aid)+\
            "and is_deducted=false "+sLbl+" order by id limit 1) a"     
    cur.execute(s)      
    r=cur.fetchone()
    if r:
        t1=''
        t2=''
        t3=''
        if r[1]==3:
            if r[0]==c:
                t1='此箱标'
            else:
                t1='此箱的另一枚箱标'+c
        else:
            t1='此瓶'        
        if r[2]==1:            
            t2='已扫码入库'
        elif r[2]==2:
            t2='已扫码出库'    
        if r[5]:
            t3="->"+r[5]
        data['err_code']=10001
        data['e']=t1+t2+'('+r[3]+' '+r[4]+t3+')'
        return JsonResponse(data)      
    
    
    if int(vtype_id)==1:        #扫码入库 （一级经销商不做入库操作）        
        #s="select id from inventory_stkdetails where vtype_id=2 and company_id="+str(aid)+\
        #    " and label_pk_id="+str(lbl_pk_id)+"  and company_to_id="+str(pid)
        #20211-01-20 内参有直接发货给二级
        s="select id from inventory_stkdetails where vtype_id=2 and company_id="+str(aid)+\
            " and label_pk_id="+str(lbl_pk_id)+"  and company_to_id in ("+str(pid)+","+str(cid)+")"  
            
        
        
        cur.execute(s)
        r=cur.fetchone()
        if not r:               #二级扫码入库错误信息
            data['err_code']=10001            
            data['e']='未查询到公司到一级经销商的发货记录'
            return JsonResponse(data)

        if lv_id==4:
            #经销商不能有此箱/瓶的扫码出库（团购/零售）记录
            e=''
            if pkg==1:
                e='此瓶所在箱'           
            else:
                e='此箱'
            s="select to_char(a.tm,'yyyy-mm-dd HH24:MI:SS'),"+\
                "(select name from company_company where id=a.company_id),"+\
                "(select name from company_company where id=a.company_to_id) from "+\
                "(select tm,company_id,company_to_id from inventory_stkdetails where vtype_id=2 " +\
                    "and label_pk_id="+str(lbl_pk_id)+" and company_to_id in (11013,11014)) a"
            cur.execute(s)
            r=cur.fetchone()
            if r:               
                data['err_code']=10001    
                data['e']=e+"已"+r[2]+'出库('+r[1]+' '+r[0]+')'
                return JsonResponse(data)
    elif int(vtype_id)==2:        
        if lv_id==2:            #一级扫码出库
            e='未查询到公司到一级经销商的发货记录'
            s="select id from inventory_stkdetails where vtype_id=2 and company_id="+str(aid)+\
                " and label_pk_id="+str(lbl_pk_id)+"  and company_to_id="+str(cid)
        else:                   #二级以上扫码出库
            e='请先进行入库操作'
            s="select id from inventory_stkdetails where vtype_id=1 and company_id="+str(cid)+\
                " and label_pk_id="+str(lbl_pk_id)
        cur.execute(s)
        r=cur.fetchone()
        if not r:
            data['err_code']=10001            
            data['e']=e
            return JsonResponse(data)

        if lv_id==2:
            #二级不能有入库记录
            e=''
            if pkg==1:
                e='此瓶所在箱'           
            else:
                e='此箱'
            s="select to_char(a.tm,'yyyy-mm-dd HH24:MI:SS'),"+\
                "(select name from company_company where id=a.company_id) from "+\
                "(select tm,company_id from inventory_stkdetails where vtype_id=1 " +\
                    "and label_pk_id="+str(lbl_pk_id)+" "\
                    "and (select level_id from company_company where id=company_id)=4"+\
                ") a"            
            cur.execute(s)
            r=cur.fetchone()
            if r:               
                data['err_code']=10001    
                data['e']=e+'二级已扫码入库('+r[1]+' '+r[0]+')'
                return JsonResponse(data)
        
    
    #同一层级，扫过箱标再扫瓶标
    if pkg==1:
        s="select a.tm,b.name from "+\
            "(select company_id,tm from inventory_stkdetails where label_pk_id="+str(lbl_pk_id)+\
                " and vtype_id="+vtype_id+" and label_pkg=3 and ancestor_id="+str(aid)+\
            ") a "+\
            "left outer join "+\
            "(select id,name,level_id from company_company) b "+\
            "on a.company_id=b.id "+\
            "where b.level_id="+str(lv_id)   
        cur.execute(s)
        r=cur.fetchone()
        if r:
            data['err_code']=10001            
            data['e']='对应箱标已被扫码('+r[1]+' '+r[0].strftime('%Y-%m-%d %H:%M:%S')+')'
    #同一层级，扫过瓶标再扫箱标
    elif pkg==3:    
        s="select a.tm,b.name from "+\
            "(select company_id,tm from inventory_stkdetails where label_pk_id="+str(lbl_pk_id)+\
                " and vtype_id="+vtype_id+" and label_pkg=1 and ancestor_id="+str(aid)+\
            ") a "+\
            "left outer join "+\
            "(select id,name,level_id from company_company) b "+\
            "on a.company_id=b.id "+\
            "where b.level_id="+str(lv_id)   
        cur.execute(s)
        r=cur.fetchone()
        if r:
            data['err_code']=10001            
            data['e']='此箱已有瓶标被扫码('+r[1]+' '+r[0].strftime('%Y-%m-%d %H:%M:%S')+')'   


    #2020-11-10 取标签产品ID
    s="select product_id,"+\
        "(select name from product_product where id=product_id) from inventory_stkdetails where label_pk_id="+str(lbl_pk_id)+\
        " and company_id="+str(aid)+" and vtype_id in (1,2) order by vtype_id limit 1"
    cur.execute(s)
    r=cur.fetchone()
    if r:
        data['product_id']=r[0]
        data['product_name']=r[1]
    return JsonResponse(data)  



#2020-11-10 检查有瓶盖产品，瓶盖绑定数据是否完整
def bottlecap_count(request,company_id,product_id):
    data={'e':''}
    e=''
    code=request.GET.get('label_code','')
    if not code:
        e='标签号码不能为空'
    elif len(code)<12:
        e='标签号码长度为12位'
    if e:
        data['e']=e
        return JsonResponse(data)

    cur=connection.cursor()
    tb='label.t'+code[:4]
    #有瓶盖数据的标签，目前只考虑箱瓶二级套标关系
    s="select a.package_id,a.label_pk_id,"+\
        "(select bottle_cnt from z_bottle_cap_product where product_id="+product_id+") bottles,"+\
        "coalesce((select count(*) from "+\
            "(select code from label.bottlecap where label_pk_id=a.label_pk_id "+\
                "and length(code)=12  group by code) b"+\
        "),0) cnt,"+\
        "to_char((select dt from inventory_stkdetails where label_pk_id=a.label_pk_id and company_id="+\
            company_id+" and vtype_id=1 and is_delete=false order by id desc limit 1),'yyyy-mm-dd') dt_inbound "+\
        "from (select package_id,coalesce(parent_id,id) label_pk_id from "+tb+"  where code='"+code+"') a" 
    try:
        cur.execute(s)
        r=cur.fetchone()
        if r:
            if not r[4] or r[4]>='2020-06-01':
                if r[2]>r[3]:
                    data['e']='瓶盖绑定数据不完整 '+str(r[3])+"/"+str(r[2])
    except Exception:
        data['e']='标签号码错误'
    cur.close()
    return JsonResponse(data)






#2020-11-12 获取标签信息---最终版
def label_all_info(company_id,code):  
    data = {
        'e': '',                #错误信息        
        'code': code,           #标签号码        
        'package':'',           #标签类型 箱/盒/瓶 
        'product':{
            'series_id':None,   #产品系列ID            
            'series_name':'',   #产品系列名称
            'id':None,          #产品ID    
            'name':'',          #产品名称
            'photo':'',         #产品图片链接
            'price':'',         #产品价格
            'batch_no':'',      #生产批次      
            'barcode':'',       #产品条形码
            'qc':'',            #质检员
            'alcohol':'',       #酒精度
            'volume':'',        #净含量
            'specification':''  #包装规格
        },              
        'boxes': {
            'pk':{
                'code':'',      #主箱标号码
                'replace':{},   #主箱标替换信息
            },       
            'related':[],       #关联箱标信息                
        },        
        'packets': [],          #盒标信息   页面以3级关联显示
        'bottles': [],          #瓶标信息   页面以2级关联显示
        'stock_dev':[],         #入库/出库信息
    } 
    
    has_outbound=False  #酒鬼酒如系统内没有物流信息，需查询SQL SVR数据

    cur=connection.cursor()
    label_pk_id=0
    # 标签是否有被替换的情况
    s="select code0,code,dt from label.lbl_replace_details where code='" + code + "' or code0='"+code+"' order by id desc limit 1"    
    cur.execute(s)   
    rr=cur.fetchone()    
    if rr:
        code=rr[0]              
    if company_id in (1,1644) and code[:1]=='4':
        r = requests.request('GET', 'http://www.china315net.com:35088/jg/fw_wl/'+code+'/')
        d = json.loads(r.text)
        if d['wl']:
            code=d['wl']
            data['code']=d['wl']
        else:
            data['e']='获取物流码失败'
            return data

    #2020-04-30 有标签要查BA表 "湖北裕贡酒业销售有限公司"
    if company_id in [16716]:
        cur.execute("select code_a FROM label.lbl_abcode where code_b='"+code+"'")
        r=cur.fetchone()
        if r:
            code=r[0]    

    t="label.t" +code[:4]
    #2020-07-27 是否跨段动态绑定
    cur.execute("select tbname from label.lbl_tbcross where segment='"+code[:4]+"'")
    rrr=cur.fetchone()
    if rrr:
        t='label.'+rrr[0]
    try:
        cur.execute("select id,package_id,(SELECT name FROM label.lbl_package where id=package_id)," + \
            "coalesce((select parent_id from " +t+ " where id=a.parent_id),parent_id) from "+t+" a where code='"+code+"'")   
        r = cur.fetchone()
        if not r:
            data['e'] = _('标签号码异常')
            return data
    except Exception as e:
        data['e'] = _('标签号码异常')
        return data    
    data['package']=r[2]
    if r[3]:
        label_pk_id=r[3]
    else:
        label_pk_id=r[0]  
    #主箱标
    s="select id,code,"+\
        "(select code0||','||code||','||to_char(dt,'yyyy-mm-dd') from "+\
            "label.lbl_replace_details where code=a.code or code0=a.code order by id desc limit 1) "+\
        "from "+t+" a where id="+str(label_pk_id)
    cur.execute(s)
    r=cur.fetchone()
    data['boxes']['pk']['code']=r[1]
    if r[2]:
        aa=r[2].split(',')
        data['boxes']['pk']['replace']={'old':aa[0],'new':aa[1],'date':aa[2]}
    #关联箱标
    s="select id,code,"+\
        "(select code0||','||code||','||to_char(dt,'yyyy-mm-dd') from "+\
            "label.lbl_replace_details where code=a.code or code0=a.code order by id desc limit 1) "+\
        "from "+t+" a where parent_id="+str(label_pk_id)+" and package_id=3"
    cur.execute(s)
    for r in cur.fetchall():
        d={}
        if r[2]:
            aa=r[2].split(',')
            d={'old':aa[0],'new':aa[1],'date':aa[2]}
        data['boxes']['related'].append({
            'code':r[1],
            'replace':d
        })
    #是否有盒标   
    s="select id,code,"+\
        "(select code0||','||code||','||to_char(dt,'yyyy-mm-dd') from "+\
            "label.lbl_replace_details where code=a.code or code0=a.code order by id desc limit 1) "+\
        "from "+t+" a where package_id=2 and parent_id="+str(label_pk_id)
    cur.execute(s)
    rs=cur.fetchall()
    #有盒标，三级对应
    if rs:
        for r in rs:   
            d={}
            if r[2]:
                aa=r[2].split(',')
                d={'old':aa[0],'new':aa[1],'date':aa[2]}                
            s="select id,code,"+\
                "(select code0||','||code||','||to_char(dt,'yyyy-mm-dd') from "+\
                    "label.lbl_replace_details where code=a.code or code0=a.code order by id desc limit 1) "+\
                "from "+t+" a where parent_id=" + str(r[0]) + " order by code"
            cur.execute(s)
            a = []
            for r1 in cur.fetchall():
                d={}
                if r1[2]:
                    aa=r1[2].split(',')
                    d={'old':aa[0],'new':aa[1],'date':aa[2]}
                a.append({'code':r1[1],'replace':d})
            data['packets'].append({
                'code': r[1],
                'replace':d,
                'bottles': a
            })
    else:
        #箱瓶二级对应
        s="select id,code,"+\
            "(select code0||','||code||','||to_char(dt,'yyyy-mm-dd') from "+\
                "label.lbl_replace_details where code=a.code or code0=a.code order by id desc limit 1) "+\
            "from "+t+" a where parent_id=" + str(label_pk_id) + " and package_id=1 order by code"           
        cur.execute(s)
        for r1 in cur.fetchall():
            d={}
            if r1[2]:
                aa=r1[2].split(',')
                d={'old':aa[0],'new':aa[1],'date':aa[2]}
            data['bottles'].append({ 'code':r1[1], 'replace':d  })
    cur.execute("select level_id,ancestor_id from company_company where id="+str(company_id))
    r=cur.fetchone()
    lv_id=r[0]   
    a_id=r[1]
    
    #产品信息
    if a_id==1644:
        s="select a.label_code,b.code,b.qc,p.name,coalesce(pnc.photo,p.photo),"+\
            "coalesce(pnc.barcode,p.barcode),coalesce(pnc.series_id,p.series_id),p.id,"+\
            "coalesce(to_char(coalesce(pnc.price,p.price),'FM999999.90'),''),"+\
            "coalesce((select name from product_series where id=coalesce(pnc.series_id,p.series_id)),''), "+\
            "(SELECT value FROM product_productprop where categoryprop_id=2 and id in "+\
                "(SELECT prd_property_id FROM product_prdprops where product_id=a.product_id)) alc,"+\
            "(SELECT value FROM product_productprop where categoryprop_id=3 and id in "+\
                "(SELECT prd_property_id FROM product_prdprops where product_id=a.product_id)) vol,"+\
            "(SELECT value FROM product_productprop where categoryprop_id=4 and id in "+\
                "(SELECT prd_property_id FROM product_prdprops where product_id=a.product_id)) spc "+\
            "from "+\
            "(select label_code,batch_id,product_id,"+\
                "(select nc_id from z_jg_nc_product where jg_id=product_id) nc_product_id "+\
                "from inventory_stkdetails where "+\
                "label_pk_id="+str(label_pk_id)+" and vtype_id in (1,2) and is_delete=false "+\
            "and ancestor_id=(select ancestor_id from company_company where id="+str(company_id)+")"+\
            " order by vtype_id,tm limit 1"+\
            ") a "+\
            "left outer join "+\
            "(select id,code,user_id,coalesce(qc_name,'') qc,batch_no from inventory_batch) b "+\
            "on a.batch_id=b.id "+\
            "left outer join "+\
            "(select id,name,series_id,photo,barcode,price from product_product) p "+\
            "on a.product_id=p.id "+\
            "left outer join "+\
            "(select id,name,series_id,photo,barcode,price from product_product) pnc "+\
            "on a.nc_product_id=pnc.id" 
    else:  
        s="select a.label_code,b.code,b.qc,p.name,p.photo,p.barcode,p.series_id,p.id,"+\
            "coalesce(to_char(p.price,'FM999999.90'),''),"+\
            "coalesce((select name from product_series where id=p.series_id),''), "+\
            "(SELECT value FROM product_productprop where categoryprop_id=2 and id in "+\
                "(SELECT prd_property_id FROM product_prdprops where product_id=a.product_id)) alc,"+\
            "(SELECT value FROM product_productprop where categoryprop_id=3 and id in "+\
                "(SELECT prd_property_id FROM product_prdprops where product_id=a.product_id)) vol,"+\
            "(SELECT value FROM product_productprop where categoryprop_id=4 and id in "+\
                "(SELECT prd_property_id FROM product_prdprops where product_id=a.product_id)) spc "+\
            "from "+\
            "(select label_code,batch_id,product_id,"+\
                "(select nc_id from z_jg_nc_product where jg_id=product_id) nc_product_id "+\
                "from inventory_stkdetails where "+\
                "label_pk_id="+str(label_pk_id)+" and vtype_id in (1,2) and is_delete=false "+\
                "and ancestor_id=(select ancestor_id from company_company where id="+str(company_id)+")"+\
                " order by vtype_id,tm limit 1"+\
            ") a "+\
            "left outer join "+\
            "(select id,code,user_id,coalesce(qc_name,'') qc,batch_no from inventory_batch) b "+\
            "on a.batch_id=b.id "+\
            "left outer join "+\
            "(select id,name,series_id,photo,barcode,price from product_product) p "+\
            "on a.product_id=p.id"    
    cur.execute(s)
    r=cur.fetchone()
    if r:
        data['product']['batch_no']=r[1]  
        data['product']['qc']=r[2]  
        data['product']['name']=r[3]
        if r[4]:            
            data['product']['photo']='/media/'+r[4] 
        if r[5]:
            data['product']['barcode']=r[5] 
        if r[6]:
            data['product']['series_id']=r[6]    
        data['product']['id']=r[7]         
        data['product']['price']=r[8]    
        if r[9]:
            data['product']['series_name']=r[9]  
        if r[10]:
            data['product']['alcohol']=r[10]
        if r[11]:
            data['product']['volume']=r[11]
        if r[12]:
            data['product']['specification']=r[12]

        #物流信息       
        sWhere=" where label_pk_id="+str(label_pk_id)
        if lv_id==1:
            #酒鬼可查内参物流
            if company_id==1:
                sAnd=" and ancestor_id in (1,1644)"
            else:
                sAnd=" and ancestor_id="+str(company_id)
        else:       
            #2020-11-14 经销商可查下级物流
            sAnd=" and company_id="+str(company_id)+" or (select parent_id from company_company where id=company_id)="+str(company_id) 
        s="select a.label_code,b.code,to_char(a.tm,'yyyy-mm-dd HH24:MI:SS'),"+\
            "(select username from company_user where id=b.user_id),"+\
            "(select name from company_company where id=a.company_id),"+\
            "coalesce((select name from company_company where id=a.company_to_id),''),"+\
            "(select name FROM label.lbl_package where id=a.label_pkg),"+\
            "(select name from inventory_voucher where id=a.vtype_id),"+\
            "coalesce((select name from inventory_storehouse where id=a.store_id),''),"+\
            "coalesce((select name from inventory_storehouse where id=a.store_fr_id),''),"+\
            "(select name from product_product where id=a.product_id),"+\
            "a.vtype_id from "+\
            "(SELECT label_code,vtype_id,batch_id,tm,product_id,store_id,store_fr_id,label_pkg,"+\
                "company_id,company_to_id from inventory_stkdetails"+sWhere+sAnd+") a "+\
            "left outer join "+\
            "(select id,code,user_id from inventory_batch) b "+\
            "on a.batch_id=b.id "+\
            "order by a.tm"
        cur.execute(s)
        for r in cur.fetchall():
            if r[11]==2:
                has_outbound=True
            data['stock_dev'].append({
                'label':r[0],
                'batch_no':[1],
                'time':r[2],
                'user':r[3],
                'company':r[4],
                'company_to':r[5],
                'package':r[6],
                'voucher':r[7],
                'store':r[8],
                'store_from':r[9],
                'product':r[10]
            })       

    if not has_outbound and company_id==1:
        #无系统物流信息，酒鬼，内参查询 SQL数据库    
        #dd=jiugui_local116(data['boxes']['pk']['code'])        

        #2022-03-15 酒鬼酒本地sql svr数据已转入 pg jiugui_local
        dd=get_jiugui_local(label_pk_id)

        for d in dd['stock_dev']:
            data['stock_dev'].append({
                'user':'',
                'store_from':'',
                'company':'酒鬼酒股份有限公司',
                'label':d['label_code'],
                'batch_no':d['voucher_no'],
                'time':d['time'],                
                'company_to':d['to_company'],
                'package':d['package'],
                'voucher':d['voucher_type'],                
                'store':d['store'],
                'product':d['product']
            })            
    return data



#2020-11-16 获取瓶盖数据不完整的箱号
def get_bottlecap_boxerr(request,company_id):
    data={'boxes':[],'e':''}
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)    
    cur=connection.cursor()
    cur.execute("select box_code,remark from z_bottlecap_boxerr where company_id="+company_id)
    for r in cur.fetchall():
        data['boxes'].append({'code':r[0], 'remark':r[1]})
    return JsonResponse(data)



#2020-12-14 酒鬼酒扫码枪 在线扫码 物流标签号码检查
def label_exists_check(request):
    data = {'e':'','label_pk_id':0,'label_id':0,'label_package':0,'label_code':''}
    e = time_key_check(request, sK)
    if e:
        data['e'] = e
        return JsonResponse(data)
    l=request.GET.get('label','')   
    if not l:
        data['e']='label_code missing'
        return JsonResponse(data)
    data['label_code']=l
    cur=connection.cursor()

    # 2022-07-06 可能扫防伪码
    if l[:2]=='40':
        tm=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        m2=hashlib.md5((settings.INTERNAL_SK+tm).encode('utf8'))
        key=m2.hexdigest()
        r = requests.post(settings.INTERNAL_URL + '/wl/', json={'key': key,'time': tm, 'labels': [{'id':1,"label":l}] })
        if r.status_code == 200:
            d = json.loads(r.text)
            if d:
                if d['data'][0]['code']:
                    l=d['data'][0]['code']            
    s="select id,package_id,coalesce(parent_id,id) from label.t"+l[:4]+" where code='"+l+"'"  
    try:
        cur.execute(s)
        r=cur.fetchone()
        if not r:
            data['e']=_('标签号码不存在')
        else:
            data['label_id']=r[0]
            data['label_package']=r[1]
            data['label_pk_id']=r[2]            
    except Exception:
        data['e']=_('标签号码不存在')
    cur.close()   
    return JsonResponse(data)



# David

@login_required
def inventory_period(request):
    data={'clmns':[],'data':[],'kjq':[],'now':[]}
    u = request.user.id
    c = request.user.company
    cur = connection.cursor()
    data['clmns']=[_('会计期'),_('备注')]
    s = "select to_char(dt,'yyyy-mm'),coalesce(remark,''),id from inventory_stkclosingperiod where ancestor_id = "+\
        str(c.id)+" or ancestor_id is null and dt < now()"
    #print(s)
    cur.execute(s)
    r = cur.fetchall()
    for i in r :
        data['data'].append([i[0],i[1]])
        data['kjq'].append([i[0],i[2]])
    #print(data)
    kjq = "select (select to_char(dt,'yyyy-mm') from inventory_stkclosingperiod where id = stkclosing_id"+\
        "),stkclosing_id from inventory_stkclosingcurrent where ancestor_id = "+str(c.id)
    cur.execute(kjq)
    for i in cur.fetchall():
        #print(i)
        data['now'].append([i[0],i[1]])

    #print(data)
    return render(request,'inventory/stock/period_conf.html',data)

@login_required
@csrf_exempt
def inventory_period_set(request,id=None):
    data={'msg':''}
    u = request.user.id
    c = request.user.company
    cur = connection.cursor() 
    if request.body:
        rd = json.loads(request.body)
        #print(rd['dt'])
        s = "select id,stkclosing_id from inventory_stkclosingcurrent where ancestor_id = "+str(c.id)
        cur.execute(s)
        r = cur.fetchone()
        #print(r)
        if r:
            cur.execute("update inventory_stkclosingcurrent set stkclosing_id = "+str(rd['dt'])+" where id ="+str(r[0]))
        else:
            cur.execute("insert into inventory_stkclosingcurrent (stkclosing_id,ancestor_id,company_id,user_id)"+\
                        "values("+str(rd['dt'])+","+str(c.id)+","+str(c.id)+","+str(u)+")")
        data['msg']='保存成功！'
    return JsonResponse(data)


#库存盘点
@csrf_exempt
def inventory_reserve(request):
    data ={
        'e':'',
        'msg':''
    }
    cur = connection.cursor()
    dt = datetime.datetime.now().strftime("%Y-%m-%d")
    tm = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    r = json.loads(request.body) 

    if 'company_id' not in r or 'user_id' not in r or 'label' not in r:
        data['e'] = 'missing data'
        return  JsonResponse(data)



    batch = StkClosingBatch()
    company_id = str(r['company_id'])
    cur.execute("select  ancestor_id from company_company where id = "+str(r['company_id']))
    ani = cur.fetchone()
    ancestor_id = str(ani[0])
    
    batch.company_id = r['company_id']
    batch.ancestor_id = ani[0]

    #batch.store = r['store']
    batch.user_id = r['user_id']
    batch.remark = r['remark']
    batch.dt = dt
    batch.tm = tm

    cur.execute("select id from inventory_stkclosingperiod "+\
                    "where id = (select stkclosing_id from inventory_stkclosingcurrent  "
                                "where ancestor_id = "+ancestor_id+")")
    sid = cur.fetchone()
    stkclosing_id = str(sid[0])
    batch.stkclosing_id = sid[0]
    batch.save()
    b_id = batch.id 
    a = []
    b = []
    #cur.execute("create temp table codes(label_code character varying(20),tb character varying(20)," + \
    #            "code character varying(20),label_id bigint,label_pk_id bigint,label_pkg smallint," + \
    #            "err character varying(100))")
    
    labels = r['label']
    for i in range(len(labels)): 
        c = labels[i]
        code = c['code']
        label_pk_id = str(c['label_pk_id'])
        package_id = str(c['package_id'])
        product_id = str(c['product_id'])
        #product_name = c['product_name']
    
    
        a.append("('"+str(code)+"',"+product_id+","+label_pk_id+","+package_id+","+company_id+","+ancestor_id+","+stkclosing_id+",1,now(),"+str(batch.id)+")")
        b.append("('"+str(code)+"',"+product_id+","+label_pk_id+","+package_id+","+company_id+","+ancestor_id+","+stkclosing_id+",1,now(),"+str(batch.id)+",1,0,1)")
        
                 
    s = "insert into inventory_stkclosingbatchdetails(label_code,product_id,label_pk_id, label_pkg,company_id,ancestor_id,"+\
                "stkclosing_id,store_id,tm,closingbatch_id) values"+ ",".join(a)
    cur.execute(s)
    
    
    sql = "INSERT INTO inventory_stkclosingdetails ( label_code, product_id, label_pk_id, label_pkg, company_id, ancestor_id, "+\
          "  stkclosing_id,store_id, tm, closingbatch_id, qty_tt, qty_adj, qty_act ) values"+ ",".join(b)
    cur.execute(sql)

    #返回箱盒瓶
    s="SELECT coalesce(sum(CASE label_pkg when 3 then 1 end),0),coalesce(sum(CASE label_pkg when 2 then 1 end),0),"+\
      "coalesce(sum(CASE label_pkg when 1 then 1 end),0) FROM "+\
     "inventory_stkclosingdetails WHERE stkclosing_id = "+stkclosing_id+" and company_id = "+company_id
    cur.execute(s)
    r = cur.fetchone()
    data['cnt'] = 1
    data['msg']="本次扫码量:%s箱%s盒%s瓶"%(r[0],r[1],r[2])
    return JsonResponse(data)



#月度库存与销售百分比
@login_required
@csrf_exempt
def product_send_out(request):
    cid = str(request.user.company_id)
    ancestor_id=str(Company.objects.get(id=cid).ancestor_id)
    dt = datetime.datetime.now()
    cur = connection.cursor()
    y = dt.year
    years = []
    for i in range(2019, y + 1):
        years.append(str(i))

    dt0 = dt.replace(day=1) - datetime.timedelta(days=1)
    y = str(dt0.year)
    m = str(dt0.month).zfill(2)
    yr = request.GET.get('year', y)
    mn = request.GET.get('month', m)
    d = str(monthrange(int(yr), int(mn))[1])

    dt1 = str(int(yr)-1) + '-' + mn + '-01'
    dt2 = str(yr) + '-' + mn + '-' + d

    dt1 = str(int(yr)-1) + '-' + mn
    dt2 = str(yr) + '-' + mn

    dt1 = request.GET.get('date_from', dt1)
    dt2= request.GET.get('date_to', dt2)
    company_id= request.GET.get('company')
    sdiv_id= request.GET.get('sdiv')
    data = {
        'quantitys': {'category': [], 'inbound': [],'remain':[]},
        'agents': {'category': [], 'data': []},
        'products': {'data': []},
        'years': years,
        'y': yr,
        'm': mn,
        'date_from': dt1,
        'date_to': dt2,
        'com':[],
        'sdiv':[],
        'filter':False,

    }

    s = "select id,name from company_company where ancestor_id = " + cid
    cur.execute(s)
    for r in cur.fetchall():
        data['com'].append(r)
    sdiv = "select id,name from company_salesdivision where company_id="+cid
    cur.execute(sdiv)
    for c in cur.fetchall():
        data['sdiv'].append(c)
    sWhere = "where company_id=" + cid + " and (dt between '" + dt1 + "' and '" + dt2 + "')"
    if cid == ancestor_id:
        data['filter'] = True
        sWhere = "WHERE (dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01') " + \
                 "AND ancestor_id=" + str(cid) + "  and vtype_id=1 "
        if company_id:
            # 经销商筛选 经销商入库与盘库
            s = "select c.d,c.vv,COALESCE(d.cc,'0'),concat(round((c.vv-COALESCE(d.cc,'0'))/(c.vv)*100,2))||'' " + \
                "from (SELECT to_char( dt, 'YYYY-MM' ) AS d,sum((select count(*)from inventory_stkdetails " + \
                "where batch_id=a.id  ))as vv FROM inventory_batch a WHERE (dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01') " + \
                 "AND company_id=" + str(company_id) + "  and vtype_id= 1  GROUP BY d )c left outer join " + \
                "(select (select to_char(dt,'YYYY-MM')as dd" + \
                " from inventory_stkclosingperiod where id = a.stkperiod_id),count(*)as cc from " + \
                "inventory_stkclosingstkdetails a where company_id = " + str(
                company_id) + " GROUP BY stkperiod_id)d on d.dd=c.d"
        elif sdiv_id:
            # 战区筛选 战区内经销商入库与盘库
            s = "select c.d,c.vv,COALESCE(d.cc,'0'),concat(round((c.vv-COALESCE(d.cc,'0'))/(c.vv)*100,2))||'' " + \
                "from (SELECT to_char( dt, 'YYYY-MM' ) AS d,sum((select count(*)from inventory_stkdetails " + \
                "where batch_id=a.id  ))as vv FROM inventory_batch a WHERE (dt BETWEEN '" + str(
                dt1) + "-01' AND '" + str(dt2) + "-01') " + \
                "AND company_id in (select id from company_company where division_id =" + str(sdiv_id) + "  ) "+\
                "and vtype_id=1 GROUP BY d )c left outer join " + \
                "(select (select to_char(dt,'YYYY-MM')as dd" + \
                " from inventory_stkclosingperiod where id = a.stkperiod_id),count(*)as cc from " + \
                "inventory_stkclosingstkdetails a where company_id in "+\
                "(select id from company_company where division_id =" + str(sdiv_id) + "  ) GROUP BY stkperiod_id)d on d.dd=c.d"
        else:
            #整体数据 company_id的出库 与 ancestor_id的盘库
            s= "select c.d,c.vv,COALESCE(d.cc,'0'),concat(round((c.vv-COALESCE(d.cc,'0'))/(c.vv)*100,2))||'' "+\
               "from (SELECT to_char( dt, 'YYYY-MM' ) AS d,sum((select count(*)from inventory_stkdetails "+\
               "where batch_id=a.id  ))as vv FROM inventory_batch a WHERE (dt BETWEEN '" + str(dt1) + "-01' AND '" + \
               str(dt2) + "-01') AND company_id=" + str(cid) + "  and vtype_id=2 GROUP BY d )c left outer join "+\
               "(select (select to_char(dt,'YYYY-MM')as dd"+\
               " from inventory_stkclosingperiod where id = a.stkperiod_id),count(*)as cc from " +\
               "inventory_stkclosingstkdetails a where company_id = "+str(cid)+" GROUP BY stkperiod_id)d on d.dd=c.d"
    else:
        #经销商级别图
        data['filter'] = False
        s = "select c.d,c.vv,COALESCE(d.cc,'0'),concat(round((c.vv-COALESCE(d.cc,'0'))/(c.vv)*100,2))||'' " + \
            "from (SELECT to_char( dt, 'YYYY-MM' ) AS d,sum((select count(*)from inventory_stkdetails " + \
            "where batch_id=a.id  ))as vv FROM inventory_batch a WHERE (dt BETWEEN '" + str(dt1) + "-01' AND '" + str(
            dt2) + "-01') " + \
            "AND company_id=" + str(cid) + "  and vtype_id= 1  GROUP BY d )c left outer join " + \
            "(select (select to_char(dt,'YYYY-MM')as dd" + \
            " from inventory_stkclosingperiod where id = a.stkperiod_id),count(*)as cc from " + \
            "inventory_stkclosingstkdetails a where company_id = " + str(
            cid) + " GROUP BY stkperiod_id)d on d.dd=c.d"
    cur.execute(s)

    for r in cur.fetchall():
        s=str(Decimal(r[1]).quantize(Decimal('0')))
        data['quantitys']['category'].append(r[0])
        data['quantitys']['inbound'].append(s)
        data['quantitys']['remain'].append(r[2])


    return render(request, 'sales/sales_table/send_out.html', data)


#环比
@login_required
@csrf_exempt
def product_inventory_in(request):
    cid = str(request.user.company_id)
    ancestor_id=str(Company.objects.get(id=cid).ancestor_id)
    dt = datetime.datetime.now()
    cur = connection.cursor()
    y = dt.year
    years = []
    for i in range(2019, y + 1):
        years.append(str(i))

    dt0 = dt.replace(day=1) - datetime.timedelta(days=1)
    y = str(dt0.year)
    m = str(dt0.month).zfill(2)
    yr = request.GET.get('year', y)
    mn = request.GET.get('month', m)
    d = str(monthrange(int(yr), int(mn))[1])


    dt11 = str(int(yr)-1) + '-' + mn
    dt22 = str(yr) + '-' + mn
    #print(dt11,dt22)

    dt11 = request.GET.get('date_from', dt11)
    dt22 = request.GET.get('date_to', dt22)

 

    dt1 = datetime.datetime.strptime(dt11, "%Y-%m" ) - relativedelta(months=1)
    dt2 = datetime.datetime.strptime(dt22, "%Y-%m" )

    dt1 = datetime.datetime.strftime(dt1, "%Y-%m" )
    dt2 = datetime.datetime.strftime(dt2, "%Y-%m" )

    company_id= request.GET.get('company')
    sdiv_id= request.GET.get('sdiv')
    data = {
        'quantitys': {'list_category': [], 'kucun_data': [],'sell_data': []},
        'agents': {'category': [], 'data': []},
        'products': {'data': []},
        'years': years,
        'y': yr,
        'm': mn,
        'date_from': dt11,
        'date_to': dt22,
        'com':[],
        'sdiv':[],
        'filter':False,
    }

    s = "select id,name from company_company where ancestor_id = " + cid
    cur.execute(s)
    for r in cur.fetchall():
        data['com'].append(r)
    sdiv = "select id,name from company_salesdivision where company_id=" + cid
    cur.execute(sdiv)
    for c in cur.fetchall():
        data['sdiv'].append(c)
    sWhere = "where company_id=" + cid + " and (dt between '" + dt1 + "' and '" + dt2 + "')"

    if cid == ancestor_id:
        data['filter'] = True
        sWhere = "WHERE (dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01') " + \
                 "AND ancestor_id=" + str(cid) + "  and vtype_id=1 "
        if company_id:
            # 经销商筛选 经销商入库与盘库
            s = "SELECT a.dd,concat ( COALESCE (C.vv ,0)),COALESCE ( d.cc, '0' ) remain," + \
                "concat ( (  COALESCE (C.vv ,'0')- COALESCE ( d.cc, '0' ) ) ) sell," + \
                "concat (round( ( C.vv - COALESCE ( d.cc, '0' ) ) / ( C.vv ) * 100, 2 ) || '' ) " + \
                "FROM( SELECT to_char( dt, 'YYYY-MM' ) AS dd " + \
                "FROM logistics.inventory_stkclosingperiod A " + \
                "WHERE ( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) " + \
                "GROUP BY dd )a left outer join 	(" + \
                "SELECT to_char( dt, 'YYYY-MM' ) AS d, SUM ( ( SELECT COUNT ( * ) FROM " \
                "logistics.inventory_stkdetails WHERE batch_id = A.ID ) ) AS vv FROM logistics.inventory_batch A " + \
                "WHERE( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) 	AND company_id = " + str(
                company_id) + "   AND vtype_id = 1 " + \
                "GROUP BY d )C on c.d=a.dd LEFT OUTER JOIN (" + \
                "SELECT( SELECT to_char( dt, 'YYYY-MM' ) AS dd FROM logistics.inventory_stkclosingperiod WHERE ID = A.stkperiod_id )," + \
                "COUNT ( * ) AS cc  FROM logistics.inventory_stkclosingstkdetails A " + \
                "WHERE company_id = " + str(company_id) + "  GROUP BY stkperiod_id ) d ON d.dd = a.dd order by a.dd"
        elif sdiv_id:
            # 战区筛选 战区内经销商入库与盘库
            s = "SELECT a.dd,concat ( COALESCE (C.vv ,0)),COALESCE ( d.cc, '0' ) remain," + \
                "concat ( (  COALESCE (C.vv ,'0')- COALESCE ( d.cc, '0' ) ) ) sell," + \
                "concat (round( ( C.vv - COALESCE ( d.cc, '0' ) ) / ( C.vv ) * 100, 2 ) || '' ) " + \
                "FROM( SELECT to_char( dt, 'YYYY-MM' ) AS dd " + \
                "FROM logistics.inventory_stkclosingperiod A " + \
                "WHERE ( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) " + \
                "GROUP BY dd )a left outer join 	(" + \
                "SELECT to_char( dt, 'YYYY-MM' ) AS d, SUM ( ( SELECT COUNT ( * ) FROM " \
                "logistics.inventory_stkdetails WHERE batch_id = A.ID ) ) AS vv FROM logistics.inventory_batch A " + \
                "WHERE( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) 	AND "+\
                "company_id in (select id from company_company where division_id =" + str(sdiv_id) + "  )    AND vtype_id = 1  " + \
                "GROUP BY d )C on c.d=a.dd LEFT OUTER JOIN (" + \
                "SELECT( SELECT to_char( dt, 'YYYY-MM' ) AS dd FROM logistics.inventory_stkclosingperiod WHERE ID = A.stkperiod_id )," + \
                "COUNT ( * ) AS cc  FROM logistics.inventory_stkclosingstkdetails A " + \
                "WHERE company_id in (select id from company_company where division_id =" + str(sdiv_id) + "  )   GROUP BY stkperiod_id ) d ON d.dd = a.dd order by a.dd"

        else:
            #整体数据 company_id的出库 与 ancestor_id的盘库
            s = "SELECT a.dd,concat ( COALESCE (C.vv ,0)),COALESCE ( d.cc, '0' ) remain," + \
                "concat ( (  COALESCE (C.vv ,'0')- COALESCE ( d.cc, '0' ) ) ) sell," + \
                "concat (round( ( C.vv - COALESCE ( d.cc, '0' ) ) / ( C.vv ) * 100, 2 ) || '' ) " + \
                "FROM( SELECT to_char( dt, 'YYYY-MM' ) AS dd " + \
                "FROM logistics.inventory_stkclosingperiod A " + \
                "WHERE ( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) " + \
                "GROUP BY dd )a left outer join 	(" + \
                "SELECT to_char( dt, 'YYYY-MM' ) AS d, SUM ( ( SELECT COUNT ( * ) FROM " \
                "logistics.inventory_stkdetails WHERE batch_id = A.ID ) ) AS vv FROM logistics.inventory_batch A " + \
                "WHERE( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) 	AND company_id = " + str(
                cid) + "   AND vtype_id = 2  " + \
                "GROUP BY d )C on c.d=a.dd LEFT OUTER JOIN (" + \
                "SELECT( SELECT to_char( dt, 'YYYY-MM' ) AS dd FROM logistics.inventory_stkclosingperiod WHERE ID = A.stkperiod_id )," + \
                "COUNT ( * ) AS cc  FROM logistics.inventory_stkclosingstkdetails A " + \
                "WHERE ancestor_id = " + str(cid) + "  GROUP BY stkperiod_id ) d ON d.dd = a.dd order by a.dd"
    else:
        s = "SELECT a.dd,concat ( COALESCE (C.vv ,0)),COALESCE ( d.cc, '0' ) remain," + \
            "concat ( (  COALESCE (C.vv ,'0')- COALESCE ( d.cc, '0' ) ) ) sell," + \
            "concat (round( ( C.vv - COALESCE ( d.cc, '0' ) ) / ( C.vv ) * 100, 2 ) || '' ) " + \
            "FROM( SELECT to_char( dt, 'YYYY-MM' ) AS dd " + \
            "FROM logistics.inventory_stkclosingperiod A " + \
            "WHERE ( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) " + \
            "GROUP BY dd )a left outer join 	(" + \
            "SELECT to_char( dt, 'YYYY-MM' ) AS d, SUM ( ( SELECT COUNT ( * ) FROM " \
            "logistics.inventory_stkdetails WHERE batch_id = A.ID ) ) AS vv FROM logistics.inventory_batch A " + \
            "WHERE( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) 	AND company_id = " + str(
            cid) + "   AND vtype_id = 1  " + \
            "GROUP BY d )C on c.d=a.dd LEFT OUTER JOIN (" + \
            "SELECT( SELECT to_char( dt, 'YYYY-MM' ) AS dd FROM logistics.inventory_stkclosingperiod WHERE ID = A.stkperiod_id )," + \
            "COUNT ( * ) AS cc  FROM logistics.inventory_stkclosingstkdetails A " + \
            "WHERE company_id = " + str(cid) + "  GROUP BY stkperiod_id ) d ON d.dd = a.dd order by a.dd"
    cur.execute(s)
    r = cur.fetchall()
    for i in range(1,len(r)):

        if r[i-1][2] != 0:
            re = (r[i][2]-r[i-1][2])/r[i-1][2]*100
        else:
            re=0
        if int(r[i-1][3]) !=0:
            se = (int(r[i][3])-int(r[i-1][3]))/int(r[i-1][3])*100
        else:
            se = 0
        se = round(se, 2)
        re = round(re, 2)
        data['quantitys']['list_category'].append((r[i][0]))
        data['quantitys']['kucun_data'].append(re)
        data['quantitys']['sell_data'].append(se)



    return render(request, 'sales/sales_table/inventory_in.html', data)

#同比
@login_required
@csrf_exempt
def product_inventory_tongbi(request):
    cid = str(request.user.company_id)
    ancestor_id=str(Company.objects.get(id=cid).ancestor_id)

    dt = datetime.datetime.now()
    cur = connection.cursor()
    y = dt.year
    years = []
    for i in range(2019, y + 1):
        years.append(str(i))

    dt0 = dt.replace(day=1) - datetime.timedelta(days=1)
    y = str(dt0.year)
    m = str(dt0.month).zfill(2)
    yr = request.GET.get('year', y)
    mn = request.GET.get('month', m)
    d = str(monthrange(int(yr), int(mn))[1])


    dt11 = str(int(yr)-1) + '-' + mn
    dt22 = str(yr) + '-' + mn

    dt11 = request.GET.get('date_from', dt11)
    dt22 = request.GET.get('date_to', dt22)


    dt1 = datetime.datetime.strptime(dt11, "%Y-%m" ) - relativedelta(months=12)
    dt2 = datetime.datetime.strptime(dt22, "%Y-%m" )

    dt1 = datetime.datetime.strftime(dt1, "%Y-%m" )
    dt2 = datetime.datetime.strftime(dt2, "%Y-%m" )

    company_id= request.GET.get('company')
    sdiv_id= request.GET.get('sdiv')

    data = {
        'quantitys': {'list_category': [], 'kucun_data': [],'sell_data': []},
        'agents': {'category': [], 'data': []},
        'products': {'data': []},
        'years': years,
        'y': yr,
        'm': mn,
        'date_from': dt11,
        'date_to': dt22,
        'com':[],
        'sdiv':[],
        'now':[],
        'filter':False,

    }

    s = "select id,name from company_company where ancestor_id = " + cid
    cur.execute(s)
    for r in cur.fetchall():
        data['com'].append(r)
    data['now']=[sdiv_id,'sss']

    sdiv = "select id,name from company_salesdivision where company_id=" + cid
    cur.execute(sdiv)
    for c in cur.fetchall():
        data['sdiv'].append(c)
    data['now']=[]

    sWhere = "where company_id=" + cid + " and (dt between '" + dt1 + "' and '" + dt2 + "')"

    if cid == ancestor_id:
        data['filter'] = True
        sWhere = "WHERE (dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01') " + \
                 "AND ancestor_id=" + str(cid) + "  and vtype_id=1 "
        if company_id:
            # 经销商筛选 经销商入库与盘库
            s = "SELECT a.dd,concat ( COALESCE (C.vv ,0)),COALESCE ( d.cc, '0' ) remain," + \
                "concat ( (  COALESCE (C.vv ,'0')- COALESCE ( d.cc, '0' ) ) ) sell," + \
                "concat (round( ( C.vv - COALESCE ( d.cc, '0' ) ) / ( C.vv ) * 100, 2 ) || '' ) " + \
                "FROM( SELECT to_char( dt, 'YYYY-MM' ) AS dd " + \
                "FROM logistics.inventory_stkclosingperiod A " + \
                "WHERE ( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) " + \
                "GROUP BY dd )a left outer join 	(" + \
                "SELECT to_char( dt, 'YYYY-MM' ) AS d, SUM ( ( SELECT COUNT ( * ) FROM " \
                "logistics.inventory_stkdetails WHERE batch_id = A.ID ) ) AS vv FROM logistics.inventory_batch A " + \
                "WHERE( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) 	AND company_id = " + str(company_id) + \
                " AND vtype_id = 1  " + \
                "GROUP BY d )C on c.d=a.dd LEFT OUTER JOIN (" + \
                "SELECT( SELECT to_char( dt, 'YYYY-MM' ) AS dd FROM logistics.inventory_stkclosingperiod WHERE ID = A.stkperiod_id )," + \
                "COUNT ( * ) AS cc  FROM logistics.inventory_stkclosingstkdetails A " + \
                "WHERE company_id = " + str(company_id) + "  GROUP BY stkperiod_id ) d ON d.dd = a.dd order by a.dd"

        elif sdiv_id:
            # 战区筛选 战区内经销商入库与盘库
            s = "SELECT a.dd,concat ( COALESCE (C.vv ,0)),COALESCE ( d.cc, '0' ) remain," + \
                "concat ( (  COALESCE (C.vv ,'0')- COALESCE ( d.cc, '0' ) ) ) sell," + \
                "concat (round( ( C.vv - COALESCE ( d.cc, '0' ) ) / ( C.vv ) * 100, 2 ) || '' ) " + \
                "FROM( SELECT to_char( dt, 'YYYY-MM' ) AS dd " + \
                "FROM logistics.inventory_stkclosingperiod A " + \
                "WHERE ( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) " + \
                "GROUP BY dd )a left outer join 	(" + \
                "SELECT to_char( dt, 'YYYY-MM' ) AS d, SUM ( ( SELECT COUNT ( * ) FROM " \
                "logistics.inventory_stkdetails WHERE batch_id = A.ID ) ) AS vv FROM logistics.inventory_batch A " + \
                "WHERE( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) 	AND company_id in "+\
                "(select id from company_company where division_id =" + str(sdiv_id) + "  ) AND vtype_id = 1  " + \
                "GROUP BY d )C on c.d=a.dd LEFT OUTER JOIN (" + \
                "SELECT( SELECT to_char( dt, 'YYYY-MM' ) AS dd FROM logistics.inventory_stkclosingperiod WHERE ID = A.stkperiod_id )," + \
                "COUNT ( * ) AS cc  FROM logistics.inventory_stkclosingstkdetails A " + \
                "WHERE company_id in (select id from company_company where division_id =" + str(sdiv_id) + "  )   GROUP BY stkperiod_id ) d ON d.dd = a.dd order by a.dd"
        else:
            s="SELECT a.dd,concat ( COALESCE (C.vv ,0)),COALESCE ( d.cc, '0' ) remain,"+\
                    "concat ( (  COALESCE (C.vv ,'0')- COALESCE ( d.cc, '0' ) ) ) sell,"+\
                    "concat (round( ( C.vv - COALESCE ( d.cc, '0' ) ) / ( C.vv ) * 100, 2 ) || '' ) "+\
                    "FROM( SELECT to_char( dt, 'YYYY-MM' ) AS dd "+\
                "FROM logistics.inventory_stkclosingperiod A "+\
                "WHERE ( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) "+\
                "GROUP BY dd )a left outer join 	("+\
                "SELECT to_char( dt, 'YYYY-MM' ) AS d, SUM ( ( SELECT COUNT ( * ) FROM " \
                "logistics.inventory_stkdetails WHERE batch_id = A.ID ) ) AS vv FROM logistics.inventory_batch A "+\
                "WHERE( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) 	AND company_id ="+str(cid)+"  AND vtype_id = 2  "+\
                "GROUP BY d )C on c.d=a.dd LEFT OUTER JOIN ("+\
                "SELECT( SELECT to_char( dt, 'YYYY-MM' ) AS dd FROM logistics.inventory_stkclosingperiod WHERE ID = A.stkperiod_id ),"+\
                    "COUNT ( * ) AS cc  FROM logistics.inventory_stkclosingstkdetails A "+\
                "WHERE ancestor_id = "+str(cid)+" GROUP BY stkperiod_id ) d ON d.dd = a.dd order by a.dd"
    else:
        s = "SELECT a.dd,concat ( COALESCE (C.vv ,0)),COALESCE ( d.cc, '0' ) remain," + \
            "concat ( (  COALESCE (C.vv ,'0')- COALESCE ( d.cc, '0' ) ) ) sell," + \
            "concat (round( ( C.vv - COALESCE ( d.cc, '0' ) ) / ( C.vv ) * 100, 2 ) || '' ) " + \
            "FROM( SELECT to_char( dt, 'YYYY-MM' ) AS dd " + \
            "FROM logistics.inventory_stkclosingperiod A " + \
            "WHERE ( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) " + \
            "GROUP BY dd )a left outer join 	(" + \
            "SELECT to_char( dt, 'YYYY-MM' ) AS d, SUM ( ( SELECT COUNT ( * ) FROM " \
            "logistics.inventory_stkdetails WHERE batch_id = A.ID ) ) AS vv FROM logistics.inventory_batch A " + \
            "WHERE( dt BETWEEN '" + str(dt1) + "-01' AND '" + str(dt2) + "-01' ) 	AND company_id =" + str(
            cid) + "  AND vtype_id = 2  " + \
            "GROUP BY d )C on c.d=a.dd LEFT OUTER JOIN (" + \
            "SELECT( SELECT to_char( dt, 'YYYY-MM' ) AS dd FROM logistics.inventory_stkclosingperiod WHERE ID = A.stkperiod_id )," + \
            "COUNT ( * ) AS cc  FROM logistics.inventory_stkclosingstkdetails A " + \
            "WHERE company_id = " + str(cid) + " GROUP BY stkperiod_id ) d ON d.dd = a.dd order by a.dd"
    cur.execute(s)
    r = cur.fetchall()
    for i in range(0,len(r)):
        if r[i][0] >= dt11:
            if r[i-12][2] != 0:
                re = (r[i][2]-r[i-12][2])/r[i-12][2]*100
            else:
                re= 0
            if int(r[i-12][3]) != 0:
                se = (int(r[i][3])-int(r[i-12][3]))/int(r[i-12][3])*100
            else:
                se = 0
            se = round(se, 2)
            re = round(re, 2)
            data['quantitys']['list_category'].append((r[i][0]))
            data['quantitys']['kucun_data'].append(re)
            data['quantitys']['sell_data'].append(se)

    return render(request, 'sales/sales_table/inventory_in.html', data)



#2021-02-22 销售启单 诗仙太白
@login_required
def sales_ticket(request,id=None):
    u=request.user
    c=u.company
    is_saved = False
    if id:
        obj=Tickets.objects.get(id=int(id))
    else:
        obj=Tickets(company_id=c.id,ancestor_id=c.ancestor_id,user_id=u.id)
    if request.method == 'GET':  
        form=TicketForm(instance=obj)
    else:  
        form = TicketForm(request.POST,instance=obj)        
        if form.is_valid():
            form.save()
            is_saved = True        
    return render(request,'obj/inventory_ticket.html',{'form':form,'is_saved':is_saved})


@login_required
def print_ticket(request):
    tickets=[]  
    cur=connection.cursor()
    r = json.loads(request.body)    
    ids=','.join(r['ids'])
    tm = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    s="select a.dt,coalesce(a.order_no,''),coalesce(s.name,''),c.name,p.name,a.qty,a.id from "+\
        "(select id,to_char(dt,'yyyy-mm-dd') dt,order_no,product_id,agent_id,store_id,qty,user_id "+\
            "from inventory_tickets where id in ("+ids+")) a "+\
        "left outer join "+\
        "(select id,name from company_company ) c "+\
        "on a.agent_id=c.id "+\
        "left outer join "+\
        "(select id,name from product_product) p "+\
        "on a.product_id=p.id "+\
        "left outer join "+\
        "(select id,name from inventory_storehouse) s "+\
        "on a.store_id=s.id "
    cur.execute(s)
    for r in cur.fetchall():
        tickets.append({'date':r[0],'order_no':r[1],'store':r[2],'agent':r[3],'product':r[4],'qty':r[5],'id':r[6]})     
    cur.close()
    html=render(request,'inventory/print_inventorytickets.html',{'tickets':tickets,'time':tm})    
    return HttpResponse(html)





#入库启票
@login_required
def yg_ticket(request):
    data={'data':[],'clmns':[],'e':[],'subtt':[],'murl':'','dt':False,'add':True}
    u=request.user
    c=u.company
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('date_from', dt)
    dt_to = request.GET.get('date_to', dt)
    data['clmns'] = ["生成时间","启票代码","批次","批号","酒原产地","生产组装地", "生产时间",
                     "检验时间", "打印"]
    if c.level_id == 1 and u.has_perm('company.sys_admin'):
        show_add = True
    data['murl'] = '/inventory/ticketinfo/conf/'
    cur = connection.cursor()
    sDt = " and (dt between '" + dt_fr + "' and '" + dt_to + "')"
    s= "select id,to_char(tm,'yyyy-mm-dd HH24:MI:SS') tm,coalesce(origin,''),"+\
       "coalesce(assembly,''), first_tm,"+\
       " check_tm,coalesce(pici,''),coalesce(pihao,''),coalesce(code,'') from  inventory_inboundtickets where company_id=" + str(c.id) + sDt

    cur.execute(s)
    for r in cur.fetchall():
        data['data'].append([
            '<a href="/inventory/ticketinfo/conf/' + str(r[0]) + '/">' + r[1] + '</a>',
            r[8],r[6],r[7],r[2], r[3], r[4], r[5],
            '<input type="checkbox" id="cb-' + str(r[0]) + '" tk_id="' + str(r[0]) + '" /><label for="cb-' + str(
                r[0]) + '">打印</label>'
        ])
    data['show_add'] = show_add
    data['date_from'] = dt_fr
    data['date_to'] = dt_to
    
    return render(request, 'inventory/yugong_info.html', data)

@login_required
def yg_ticket_conf(request,id=None):
    u=request.user
    c=u.company
    is_saved = False
    if id:
        obj=InboundTickets.objects.get(id=int(id))
    else:
        obj=InboundTickets(company_id=c.id,ancestor_id=c.ancestor_id)
    if request.method == 'GET':
        form=InboundTicketsForm(instance=obj)
    else:
        form = InboundTicketsForm(request.POST,instance=obj)
        if form.is_valid():
            form.save()
            is_saved = True
    return render(request, 'inventory/yg_inbound_ticket.html', {'form':form, 'is_saved':is_saved})


@login_required
def yg_print_ticket(request):
    tickets=[]
    cur=connection.cursor()
    r = json.loads(request.body)
    ids=','.join(r['ids'])
    tm = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    s = "select to_char(tm,'yyyy-mm-dd HH24:MI:SS') tm,pihao,"+\
        "origin,first_tm,assembly," + \
        " check_tm,id,check_user,pici,"+\
        "(select name from product_product where id = product_id ) from "+\
        " inventory_inboundtickets  where id in ("+ids+")"
    cur.execute(s)
    for r in cur.fetchall():
        tickets.append({'date':r[0],'pihao':r[1],'origin':r[2],'first_tm':r[3],'assembly':r[4],
                        'check_tm':r[5],'id':r[6],'check_user':r[7],'pici':r[8],'product_name':r[9]})
    cur.close()
    html=render(request, 'inventory/print_inboundtickets.html', {'tickets':tickets, 'time':tm})
    return HttpResponse(html)





#2021-03-31
def stack_inbound_codes_sql(batch,stacks):
    insert_sql=[]
    for s in stacks:   
        code=s['code'] 
        stks=Stack.objects.filter(code=code)  
        if stks:            
            stack=stks[0]
        else:
            stack=Stack(company_id=batch.company_id,code=code)          
        stack.product_id=batch.product_id
        stack.store_id=batch.store_fr_id       
        if 'location' in s:
            stack.location=s['location']
        if 'qty_lmt' in s:
            stack.qty_lmt=s['qty_lmt']
        if 'is_fixed' in s:
            stack.is_fixed=s['is_fixed']           
        stack.save()        
        if stack.code_is_permanent==False:
            # 2022-07-02 如诗仙太白含垛标套标，已事先将对应箱标写入stackdetails，入库时只扫垛标,不会上传垛标下面绑定的箱标
            s['labels']=[]
            for d in stack.stackdetails_stack.all():
                s['labels'].append(d.label_code)
        if batch.product_id:
            product_id=str(batch.product_id)
        else:
            product_id='null'
        for l in s['labels']:               
            insert_sql.append("('"+l+"','"+l[:4]+"',"+product_id+","+str(stack.id)+")")        

        """
        stks=Stack.objects.filter(code=code)                    
        #if stacks:
        #    stack=stacks[0]
        #else:
        #    stack=Stack(company_id=batch.company_id,code=code)  

        # 2022-06-28 垛标要事先写入inventory_stack，并区分永久性还是一次性垛标码
        if stacks:
            stack=stacks[0]
            if stack.code_is_permanent:
                stack.product_id=batch.product_id
                stack.store_id=batch.store_fr_id       
                if 'location' in s:
                    stack.location=s['location']
                if 'qty_lmt' in s:
                    stack.qty_lmt=s['qty_lmt']
                if 'is_fixed' in s:
                    stack.is_fixed=s['is_fixed']           
                stack.save()      
        if batch.product_id:
            product_id=str(batch.product_id)
        else:
            product_id='null'
        for l in s['labels']:            
            #sSql="insert into codes(label_code,   tb,               product_id,   stack_id) values "+",".join(aSql)
            insert_sql.append("('"+l+"','"+l[:4]+"',"+product_id+","+str(stack.id)+")")
        """

    return insert_sql


#2021-03-23 标签查询:分步
#def get_lable_pk_id(code):
#    s="select id,is_pk,package_id,parent_id from "



@login_required
def online_action(request,action):
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('dt_fr', dt)
    dt_to = request.GET.get('dt_to', dt)
    dt_max = max(dt_fr, dt_to)
    dt_min = min(dt_fr, dt_to)
    dt_fr = dt_min
    dt_to = dt_max    
    c=request.user.company
    cid=str(c.id)
    uid=str(request.user.id)
    cur=connection.cursor()
    if action=='list_binding':
        data={'e':'','data':[],'clmns':[],'dt_fr': dt_fr, 'dt_to': dt_to}
        data['clmns']=[_('日期'),_('产品名称'),_('仓库名称'),_('生产批次'),_('质检员'),_('完整绑定'),_('不完整绑定'),_('已入库数量')]
        '''
        s="select to_char(o.dt,'yyyy-mm-dd'),o.product_id,o.store_id,o.batch_no,right(o.batch_no,1),o.cnt_ok,o.cnt_err,i.qty_boxes,"+\
            "p.product_name,(select name from inventory_storehouse where id=o.store_id) from "+\
            "(select dt,product_id,store_id,batch_no,sum(cnt_ok) cnt_ok,sum(cnt_err) cnt_err "+\
                "from "+\
                "(select dt,box_code,1 cnt_ok,0 cnt_err,product_id,store_id,batch_no from z_bottlecap_binding "+\
                    "where company_id="+cid+" and dt between '"+dt_fr+"' and '"+dt_to+"' "\
                    "group by dt,box_code,product_id,store_id,batch_no having count(*)=max(bottles_cnt) "+\
                "union all "+\
                "select dt,box_code,0 cnt_err,1 cnt_err,product_id,store_id,batch_no from z_bottlecap_binding "+\
                    "where company_id="+cid+" and dt between '"+dt_fr+"' and '"+dt_to+"' "\
                    "group by dt,box_code,product_id,store_id,batch_no having count(*)<>max(bottles_cnt)"+\
                ") a "+\
                "group by dt,product_id,store_id,batch_no "+\
            ") o "+\
            "left outer join "+\
            "(select id,product_id,product_name from z_bottle_cap_product) p "+\
            "on o.product_id=p.id "+\
            "left outer join "+\
            "(SELECT period,product_id,store_id,batch_no,dt,tm,user_id,remark,qty_boxes FROM z_bottlecap_inbound "+\
                "where company_id="+cid+" and period between '"+dt_fr+"' and '"+dt_to+"'"+\
            ") i "+\
            "on o.dt=i.dt and o.product_id=i.product_id and o.store_id=i.store_id and o.batch_no=i.batch_no"
        '''
        s="select to_char(o.dt,'yyyy-mm-dd'),o.product_id,o.store_id,o.batch_no,right(o.batch_no,1),o.cnt_ok,o.cnt_err,coalesce(o.inbound,0),"+\
            "coalesce(p.product_name,''),coalesce((select name from inventory_storehouse where id=o.store_id),'') from "+\
            "(select dt,product_id,store_id,batch_no,sum(cnt_ok) cnt_ok,sum(cnt_err) cnt_err,sum(inbound) inbound "+\
                "from "+\
                "(select dt,product_id,store_id,batch_no,"+\
                    "case when bnd=cnt then 1 else 0 end cnt_ok,case when bnd<>cnt then 1 else 0 end cnt_err,"+\
                    "case when (select max(id) from inventory_stkdetails where company_id="+cid+" and vtype_id=1 and is_delete=false and label_pk_id=a.label_pk_id) "+\
                        "is null then 0 else 1 end inbound "+\
                    "from "+\
                    "(select dt,label_pk_id,product_id,store_id,batch_no,count(*) bnd,max(bottles_cnt) cnt from z_bottlecap_binding "+\
                        "where company_id="+cid+" and dt between '"+dt_fr+"' and '"+dt_to+"' group by dt,label_pk_id,product_id,store_id,batch_no"+\
                    ") a"+\
                ") b "+\
                "group by dt,product_id,store_id,batch_no "+\
            ") o "+\
            "left outer join "+\
            "(select id,product_id,product_name from z_bottle_cap_product) p "+\
            "on o.product_id=p.id"
        
        #2021-11-15 同一生产批次，可能有不同质检员 
        s="select to_char(o.dt,'yyyy-mm-dd'),o.product_id,o.store_id,o.batch_no,coalesce(o.qc,right(o.batch_no,1)),o.cnt_ok,o.cnt_err,coalesce(o.inbound,0),"+\
            "coalesce(p.product_name,''),coalesce((select name from inventory_storehouse where id=o.store_id),''),to_char(tm,'yyyy-mm-dd HH24:MI:SS') from "+\
            "(select dt,product_id,store_id,batch_no,sum(cnt_ok) cnt_ok,sum(cnt_err) cnt_err,sum(inbound) inbound,qc,min(tm) tm "+\
                "from "+\
                "(select a.dt,product_id,store_id,batch_no,qc, tm,"+\
                    "case when bnd=cnt then 1 else 0 end cnt_ok,case when bnd<>cnt then 1 else 0 end cnt_err,"+\
                    "case when (select max(id) from inventory_stkdetails where company_id="+cid+" and vtype_id=1 and is_delete=false and label_pk_id=a.label_pk_id) "+\
                        "is null then 0 else 1 end inbound "+\
                    "from "+\
                    "(select dt,label_pk_id,product_id,store_id,batch_no,qc,count(*) bnd,max(bottles_cnt) cnt,min(tm) tm from z_bottlecap_binding "+\
                        "where company_id="+cid+" and dt between '"+dt_fr+"' and '"+dt_to+"' group by dt,label_pk_id,product_id,store_id,batch_no,qc"+\
                    ") a"+\
                ") b "+\
                "group by dt,product_id,store_id,batch_no,qc "+\
            ") o "+\
            "left outer join "+\
            "(select id,product_id,product_name from z_bottle_cap_product) p "+\
            "on o.product_id=p.id"

        cur.execute(s)
        j=0
        for r in cur.fetchall():
            sStore=''
            sQc=''
            name_store=''
            name_product=''
            if r[0]:
                name_product="&product_name="+r[8]
            if r[8]:
                sStore='&store_id='+str(r[2])
                name_store='&store_name='+r[9]
            if r[4]:
                sQc='&qc='+r[4]
            url='/inventory/online/list_boxes/?dt_fr='+dt_fr+'&dt_to='+dt_to+'&product_id='+str(r[1])+\
                '&batch_no='+r[3]+sQc+sStore+name_product+name_store
            url_err='/inventory/online/list_boxes_error/?dt_fr='+dt_fr+'&dt_to='+dt_to+'&product_id='+str(r[1])+\
                '&batch_no='+r[3]+sQc+sStore+name_product+name_store
            if r[6]:
                a_e='<a href="'+url_err+'">'+str(r[6])+'</a>'
            else:
                a_e=''           
            q=str(r[7])
            if r[7]<r[5]:
                q=q+'<span class="pull-right"span> <input type="checkbox" id="cb-'+str(j)+'" /><label for="cb-'+str(j)+'">入库</label></span>'
            data['data'].append([
                '<span dt="'+r[0]+'" tm="'+r[10]+'" >'+r[0]+'</span>',
                '<a href="'+url+'" product_id="'+str(r[1])+'">'+r[8]+'</a>',
                '<span store_id="'+str(r[2])+'">'+r[9]+'</span>',
                '<span batch_no="'+r[3]+'">'+r[3]+'</span>',
                '<span qc="'+r[4]+'">'+r[4]+'</span>',
                r[5],
                a_e,
                q
            ])
            j=j+1
        return render(request,'inventory/stock/online_binding_inbound_list.html',data)
        
    elif action=='list_boxes':
        data={'e':'','data':[],'clmns':[],'dt_fr': dt_fr, 'dt_to': dt_to}
        data['clmns']=[_('箱标'),_('产线'),_('开始时间'),_('结束时间'),_('绑定'),_('入库时间')]
        dt_fr=request.GET.get('dt_fr',dt_fr)
        dt_to=request.GET.get('dt_fr',dt_to)
        pid=request.GET.get('product_id','null')
        sid=request.GET.get('store_id','null')
        bid=request.GET.get('batch_no','null')        
        qc =request.GET.get('qc','null')
        data['store_name']  =request.GET.get('store_name','')
        data['product_name']=request.GET.get('product_name','')      
        data['batch_no']=request.GET.get('batch_no','')
        data['qc']=request.GET.get('qc','')
        andPid=" and product_id="+pid
        if sid=='null':
            andSid=""
        else:
            andSid=" and store_id="+sid 
        if qc=='null':
            andQc=""
        else:
            andQc=" and qc='"+qc+"'"        
        if bid=='null':
            andBid=""
        else:
            andBid=" and batch_no='"+bid+"'"                   
        s="select a.box_code,a.prd_line,a.cnt||'/'||a.cnt_bottles,"+\
            "to_char(a.tm_min,'yy-mm-dd HH24:MI:SS'),to_char(a.tm_max,'yy-mm-dd HH24:MI:SS'),"+\
            "coalesce((select to_char(tm,'yy-mm-dd HH24:MI:SS') from inventory_stkdetails where company_id="+cid+" "\
                "and label_pk_id=a.label_pk_id "+\
                 "and vtype_id=1 and is_delete=false limit 1),'') "+\
            "from "+\
            "(select 'ok' cat,box_code,label_pk_id,prd_line,max(bottles_cnt) cnt_bottles,count(*) cnt,"+\
                "product_id,store_id,qc,batch_no,min(tm) tm_min,max(tm) tm_max "+\
                "from z_bottlecap_binding where company_id="+cid+" "+\
                "and (dt between '"+dt_fr+"' and '"+dt_to+"')"+andPid+andSid+andBid+andQc+" "+\
                "group by box_code,label_pk_id,prd_line,product_id,store_id,qc,batch_no having count(*)=max(bottles_cnt) "+\
                "union all "+\
                "select 'err' cat,box_code,label_pk_id,prd_line,max(bottles_cnt) cnt_bottles,count(*) cnt,"+\
                "product_id,store_id,qc,batch_no,min(tm) tm_min,max(tm) tm_max "+\
                "from z_bottlecap_binding where company_id="+cid+" "+\
                "and (dt between '"+dt_fr+"' and '"+dt_to+"')"+andPid+andSid+andBid+andQc+" "+\
                "group by box_code,label_pk_id,prd_line,product_id,store_id,qc,batch_no having count(*)<>max(bottles_cnt)"+\
            ") a "+\
            "left outer join "+\
            "(select id,product_id,product_name from z_bottle_cap_product) p "+\
            "on a.product_id=p.id"     
        cur.execute(s)
        for r in cur.fetchall():
            data['data'].append([ r[0],r[1],r[3],r[4],r[2],r[5] ])
        return render(request,'inventory/stock/online_binding_boxes_list.html',data)
    elif action=='list_boxes_error':
        data={'e':'','data':[],'clmns':[],'dt_fr': dt_fr, 'dt_to': dt_to}       
        data['clmns']=[_('产品名称'),_('产线'),_('箱标'),_('盒标'),_('瓶盖码'),_('绑定时间')]
        dt_fr=request.GET.get('dt_fr',dt_fr)
        dt_to=request.GET.get('dt_fr',dt_to)
        pid=request.GET.get('product_id','null')
        sid=request.GET.get('store_id','null')
        bid=request.GET.get('batch_no','null')        
        qc =request.GET.get('qc','null')
        data['store_name']  =request.GET.get('store_name','')
        data['product_name']=request.GET.get('product_name','')      
        data['batch_no']=request.GET.get('batch_no','')
        data['qc']=request.GET.get('qc','')
        andPid=" and product_id="+pid
        if sid=='null':
            andSid=""
        else:
            andSid=" and store_id="+sid 
        if qc=='null':
            andQc=""
        else:
            andQc=" and qc='"+qc+"'"        
        if bid=='null':
            andBid=""
        else:
            andBid=" and batch_no='"+bid+"'"                   
        s="select product,prd_line,box_code,bottle,label,"+\
            "to_char(tm,'yyyy-mm-dd HH24:MI:SS') "+\
            "from z_bottlecap_binding where company_id="+cid+" "+\
            "and (dt between '"+dt_fr+"' and '"+dt_to+"')"+andPid+andSid+andBid+andQc+\
            " and label_pk_id in ("+\
                "select label_pk_id from z_bottlecap_binding where company_id="+cid+" "+\
                    "and (dt between '"+dt_fr+"' and '"+dt_to+"')"+\
                    "group by label_pk_id having count(*)<>max(bottles_cnt)"+\
                ") "+\
            "order by box_code,bottle"
        cur.execute(s)
        for r in cur.fetchall():
            data['data'].append([ r[0],r[1],r[2],r[3],r[4],r[5] ])
        return render(request,'inventory/stock/online_binding_boxes_list_error.html',data)
    elif action=='inbound':
        data={'e':''}
        d = json.loads(request.body)
        dt_fr=d['dt_fr']
        dt_to=d['dt_to']
        i=1
        cnt=0
        for r in d['details']:   
            product_id=r['product_id']
            cur.execute("select product_id from z_bottle_cap_product where id="+str(product_id))
            rr=cur.fetchone()
            pid=None
            if rr:
                pid=rr[0]    
            store_id=r['store_id']
            period=r['period']
            bn=r['batch_no']
            #2021-11-15 同一生产批次，可能有不同质检员 

            qc=r['qc']
            dt=r['dt']
            tm=r['tm']            
            if not qc:
                qc=bn[-1:]

          
            
            b=Batch(company_id=c.id,company_fr_id=c.id,level_id=c.level_id,hierarchy_id=c.hierarchy_id,version=c.version,user_id=int(uid),ancestor_id=c.ancestor_id,vtype_id=1,code=bn)               
            
            
          

            b.batch_no="RK-"+period.replace('-','')+str(i).zfill(3)
            b.store_fr_id=store_id
            b.product_id=pid
            b.qc_name=qc
            

            b.save()
            b.dt=dt
            b.tm=tm
            b.save()

            s="insert into logistics.inventory_batchdetails(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id,ancestor_id,product_id,dt,tm) "+\
                "select "+str(b.id)+",box_code,label_pk_id,3,label_pk_id,"+cid+","+cid+","+\
                    "(select product_id from z_bottle_cap_product where id="+str(product_id)+"),dt,tm from "+\
                "(select box_code,label_pk_id,max(dt) dt,max(tm) tm from z_bottlecap_binding where  company_id="+cid+" and product_id="+str(product_id)+" "+\
                    "and store_id="+str(store_id)+" and label_pk_id>0 and dt='"+period+"' and batch_no='"+bn+"' and qc='"+qc+"' "+\
                    "group by box_code,label_pk_id"+\
                ") i"            
            cur.execute(s)
            bDuplication_inboud=False
            cfgs=CompanyCfg.objects.filter(company_id=c.ancestor_id) 
            if cfgs:
                cfg=cfgs[0]
                if c.level_id==1:
                    if cfg.duplication_inbound_company:            
                        bDuplication_inboud=True
                else:
                    if cfg.duplication_inbound_agent:            
                        bDuplication_inboud=True                        
            if not bDuplication_inboud:   
                #扫了同一个箱码,一箱上的两个箱码，或箱上的A标和B标
                s="update logistics.inventory_batchdetails b set err='此箱已于'||("+\
                        "select to_char(tm,'yyyy-mm-dd HH24:MI:SS') from logistics.inventory_stkdetails where "+\
                        "vtype_id=1 and company_id="+str(c.id)+" and label_pk_id=b.label_pk_id order by id desc limit 1)"+\
                    " where batch_id="+str(b.id)+" and err is null "\
                    " and (select tm from logistics.inventory_stkdetails where "+\
                        "vtype_id=1 and company_id="+str(c.id)+\
                        " and label_pk_id=b.label_pk_id and is_delete=false limit 1) is not null "
                cur.execute(s)           
            s="insert into logistics.inventory_stkdetails(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id,product_id,vtype_id,store_id,store_fr_id,ancestor_id,dt,tm) "+\
                "select "+str(b.id)+",label_code,label_id,label_pkg,label_pk_id,company_id,product_id,1,"+str(store_id)+","+str(store_id)+","+cid+",dt,tm "+\
                "from inventory_batchdetails where batch_id="+str(b.id)+" and err is null"
            cur.execute(s)
            qty=cur.rowcount
            cnt=cnt+qty
            s="INSERT INTO z_bottlecap_inbound(period,product_id,store_id,batch_no,user_id,company_id,qty_boxes) VALUES "+\
                "('"+period+"',"+str(product_id)+","+str(store_id)+",'"+bn+"',"+uid+","+cid+","+str(qty)+")"            
            cur.execute(s)
            i=i+1
        return redirect('/inventory/online/list_binding/?dt_fr='+dt_fr+'&dt_to='+dt_to) 
    return JsonResponse(data)

     







"""
#2022-06-17
class LabelQuery():
    def __init__(self,company_id,code,conn=None):
        if not conn:
            conn=connection
        self.code=code    
        self.tb_cross=''    #卷标跨段表名
        self.company_id=int(company_id)
        self.connection=conn 
        self.package={}        
        self.infor={
            'code':code,                #查询的106301364235
            'label_a':'',               #A标号码
            'label_b':'',               #B标号码
            'label_pk_id':0,            #主箱标ID

            #2022-02-23
            'label_id':0,               #标签ID

            'label_pk_code':'',         #主箱标号码
            'ab_bindding':False,        #是否为AB标 
            'has_nfc':False,            #是否有NFC标签
            'is_thirdparty':False,      #是否为第三方标签
            'ab_data':1,                #AB标基础数据表 0:单枚标 无基础数据 1:code_a 2:code_b
            'is_active':False,          #标签是否已激活（系统内是否有物流记录）
            'is_bottlecap':False,       #是否为瓶盖码
            'bottlecap':'',             #瓶盖码
            'wl':'',                    #系统内物流编码

            #2022-04-25 后补主箱标IDS 
            #如诗仙太白：159箱，箱-箱（跨段）绑定，1托3 +1托6 =9瓶/箱
            'sup_pk_id':{},
            
            #2022-06-14  标签库新建的schema,用以保存企业跨段后绑定的主箱标及子标所有号段
            'carton':'',
            # 2022-06-257;"垛标";"用于扫垛标发货/入库"
            'stack':{}
        } 
        #取主箱标ID，包装，是否已激活          
        self.infor['label_pk_id']=self.get_label_pk()     
        
    def get_label_pk(self):
        label_pk_id=None
        company_id=self.company_id
        company=Company.objects.get(id=int(company_id))
        aid=company.ancestor_id
        code=self.code    
        cur=self.connection.cursor()

        sPkg='package_id'   #一般情况下，标签类别取标签基础表的 package_id 字段
        #2021-05-06 瓶盖码
        if not code.isdigit():  
            #2022-03-14 酒鬼小圆标也有替换
            s="select code0,code from label.lbl_replace_details where code='"+code+"' order by id desc limit 1"
            cur.execute(s)
            r=cur.fetchone()
            if r:
                code=r[0]     
            d_code=decrypt_11h(code)
            if not d_code:               
                return None
            else:
                self.infor['is_bottlecap']=True
                self.infor['bottlecap']=code
                self.infor['code']=d_code
                sPkg='100 package_id'  #瓶盖码标签类别id为100                
                cur.execute("select bottle from label.bottlecap where  label='"+code+"' "+\
                    " union all "+\
                    "select bottle from z_bottlecap_binding where  label='"+code+"' "
                )
                r=cur.fetchone()
                if r:
                    code=r[0]                    
                else:
                    #2021-09-13 是否为小圆标活动码
                    code=d_code  
                #2021-11-29
                self.code=code   
        #2022-04-27 可能查询的是瓶盖码解密后的数据
        else:             
            cur.execute("select bottle from label.bottlecap where code='"+code+"' "+\
                " union all "+\
                "select bottle from z_bottlecap_binding where code='"+code+"' "
            )
            r=cur.fetchone()
            if r:
                self.infor['code']=code
                self.infor['bottlecap']=code
                code=r[0]   
                sPkg='100 package_id'  #瓶盖码标签类别id为100 

        if company.ancestor_id in (1,1644) and code[:1]=='4':
            r = requests.request('GET', 'http://www.china315net.com:35088/jg/fw_wl/'+code+'/')
            d = json.loads(r.text) 
            if d['wl']:
                code=d['wl']   
                self.infor['wl']=code                
            else:       
                #cur.close()
                #return None 2022-03-15 酒鬼有4开头的物流码 如早期 54°500ml简优  
                pass
        #是否为AB表 A标为物流码，B标用于显示（肉眼可见，12位数字）
        cur.execute("select coalesce(code_a,''),coalesce(code_b,''),id FROM label.lbl_abcode where code_a='"+code+"' or code_b='"+code+"'")
        r=cur.fetchone()
        if r:            
            code=r[0] 
            self.infor['ab_bindding']=True
            self.infor['label_a']=r[0]
            self.infor['label_b']=r[1]
            #2021-07-14 正常情况，查A标（物流标） code_a 数据表            
            self.code=code
            #2022-04-25 诗仙太白 code_a,跨段 箱-箱 159箱
            if r[1][:4]=='1045' or r[0][:4]=='1045':
                s="select code from label.t1045 where package_id=3 and left(code,4)='1044' and parent_id="+\
                    "(select id from label.t1045 where code='"+code+"')"  
                cur.execute(s)
                rrr=cur.fetchone()
                if rrr:     
                    s="select id from label.t9073 where code="+\
                        "(select code_a from label.lbl_abcode where code_b='"+rrr[0]+"')"                    
                    cur.execute(s)
                    rrr=cur.fetchone()
                    if rrr:
                        self.infor['sup_pk_id']={'id':rrr[0],'tb':'label.t9073'}           
        s="select code0,code,dt from label.lbl_replace_details where code='" + code +"' order by id desc limit 1"    
        cur.execute(s)   
        rr=cur.fetchone()    
        if rr:
            code=rr[0] 
        if not self.infor['wl']:    
            self.infor['wl']=code
        t="label.t" +code[:4]    

        #2022-06-24 是否在酒鬼跨段表
        cur.execute("select coalesce(parent_id,id),"+\
            "(select code from label.lbl_binding_jg where id=coalesce(j.parent_id,j.id)),"+\
            "package_id,(select name from label.lbl_package where id=package_id) "+\
            "from label.lbl_binding_jg j where code='"+code+"'")
        rrr=cur.fetchone()
        if rrr:    
            t='label.lbl_binding_jg'
            self.tb_cross=t
            self.infor['label_pk_code']=rrr[1]
            self.package={'id':rrr[2],'name':rrr[3]}
            return rrr[0]

        #2022-06-24 是否是垛标
        s="SELECT id,code,parent_id,location,qty_lmt,is_fixed,store_id,product_id,remark,code_is_permanent "+\
            "from inventory_stack where code='"+code+"' and is_delete=false"  
        cur.execute(s)
        rrr=cur.fetchone()
        if rrr:
            is_permanent=True
            self.package={'id':7,'name':'垛标'}     
            if rrr[2]:
                label_pk_id=rrr[2]
                cur.execute("select code,code_is_permanent from inventory_stack where id="+str(rrr[2]))
                r3=cur.fetchone()
                if r3:
                    sc=r3[0]
                    is_permanent=r3[1]
                else:
                    sc=''
            else:
                label_pk_id=rrr[0]
                sc=rrr[1]
                is_permanent=rrr[9]
            
            self.infor['stack']['id']=label_pk_id
            self.infor['stack']['code']=sc    
            self.infor['stack']['is_permanent']=is_permanent
            self.infor['label_pk_code']=sc
            return label_pk_id

        #查询的物流基础表是否存在    
        cur.execute("select count(*) from information_schema.tables where table_schema='label' and table_type='BASE TABLE' and table_name='t"+code[:4]+"'")       
        rr=cur.fetchone()  
        if rr[0]==0:
            #表不存在
            if self.infor['ab_bindding']:
                #基础数据是否在code_b
                tb="t"+self.infor['label_b'][:4]
                cur.execute("select count(*) from information_schema.tables where table_schema='label' and table_type='BASE TABLE' and table_name='"+tb+"'")
                rrr=cur.fetchone()
                if rrr[0]:
                    t='label.t'+self.infor['label_b'][:4]
                    code=self.infor['label_b']
                else:
                    cur.close()
                    return None 
            else:      
                #是否为第三方标签                                  
                cur.execute("select id from label.thirdparty where code='"+code+"' and cid="+str(aid))
                rrr=cur.fetchone()
                if rrr:
                        self.infor['is_thirdparty'] = True
                        t="label.thirdparty"
                else:
                        cur.close()
                        return None   
        else:
            #表存在，标不在表里 （可能是第三方标签）
            cur.execute("select id from "+t+" where code='"+code+"'")
            rrr=cur.fetchone()
            if not rrr:            
                tb="label.thirdparty"                
                cur.execute("select id from "+tb+" where code='"+code+"' and cid="+str(aid))
                rrr=cur.fetchone()
                if rrr:
                    self.infor['is_thirdparty'] = True
                    t="label.thirdparty"
                else:
                    cur.close()
                    return None  

        s="select p.id,p.name,coalesce(p.remark,''),p.outermost,p.innermost,p.binding,"+\
            "coalesce((select parent_id from " +t+ " where id=l.parent_id),l.parent_id,l.id),"+\
            "l.id,l.parent_tb,l.package_id,l.parent_id  from "+\
            "(select id,"+sPkg+",parent_id,parent_tb from "+t+" where code='"+code+"') l "+\
            "left outer join "+\
            "(SELECT id,name,remark,outermost,innermost,binding FROM label.lbl_package) p "+\
            "on l.package_id=p.id"
        cur.execute(s)
        r = cur.fetchone()             
        
        #因为有跨段后绑定、再绑定，只能 逐级查找 目的：找到主箱标物流码ID和号码
        #有父级ID或本身ID
        if r[6]:
            #2022-06-14 标签是否为跨段后绑定,非主箱标
            if r[8]:
                #1;"瓶标";"套标，无子级";FALSE;TRUE;TRUE
                #2;"盒标";"套标，有父级和子级";FALSE;FALSE;TRUE
                #3;"箱标";"套标，无父级";TRUE;FALSE;TRUE
                #4;"单枚标";"独立箱标或独立瓶标";TRUE;TRUE;FALSE
                #5;"条盒";"烟标，条盒";TRUE;FALSE;FALSE
                #6;"小盒";"烟标，小盒";FALSE;TRUE;FALSE
                #11;"独立瓶标";"瓶标，但生号时没有套标关系";FALSE;TRUE;FALSE
                #12;"独立盒标";"盒标，但生号时没有套标关系";FALSE;FALSE;FALSE
                #13;"独立箱标";"箱标，但生号时没有套标关系";TRUE;FALSE;FALSE
                #20;"外包码";"按包发货，如众茶国际，1包100套";TRUE;FALSE;TRUE
                #100;"活动码";"瓶盖内码,用于促销活动";FALSE;TRUE;FALSE               

                #当前标签为副箱标，或盒标
                if r[9] in [2,3,12,13]:                    
                    self.infor['carton']=r[8]
                    label_pk_id=r[10]                        
                    self.infor['label_pk_id']=label_pk_id
                elif r[9] in [1,11]:
                    ct=r[8]
                    #查询的是瓶标 如果三级绑定，可能瓶盒在一个号段，箱在另一个号段                    
                    s="select parent_id,parent_tb,package_id,code,id from label.t"+r[8]+" where id="+str(r[10])
                    cur.execute(s)
                    r10=cur.fetchone()    
                    if r10:
                        if r10[2] in [3,13]:                            
                            label_pk_id=r10[4]             
                            self.infor['carton']=ct
                            if r10[1]:
                                self.infor['carton']=r10[1]
            else: 
                if self.infor['is_thirdparty']:
                    label_pk_id=r[6]
                else:                              
                    cur.execute("select parent_id,parent_tb,package_id,code,id from "+t+" where id="+str(r[6])) 
                    r10=cur.fetchone()
                    if r10:
                        if r10[2] in [3,13]:   
                            label_pk_id=r[6]  
                            #也可能查询的是主箱标,主箱标是否在 schema carton    
                            cur.execute("select count(*) from information_schema.tables where "\
                                "table_schema='carton' and table_type='BASE TABLE' and table_name='t"+r10[3][:4]+"'")
                            rr=cur.fetchone()  
                            if rr[0]>0:    
                                cur.execute("select id from carton.t"+code[:4]+" where code='"+r10[3]+"'")
                                rrr=cur.fetchone()
                                if rrr:
                                    self.infor['carton']=r10[3][:4]                        
                        #可能返回的是盒标
                        elif r10[0]: 
                            if r10[1]:
                                cur.execute("select parent_id,parent_tb,package_id,code from label.t"+r10[1]+" where id="+str(r10[0]))
                                r11=cur.fetchone()
                                if r11:
                                    label_pk_id=r11[0]
                                    if r11[1]:
                                        self.infor['carton']=r11[1]
            #2022-02-23
            self.infor['label_id']=r[7]   
            #2022-06-17 
            if not label_pk_id:
                label_pk_id=r[6]
        else:           
            return None 
        self.package={'id':r[0],'name':r[1],'remark':r[2],'outermost':r[3],'innermost':r[4],'is_biding':r[5]}          
        #2022-06-15 是否有写入carton schema
        if self.infor['carton']:
            t='label.t'+self.infor['carton']     
        cur.execute("select code from "+t+" where id="+str(label_pk_id))
        r=cur.fetchone()        
        
        #2022-05-20 小型企业，套标再绑定，箱瓶可能不在一个表
        if r:
            self.infor['label_pk_code']=r[0]
        else:
            s="select parent_id,parent_code,parent_tb "+\
                "from  label.lbl_rebinding_details where code='"+code+"'"
            cur.execute(s)
            rr=cur.fetchone()
            if rr:
                label_pk_id=rr[0]
                self.infor['label_pk_code']=rr[1]
                self.tb_cross=rr[2]
        cur.execute("select id from inventory_stkdetails where label_pk_id="+str(label_pk_id)+" limit 1")
        r=cur.fetchone()
        if r:
            self.infor['is_active']=True        
        cur.close()        
        return label_pk_id     


    # 2022-06-25
    def get_stack(self):
        stack={}
        pk=str(self.infor['label_pk_id'])        
        if self.package['id']==3:
            cur=self.connection.cursor() 
            s="select s.id,s.code from "+\
                "(select stack_id from inventory_stackdetails where label_pk_id="+pk+") d "+\
                "left outer join "+\
                "(select id,code,parent_id from inventory_stack) s "+\
                "on d.stack_id=s.id"
            cur.execute(s)
            r=cur.fetchone()
            if r:
                stack={'id':r[0],'code':r[1]}
        return stack

    #获取套标关系，目前只考虑箱carton，盒box，瓶bottle 三级对应关系
    #2022-05-20 AB标，跟亮亮确认，肉眼看到的是B标，套标关系一律显示B标
    def get_relations(self):   
        data={'level':0}
        pk=self.infor['label_pk_id']
        if not pk:
            return data   
        pk=str(pk)    
        c=self.infor['wl']
        cur=self.connection.cursor()     
        sA="coalesce((select code_a from label.lbl_abcode where code_a=l.code or code_b=l.code),'')"
        sB="coalesce((select code_b from label.lbl_abcode where code_a=l.code or code_b=l.code),'')"
        sNFC="coalesce((select nfc from label.lbl_nfc where label_code=l.code order by label_code limit 1),'')"   

        # 2022-06-25 是否为垛标
        if self.package['id']==7:            
            data['level']=2
            #取垛内箱标（主箱标) 注意写入垛标明细时用主箱标ID   
            s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                sA+","+sB+","+sNFC+",label_pk_id "+\
                "from "+\
                "(select id,label_code code,(select max(id) from label.lbl_replace_details where code=a.label_code or code0=a.label_code) rid," +\
                    "label_pk_id,label_id "+\
                    "from inventory_stackdetails a where stack_id="+pk+" and is_delete=false"+\
                ") l "+\
                "left outer join "+\
                "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                "on l.rid=r.id"
            cur.execute(s)            
            cartons=[]
            for r1 in cur.fetchall():               
                cartons.append({'label':r1[1],'code0':r1[2],'code':r1[3],'dt_replace':r1[4],'bottlecap':{},'code_a':r1[5],'code_b':r1[6],'color':'','nfc':r1[7],'label_pk_id':r1[8]})  
            data['cartons']=cartons
            data['children']=[]            
            return data    

        #2022-06-16 为不影响以前代码，对跨段，后绑定、再绑定 启用schema cartons  的标签单独处理
        if self.infor['carton']:   
            cartons=[]  
            children=[]    
            code=self.infor['label_pk_code']           
            cur.execute("SELECT level,box_tb,bottle_tb FROM carton.t"+code[:4]+"  where code='"+code+"'")
            r=cur.fetchone()            
            lv=r[0]
            data['level']=lv            
            #先取箱标
            t='label.t'+code[:4]
            s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                sA+","+sB+","+sNFC+" "+\
                "from "+\
                "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid " +\
                    "from "+t+" a where (id="+pk+" or parent_id="+pk+") and package_id=3 order by is_pk desc) l "+\
                "left outer join "+\
                "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                "on l.rid=r.id"
            cur.execute(s)
            rs1=cur.fetchall()        
            for r1 in rs1:
                clr_x=''
                nfc_x=r1[7]
                if c in [ r1[1],r1[2],r1[3],r1[5],r1[6] ]:
                    clr_x='red'
                cartons.append({'label':r1[1],'code0':r1[2],'code':r1[3],'dt_replace':r1[4],'bottlecap':{},'code_a':r1[5],'code_b':r1[6],'color':clr_x,'nfc':nfc_x}) 
            sFw="'' fw_code"
            #箱瓶二级对应
            if lv==2:
                #取瓶标对应关系 一箱的瓶标有可能在多个号段表   
                aLbl=[]
                for lbl in r[2].split(','):
                    aLbl.append("select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid,"+sFw+" "+\
                        "from label.t"+lbl+" a where parent_id="+pk+" and package_id=1")                     
                sLbl=" union all ".join(aLbl)                             
                s="select l.id,coalesce((select code_b from label.lbl_abcode where code_a=l.code or code_b=l.code),l.code),"+\
                    "coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from label.bottlecap where bottle in (r.code0,r.code,l.code) order by dt limit 1),''),"+\
                    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from logistics.z_bottlecap_binding where bottle in (r.code0,r.code,l.code) order by id desc limit 1),''),"+\
                    sA+","+sB+","+sNFC+","+sFw+" "+\
                    "from "+\
                    "(select max(id) id,code,rid,"+sFw+" from ("+sLbl+") u group by code,rid) l "+\
                    "left outer join "+\
                    "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                    "on l.rid=r.id "+\
                    "order by l.code"                
                cur.execute(s)
                rs3=cur.fetchall()            
                for r3 in rs3:
                    cap={'code':''}               
                    if r3[5]:
                        cap={'complete':True,'code':r3[5]}
                    elif r3[6]:
                        cap={'complete':False,'code':r3[6]}  
                    clr_p=''                
                    if r3[1]==c:
                        clr_p='red'   
                    children.append({'label':r3[1],'code0':r3[2],'code':r3[3],'dt_replace':r3[4],'bottlecap':cap,'code_a':r3[7],'code_b':r3[8],'is_bottlecap':False,'fw':r3[10],'color':clr_p,'nfc':r3[9] }) 
            #箱盒瓶三级对应
            elif lv==3:
                #盒标                
                aLbl=[]
                for lbl in r[1].split(','):
                    aLbl.append("select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid,"+sFw+" "+\
                        "from label.t"+lbl+" a where parent_id="+pk+" and package_id=2")                     
                sLbl=" union all ".join(aLbl)  
                s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                    sA+","+sB+","+sNFC+" "+\
                    "from "+\
                    "(select max(id) id,code,rid,"+sFw+" from ("+sLbl+") u group by code,rid) l "+\
                    "left outer join "+\
                    "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                    "on l.rid=r.id"
                cur.execute(s)
                rs2=cur.fetchall()
                for r2 in rs2:
                    clr_h=''
                    nfc_h=r2[7]
                    if c in [ r2[1],r2[2],r2[3],r2[5],r2[6] ] :
                        clr_h='red'
                    bottles=[]                  
                    processed=False      
                    aLbl=[]
                    for lbl in r[2].split(','):
                        aLbl.append("select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid,"+sFw+" "+\
                            "from label.t"+lbl+" a where parent_id="+pk+" and package_id=1")                     
                    sLbl=" union all ".join(aLbl)  
                    s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                        "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from label.bottlecap where bottle in (r.code0,r.code,l.code) order by dt limit 1),''),"+\
                        "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from logistics.z_bottlecap_binding where bottle in (r.code0,r.code,l.code) order by id desc limit 1),''),"+\
                        sA+","+sB+","+sNFC+" "+\
                        "from "+\
                        "(select id,code,rid,"+sFw+" from ("+sLbl+") u group by code,rid) l "+\
                        "left outer join "+\
                        "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                        "on l.rid=r.id"
                    cur.execute(s)
                    rs3=cur.fetchall()
                    #瓶标
                    for r3 in rs3:                    
                        clr_p=''
                        cap={'code':''}
                        nfc_p=r3[9]
                        if c in [ r3[1],r3[2],r3[7],r3[8] ]:
                            clr_p='red'                    
                        if r3[5]:                        
                            cap={'complete':True,'code':r3[5]}
                        elif r3[6]:
                            cap={'complete':False,'code':r3[6]}                                          
                        bottles.append({'label':r3[1],'code0':r3[2],'code':r3[3],'dt_replace':r3[4],'bottlecap':cap,'code_a':r3[7],'code_b':r3[8],'color':clr_p,'nfc':nfc_p})                
                    children.append({'label':r2[1],'code0':r2[2],'code':r2[3],'dt_replace':r2[4],'bottlecap':{},'code_a':r2[5],'code_b':r2[6],'children':bottles,'color':clr_h,'nfc':nfc_h})                
            cur.close()
            data['cartons']=cartons
            data['children']=children        
            return data
        else:        
            #2021-12-03
            if self.tb_cross:
                t=self.tb_cross   
            elif self.infor['is_thirdparty']: 
                t="label.thirdparty"
            else:
                t="label.t" +c[:4]    
        #箱标
        s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
            sA+","+sB+","+sNFC+" "+\
            "from "+\
            "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid " +\
                "from "+t+" a where (id="+pk+" or parent_id="+pk+") and package_id=3 order by is_pk desc) l "+\
            "left outer join "+\
            "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
            "on l.rid=r.id"
        cur.execute(s)
        rs1=cur.fetchall()
        cartons=[]  
        children=[]     

        
        for r1 in rs1:
            clr_x=''
            nfc_x=r1[7]
            if c in [ r1[1],r1[2],r1[3],r1[5],r1[6] ]:
                clr_x='red'
            cartons.append({'label':r1[1],'code0':r1[2],'code':r1[3],'dt_replace':r1[4],'bottlecap':{},'code_a':r1[5],'code_b':r1[6],'color':clr_x,'nfc':nfc_x})
        s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
            sA+","+sB+","+sNFC+" "+\
            "from "+\
            "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid " +\
                "from "+t+" a where parent_id="+pk+" and package_id=2"+\
            ") l "+\
            "left outer join "+\
            "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
            "on l.rid=r.id"
        cur.execute(s)
        rs2=cur.fetchall()
        if rs2:            
            data['level']=3  
            #盒标
            for r2 in rs2:
                clr_h=''
                nfc_h=r2[7]
                if c in [ r2[1],r2[2],r2[3],r2[5],r2[6] ] :
                    clr_h='red'
                bottles=[]                  
                processed=False                
                s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from label.bottlecap where bottle in (r.code0,r.code,l.code) order by dt limit 1),''),"+\
                    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from logistics.z_bottlecap_binding where bottle in (r.code0,r.code,l.code) order by id desc limit 1),''),"+\
                    sA+","+sB+","+sNFC+" "+\
                    "from "+\
                    "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid " +\
                        "from "+t+" a where parent_id="+str(r2[0])+" and package_id=1"+\
                    ") l "+\
                    "left outer join "+\
                    "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                    "on l.rid=r.id"
                cur.execute(s)
                rs3=cur.fetchall()
                #瓶标
                for r3 in rs3:                    
                    clr_p=''
                    cap={'code':''}
                    nfc_p=r3[9]
                    if c in [ r3[1],r3[2],r3[7],r3[8] ]:
                        clr_p='red'                    
                    if r3[5]:                        
                        cap={'complete':True,'code':r3[5]}
                    elif r3[6]:
                        cap={'complete':False,'code':r3[6]}                                          
                    bottles.append({'label':r3[1],'code0':r3[2],'code':r3[3],'dt_replace':r3[4],'bottlecap':cap,'code_a':r3[7],'code_b':r3[8],'color':clr_p,'nfc':nfc_p})                
                children.append({'label':r2[1],'code0':r2[2],'code':r2[3],'dt_replace':r2[4],'bottlecap':{},'code_a':r2[5],'code_b':r2[6],'children':bottles,'color':clr_h,'nfc':nfc_h})
        else:    
            #2021-11-29 第三方防伪码，目前只考虑二级对应
            data['level']=2
            sFw="'' fw_code"
            sUnionRebinding="union all select parent_id id,code,null rid,'' fw_code from label.lbl_rebinding_details "+\
                "where parent_id="+pk
            if self.infor['is_thirdparty']: 
                sFw="coalesce(fw_code,'') fw_code"
                sUnionRebinding=""   
            #2022-05-20
            s="select l.id,coalesce((select code_b from label.lbl_abcode where code_a=l.code or code_b=l.code),l.code),"+\
                "coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from label.bottlecap where bottle in (r.code0,r.code,l.code) order by dt limit 1),''),"+\
                "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from logistics.z_bottlecap_binding where bottle in (r.code0,r.code,l.code) order by id desc limit 1),''),"+\
                sA+","+sB+","+sNFC+","+sFw+" "+\
                "from "+\
                "(select max(id) id,code,rid,"+sFw+" from "+\
                    "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid,"+sFw+" "+\
                        "from "+t+" a where parent_id="+pk+" and package_id=1 "+\
                        sUnionRebinding+\
                    ") u "+\
                    "group by code,fw_code,rid "+\
                ") l "+\
                "left outer join "+\
                "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                "on l.rid=r.id "+\
                "order by l.code"       
            cur.execute(s)
            rs3=cur.fetchall()            
            for r3 in rs3:
                cap={'code':''}               
                if r3[5]:
                    cap={'complete':True,'code':r3[5]}
                elif r3[6]:
                    cap={'complete':False,'code':r3[6]}  
                clr_p=''                
                if r3[1]==c:
                    clr_p='red'   
                children.append({'label':r3[1],'code0':r3[2],'code':r3[3],'dt_replace':r3[4],'bottlecap':cap,'code_a':r3[7],'code_b':r3[8],'is_bottlecap':False,'fw':r3[10],'color':clr_p,'nfc':r3[9] })  

            #2022-04-25 诗仙太白 code_a,跨段 箱-箱 159箱
            if self.infor['sup_pk_id']:
                clr=''
                s="select code,"+sA+","+sB+","+sNFC+" "+\
                    "from "+self.infor['sup_pk_id']['tb']+" l where parent_id="+str(self.infor['sup_pk_id']['id'])   
                cur.execute(s)
                for r3 in cur.fetchall():
                    if r3[0]==c:
                        cls='red'
                    cap={'complete':False,'code':''}
                    children.append({'label':r3[0],'code0':'','code':'','dt_replace':'','bottlecap':cap,'code_a':r3[1],'code_b':r3[2],'is_bottlecap':False,'fw':'','color':clr,'nfc':r3[3] })
                #删除159箱 箱-箱 绑定关系里后补关联箱
                #cartons.append({'label':r1[1],'code0':r1[2],'code':r1[3],'dt_replace':r1[4],'bottlecap':r1[5],'code_a':r1[1],'code_b':r1[6]})  
                i=0
                for ct in cartons:                    
                    if ct['label'][:4]=='1044':
                        cartons.pop(i)
                    i=i+1              
            
            #2021-05-03 酒鬼酷客白在线绑定,把米多瓶盖码做为瓶标显示
            if not children:  
                cur.execute("select bottle from label.bottlecap where label_pk_id="+pk)
                rs4=cur.fetchall()                
                if rs4:
                    cap={'complete':True,'code':''}
                    for r4 in rs4:
                        clr=''
                        if r4[0]==c:
                            clr='red'
                        children.append({'label':r4[0],'code0':'','code':'','dt_replace':'','bottlecap':cap,'code_a':'','code_b':'','is_bottlecap':True,'color':clr,'nfc':''})
                else:
                    cur.execute("select bottle from logistics.z_bottlecap_binding where label_pk_id="+pk)
                    rs4=cur.fetchall()  
                    cap={'complete':False,'code':''}
                    for r4 in rs4:
                        clr=''
                        if r4[0]==c:
                            clr='red'
                        children.append({'label':r4[0],'code0':'','code':'','dt_replace':'','bottlecap':cap,'code_a':'','code_b':'','is_bottlecap':True,'color':clr,'nfc':''})
        cur.close()
        data['cartons']=cartons
        data['children']=children        
        return data

    def get_product(self):
        data={'name':'未知','price':'未知','property':[],'id':0,'external_code':'','photo':'','shelf_life':{},'barcode':'',
                'inbound_date':'','inbound_lot':'','inbound_aging':'','inbound_vendor':'','outbound_aging':''}
        pk=self.infor['label_pk_id']
        if not pk:
            return data     
        pk=str(pk)
        cur=self.connection.cursor()
        cur.execute("select ancestor_id from company_company where id="+str(self.company_id))
        r=cur.fetchone()
        aid=str(r[0])     
        
        # 2022-06-25 是否为垛标   
        if self.package['id']==7:            
            s="select s.product_id,coalesce(p.name,''),coalesce(to_char(p.price,'99999.09'),'未知'),p.contents,p.external_code,"+\
                "coalesce(p.photo,''),shelf_life,barcode from "+\
                "(select product_id from inventory_stack where id="+pk+") s "+\
                "left outer join "+\
                "(select id,name,price,coalesce(contents,'') contents,external_code,photo,shelf_life,barcode from product_product where company_id="+aid+") p "+\
                "on s.product_id=p.id"
        else:
            s="select s.product_id,coalesce(p.name,''),coalesce(to_char(p.price,'99999.09'),'未知'),p.contents,p.external_code,"+\
                "coalesce(p.photo,''),shelf_life,barcode from "+\
                "(select coalesce("+\
                        "(select product_id from inventory_stkdetails where company_id="+aid+" "+\
                            "and label_pk_id="+pk+" and vtype_id=1 and is_delete=false order by id limit 1),"+\
                        "(select product_id from inventory_stkdetails where company_id="+aid+" "+\
                            "and label_pk_id="+pk+" and  vtype_id=2 order by id limit 1), "+\
                        "(select product_id from z_bottle_cap_product where id="+\
                            "(select coalesce((select product_id from label.bottlecap where label_pk_id="+pk+" limit 1),"+\
                                "(select product_id from z_bottlecap_binding where label_pk_id="+pk+" limit 1))) "+\
                        ")"+\
                    ") product_id "+\
                ") s "+\
                "left outer join "+\
                "(select id,name,price,coalesce(contents,'') contents,external_code,photo,shelf_life,barcode from product_product where company_id="+aid+") p "+\
                "on s.product_id=p.id  where s.product_id>0"           
        
        cur.execute(s)
        r=cur.fetchone()
        if r: 
            # 2022-06-26 产品ID不为空
            if r[0]:
                data['name']=r[1]
                data['price']=r[2].strip()
                data['id']=r[0]
                data['external_code']=r[4]
                # 2022-07-27
                if r[5]:
                    data['photo']='/media/'+r[5]
                if r[6]:
                    data['shelf_life']=r[6]
                if r[7]:
                    data['barcode']=r[7]
                s="select coalesce(c.value,'') val,g.name,g.desc_cn,coalesce(g.unit,'') from "+\
                    "(SELECT * FROM product_prdprops where product_id="+str(r[0])+") p "+\
                    "left outer join "+\
                    "(SELECT * FROM product_productprop where company_id="+aid+") c "+\
                    "on p.prd_property_id=c.id "+\
                    "left outer join "+\
                    "(select * from company_categoryprop) g "+\
                    "on c.categoryprop_id=g.id"
                cur.execute(s)
                for rr in cur.fetchall():
                    data['property'].append({'desc_cn':rr[2],'unit':rr[3],'value':rr[0]})                
                #2021-08-05 颂恩在产品表添加contents字段，用于存放当前产品的多张图片
                contents=''
                if r[3]:
                    if r[4]:
                        contents=urllib.parse.quote(r[4])
                data['contents']=contents            
                #2022-04-18 取生产批次,采摘日期（入库）,入库日期，供应商           
                s="select coalesce(b.code,b.batch_no),coalesce(b.product_aging,''),"+\
                    "coalesce((select name from mes_vendor where id=vendor_id),''),to_char(b.dt,'yyyy-mm-dd') "+\
                    "from "+\
                    "(select batch_id from inventory_stkdetails where company_id="+aid+" and vtype_id=1 "+\
                        "and is_delete=false and label_pk_id="+pk+" order by id limit 1) d "+\
                    "left outer join "+\
                    "(select id,code,batch_no,product_aging,vendor_id,dt from inventory_batch where company_id="+aid+" and vtype_id=1) b "+\
                    "on d.batch_id=b.id"
                cur.execute(s)
                rr=cur.fetchone()
                if rr:
                    data['inbound_lot']=rr[0]
                    data['inbound_aging']=rr[1]
                    data['inbound_vendor']=rr[2]
                    data['inbound_date']=rr[3]
                #产品年份（内参销售出库）
                s="select coalesce(b.product_aging,'')    from "+\
                    "(select batch_id from inventory_stkdetails where company_id="+aid+" and vtype_id=2 "+\
                        "and is_delete=false and label_pk_id="+pk+" order by id desc limit 1) d "+\
                    "left outer join "+\
                    "(select id,code,batch_no,product_aging from inventory_batch where company_id="+aid+" and vtype_id=2) b "+\
                    "on d.batch_id=b.id"
                cur.execute(s)
                rr=cur.fetchone()
                if rr:
                    data['outbound_aging']=rr[0]  
        cur.close()            
        return data

    #2022-04-18 返回防伪查询信息
    def get_security_info(self):
        aid=str(self.company_id)
        data={"times":0,"image":""}        
        url_internal='http://www.china315net.com:35088/get/codes/from/wuliu/'+aid+'/'
        sK_internal='$internal&GLker5w3jtQLx#'
        #根据物流码取防伪码        
        wl_code=self.infor['wl']
        t = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        m2 = hashlib.md5((sK_internal + t).encode('utf8'))
        key = m2.hexdigest()
        d=[{'id':1,'label':wl_code}]
        r=requests.post(url_internal + '/fw/', json={'key': key, 'time': t, 'labels': d}) 
        if r.status_code==200:
            d = json.loads(r.text)
            fw_code=d['data'][0]['code']        
            url='http://www.china315net.com:35207/tjfw/get/'
            guid=str(uuid.uuid1())
            param={
                'fwcode':fw_code,   #防伪码
                'record':1,         #需要写入查询记录
                'uid':'hand_'+guid,       #用户名，上海汉得
                #'pid':,             #产品ID
                #'cid':1,            #酒鬼酒
                #'package':          #包装
            }
            r=requests.get(url,param) 
            #{
            # "err":错误信息,
            # "img":Base64,
            # "counter":{
            #   "tel":电话查询次数,
            #   "sms":短信查询次数,
            #   "net":网络查询次数
            #  },
            #  "am":暗码,
            #  "wz":文字,
            #  "company":公司名称,
            #  "product":产品名称,
            #  "QueryResult":查询结果,
            #  "CodeState":0出错,1正常,
            #  "history":[前10条查询记录]
            #}
            if r.status_code==200:
                d=json.loads(r.text)
                cnt=d['counter']['net']
                img=d['img']
                data={'times':cnt,'image':img}
        return data



    def get_replaced_labels(self):
        b=[]
        pk=self.infor['label_pk_id']
        if not pk:
            return b
        pk=str(pk)
        c=self.infor['label_pk_code']
        if self.tb_cross:
            tb=self.tb_cross
        elif self.infor['is_thirdparty']:
            tb="label.thirdparty"
        else:
            tb="label.t"+c[:4]

        s="select code from label.lbl_replace_details where code0 in "+\
            "(select code from "+tb+" where id="+pk+" or parent_id="+pk+") "+\
            "group by code"
        cur=self.connection.cursor()
        cur.execute(s)
        for r in cur.fetchall():
            b.append(r[0])
        cur.close()
        return b
    

    def get_stk_dev(self):
        data=[]
        pk=self.infor['label_pk_id']
        if not pk:
            return data
        pk=str(pk)
        
        #2022-07-21
        code=self.infor['code']
        if self.infor['label_a']:
            code=self.infor['label_a']

        # 2022-06-25 是否为垛标
        if self.package['id']==7: 
            return data

        cur=cur=self.connection.cursor()
        cur.execute("select ancestor_id from company_company where id="+str(self.company_id))
        r=cur.fetchone()
        aid=str(r[0])


        # 2022-07-19 同一族系，母公司可以查子公司物流 hierarchy_id
        #100424;"成义烧坊酒业股份有限公司" 111006;"成都成义烧坊电子有限公司"
        #1;"酒鬼酒股份有限公司" 1644;"湖南内参酒销售有限责任公司"        
        hierarchies={
            '1':['1','1644'],                   #酒鬼可查内参
            '100424':['100424','111006'],       #烧坊可查电子
        }
        if str(self.company_id)==aid:
            sAid=" and ancestor_id="+aid
            #if aid=='1':
            #    sAid=" and ancestor_id in (1,1644)"
            if str(self.company_id) in hierarchies:
                sAid=" and ancestor_id in ("+",".join(hierarchies[str(self.company_id)])+")"
        else:
            #经销商可查自己和下级经销商物流
            #sAid=" and company_id="+str(self.company_id)+" or (select parent_id from company_company where id=company_id)="+str(self.company_id) 
            #2022-06-15
            #sAid=" and (company_id="+str(self.company_id)+" and parent_id="+str(self.company_id)+")" 
            # 2022-07-06
            sAid=" and (company_id="+str(self.company_id)+" or (select parent_id from company_company where id=company_id)="+str(self.company_id)+")" 
        
        replaced_labels=self.get_replaced_labels()
        sRep=''
        if replaced_labels:
            sRep=" or label_code in ('"+"','".join(replaced_labels)+"')"
        s="select "+\
            "coalesce((select code_b from label.lbl_abcode where code_a=s.label_code or code_b=s.label_code limit 1),s.label_code),"+\
            "b.code,to_char(s.tm,'yyyy-MM-dd HH24:MI:ss'),"+\
            "(select name from inventory_voucher where id=s.vtype_id),"+\
            "(select name from product_product where id=s.product_id),"+\
            "(select username from company_user where id=b.user_id),"+\
            "(select name from company_company where id=s.company_id),"+\
            "coalesce(c.name,''),"+\
            "coalesce((select name from inventory_storehouse where id=s.store_id),''),"+\
            "coalesce((select name from inventory_storehouse where id=s.store_to_id),''),"+\
            "(select name from label.lbl_package where id=s.label_pkg),"+\
            "coalesce((select code_b from label.lbl_abcode where code_a=s.label_code),''),"+\
            "vtype_id,case when is_delete then 1 else 0 end,"+\
            "coalesce(c.external_code,''),b.id,coalesce(c.address,''),"+\
            "coalesce((select name from gis.adm where id=c.province_gis_id),c.province,''),"+\
            "coalesce((select name from gis.adm where id=c.city_gis_id),c.city,''),"+\
            "s.label_pkg,coalesce(b.rmk_name,'') "+\
            "from "+\
            "(select label_code,label_pkg,company_id,company_to_id,product_id,"+\
                "store_id,store_to_id,batch_id,tm,vtype_id,is_delete FROM inventory_stkdetails "+\
                "where (label_pk_id="+pk+sRep+" or label_code='"+code+"')"+sAid+") s "+\
            "left outer join "+\
            "(select id,code,user_id,rmk_name from inventory_batch) b "+\
            "on s.batch_id=b.id "+\
            "left outer join "+\
            "(select id,name,external_code,address,province,province_gis_id,city,city_gis_id "+\
                "from company_company where ancestor_id="+aid+\
            ") c "+\
            "on s.company_to_id=c.id "+\
            "order by s.tm "
        cur.execute(s)
        #print(s)
        bOut=False #是否需要查询酒鬼酒本地数据库
        for r in cur.fetchall():
            rmk=''
            if r[20]:
                rmk=' '+r[20]
            if r[12]==2:
                bOut=True
            data.append({
                'label_code':r[0],'bill_no':r[1],'tm':r[2],'voucher':r[3],'product':r[4],'user':r[5],'vtype_id':r[12],
                'company':r[6],'customer':r[7]+rmk,'store':r[8],'store_to':r[9],'label_pkg':r[10],"code_b":r[11],'is_delete':r[13],
                'customer_external_code':r[14],'batch_id':r[15],'label_pkg_id':r[19],
                'agent':{'name':r[7],'external_code':r[14],'address':r[16],'province':r[17],'city':r[18]}
            })
        if not bOut and aid=='1': 
            #dd=jiugui_local116(self.infor['label_pk_code']) 
            #2022-03-15 酒鬼酒本地sql svr数据已转入 pg jiugui_local            
            dd=get_jiugui_local(pk)            
            
            for d in dd['stock_dev']:
                data.append({ 
                    #'vtype_id':0,
                    'vtype_id':d['vtype_id'],
                    'label_code':d['label_code'],
                    'bill_no':d['voucher_no'],
                    'tm':d['time'],  
                    'voucher':d['voucher_type'],
                    'product':d['product'],                                  
                    'user':'',                    
                    'company':'酒鬼酒股份有限公司',                    
                    'customer':d['to_company'],
                    'store':d['store'],
                    'store_from':'',
                    'label_pkg':d['package'],
                    'label_pkg_id':3,
                    'code_b':'',
                    'is_delete':0,
                    'agent':{'name':'','external_code':'','address':'','province':'','city':''}
                }) 
                
        #2022-06-18
        elif aid in os_cids:
            ds=os_label_outbound(os_cids[aid],self.infor['label_pk_code'])
            _data = []
            # 循环找出不重复的单号 插入到_data
            for da in data:
                is_repeat = False
                for d in ds:
                    if da['bill_no'] == d['bill_no']:
                        is_repeat = True
                # 如果没有和os产生重复数据
                if not is_repeat:
                    _data.append(da)
                
            for d in ds:
                _data.insert(0,d)      
            data = _data
        cur.close()
        return data
"""






#2022-08-25 含跨段在线绑定（再绑定）标签查询
class LabelQuery():
    def __init__(self,company_id,code,conn=None):
        if not conn:
            conn=connection
        self.code=code    
        self.tb_cross=''    #卷标跨段表名
        self.company_id=int(company_id)
        self.connection=conn 
        self.package={}        
        self.infor={
            'label_company_id':0,       #标签所属公司ID
            'code':code,                #查询的106301364235
            'label_a':'',               #A标号码
            'label_b':'',               #B标号码
            'label_pk_id':0,            #主箱标ID
            'label_pk_code':'',         #主箱标号码
            #2022-02-23
            'label_id':0,               #标签ID            
            'ab_bindding':False,        #是否为AB标 
            'has_nfc':False,            #是否有NFC标签
            'is_thirdparty':False,      #是否为第三方标签
            'ab_data':1,                #AB标基础数据表 0:单枚标 无基础数据 1:code_a 2:code_b
            'is_active':False,          #标签是否已激活（系统内是否有物流记录）
            'is_bottlecap':False,       #是否为瓶盖码            
            'bottlecap':'',             #瓶盖码
            'wl':'',                    #系统内物流编码

            #2022-04-25 后补主箱标IDS 
            #如诗仙太白：159箱，箱-箱（跨段）绑定，1托3 +1托6 =9瓶/箱
            'sup_pk_id':{},
            
            #2022-06-14  标签库新建的schema,用以保存企业跨段后绑定的主箱标及子标所有号段
            'carton':'',

            # 2022-06-257;"垛标";"用于扫垛标发货/入库"
            'stack':{}
        } 
        #取主箱标ID，包装，是否已激活          
        self.infor['label_pk_id']=self.get_label_pk()     
        
    def get_label_pk(self):
        label_pk_id=None
        label_pk_code=None
        company_id=self.company_id
        company=Company.objects.get(id=int(company_id))
        aid=company.ancestor_id
        code=self.code    
        cur=self.connection.cursor()

        sPkg='package_id'   #一般情况下，标签类别取标签基础表的 package_id 字段
        #2021-05-06 瓶盖码
        if not code.isdigit():  
            #2022-03-14 酒鬼小圆标也有替换
            s="select code0,code from label.lbl_replace_details where code='"+code+"' order by id desc limit 1"
            cur.execute(s)
            r=cur.fetchone()
            if r:
                code=r[0]     
            d_code=decrypt_11h(code)
            if not d_code:               
                return None
            else:
                self.infor['is_bottlecap']=True
                self.infor['bottlecap']=code
                self.infor['code']=d_code
                sPkg='100 package_id'  #瓶盖码标签类别id为100                
                cur.execute("select bottle from label.bottlecap where  label='"+code+"' "+\
                    " union all "+\
                    "select bottle from z_bottlecap_binding where  label='"+code+"' "
                )
                r=cur.fetchone()
                if r:
                    code=r[0]                    
                else:
                    #2021-09-13 是否为小圆标活动码
                    code=d_code  
                #2021-11-29
                self.code=code   
        #2022-04-27 可能查询的是瓶盖码解密后的数据
        else:             
            cur.execute("select bottle from label.bottlecap where code='"+code+"' "+\
                " union all "+\
                "select bottle from z_bottlecap_binding where code='"+code+"' "
            )
            r=cur.fetchone()
            if r:
                self.infor['code']=code
                self.infor['bottlecap']=code
                code=r[0]   
                sPkg='100 package_id'  #瓶盖码标签类别id为100 

        if company.ancestor_id in (1,1644) and code[:1]=='4':
            r = requests.request('GET', 'http://www.china315net.com:35088/jg/fw_wl/'+code+'/')
            d = json.loads(r.text) 
            if d['wl']:
                code=d['wl']   
                self.infor['wl']=code                
            else:       
                #cur.close()
                #return None 2022-03-15 酒鬼有4开头的物流码 如早期 54°500ml简优  
                pass
        #是否为AB表 A标为物流码，B标用于显示（肉眼可见，12位数字）
        cur.execute("select coalesce(code_a,''),coalesce(code_b,''),id FROM label.lbl_abcode where code_a='"+code+"' or code_b='"+code+"'")
        r=cur.fetchone()
        if r:            
            code=r[0] 
            self.infor['ab_bindding']=True
            self.infor['label_a']=r[0]
            self.infor['label_b']=r[1]
            #2021-07-14 正常情况，查A标（物流标） code_a 数据表            
            self.code=code
            #2022-04-25 诗仙太白 code_a,跨段 箱-箱 159箱
            if r[1][:4]=='1045' or r[0][:4]=='1045':
                s="select code from label.t1045 where package_id=3 and left(code,4)='1044' and parent_id="+\
                    "(select id from label.t1045 where code='"+code+"')"  
                cur.execute(s)
                rrr=cur.fetchone()
                if rrr:     
                    s="select id from label.t9073 where code="+\
                        "(select code_a from label.lbl_abcode where code_b='"+rrr[0]+"')"                    
                    cur.execute(s)
                    rrr=cur.fetchone()
                    if rrr:
                        self.infor['sup_pk_id']={'id':rrr[0],'tb':'label.t9073'}           
        s="select code0,code,dt from label.lbl_replace_details where code='" + code +"' order by id desc limit 1"    
        cur.execute(s)   
        rr=cur.fetchone()    
        if rr:
            code=rr[0] 
        if not self.infor['wl']:    
            self.infor['wl']=code

        t="label.t" +code[:4]    
        # 2022-08-19 是否保存于标准物流标签库（含套标跨段标准格式存储）
        cur.execute("select count(*) from information_schema.tables where table_schema = 'label' "+
            "and table_type = 'BASE TABLE' and table_name = 't"+code[:4]+"'")
        r0=cur.fetchone()
        if r0[0]:
            s="select l.id,l.package_id,l.parent_id,l.is_pk,l.parent_tb,l.code,"+\
                "p.id,p.name,coalesce(p.remark,''),p.outermost,p.innermost,p.binding,l.company_id "+\
                "from "+\
                "(select id,package_id,parent_id,is_pk,parent_tb,code,company_id from "+t+" where code='"+code+"') l "+\
                "left outer join "+\
                "(SELECT id,name,remark,outermost,innermost,binding FROM label.lbl_package) p "+\
                "on l.package_id=p.id"
            cur.execute(s)
            rrr=cur.fetchone()
            # 默认主箱标表名 t
            x_tb=t           
            if rrr:
                if rrr[12]:
                    self.infor['label_company_id']=rrr[12]
                self.infor['label_id']=rrr[0]
                self.package={'id':rrr[6],'name':rrr[7],'remark':rrr[8],'outermost':rrr[9],'innermost':rrr[10],'is_biding':rrr[11]}
                if rrr[1]==3:
                    # 副箱标
                    if rrr[2]:
                        if rrr[4]:
                            self.infor['carton']=rrr[4]
                            x_tb='label.t'+rrr[4]
                        s="select id,code from "+x_tb+" where id="+str(rrr[2])
                        cur.execute(s)
                        r4=cur.fetchone()
                        if r4:
                            self.infor['label_pk_id']=r4[0]
                            self.infor['label_pk_code']=r4[1]
                            return self.infor['label_pk_id']
                    # 主箱标
                    else:
                        cur.execute("select count(*) from information_schema.tables where table_schema = 'carton' "+
                            "and table_type = 'BASE TABLE' and table_name = 't"+code[:4]+"'")
                        r0=cur.fetchone()
                        if r0[0]:
                            s="select id from carton.t"+code[:4]+" where code='"+code+"'"
                            cur.execute(s)
                            r4=cur.fetchone()
                            if r4:
                                self.infor['carton']=code[:4]
                            self.infor['label_pk_id']=rrr[0]
                            self.infor['label_pk_code']=rrr[5]                            
                            return self.infor['label_pk_id']
                elif rrr[1]==2:
                    if rrr[4]:
                        self.infor['carton']=rrr[4]
                        x_tb='label.t'+rrr[4]
                    if rrr[2]:
                        s="select id,code,parent_tb from "+x_tb+" where id="+str(rrr[2])
                        cur.execute(s)
                        r4=cur.fetchone()
                        if r4:                        
                            self.infor['label_pk_id']=r4[0]
                            self.infor['label_pk_code']=r4[1]                       
                            return self.infor['label_pk_id']
                elif rrr[1]==1:
                    b_cross=False
                    h_tb=t
                    if rrr[4]:
                        b_cross=True                        
                        h_tb='label.t'+rrr[4]
                    if rrr[2]:
                        s="select id,code,parent_id,parent_tb,package_id from "+h_tb+" where id="+str(rrr[2])                        
                        cur.execute(s)
                        r4=cur.fetchone()
                        if r4:
                            if r4[3]:
                                b_cross=True
                                x_tb='label.t'+r4[3]
                            if r4[4]==3:
                                # 箱瓶 二级绑定关系
                                self.infor['label_pk_id']=r4[0]
                                self.infor['label_pk_code']=r4[1]
                                if rrr[4]:
                                    self.infor['carton']=r4[1]
                                return r4[0]
                            else:
                                # 箱盒瓶三级绑定
                                s="select id,code,parent_id,parent_tb,package_id from "+x_tb+" where id="+str(r4[2])    #2022-08-23                              
                                cur.execute(s)
                                r5=cur.fetchone()         
                                if r5:
                                    self.infor['label_pk_id']=r5[0]
                                    self.infor['label_pk_code']=r5[1]
                                    if b_cross:
                                        self.infor['carton']=r5[1]    
                                    return self.infor['label_pk_id']

        #2022-06-24 是否在酒鬼跨段表
        cur.execute("select coalesce(parent_id,id),"+\
            "(select code from label.lbl_binding_jg where id=coalesce(j.parent_id,j.id)),"+\
            "package_id,(select name from label.lbl_package where id=package_id) "+\
            "from label.lbl_binding_jg j where code='"+code+"'")
        rrr=cur.fetchone()
        if rrr:    
            t='label.lbl_binding_jg'
            self.tb_cross=t
            self.infor['label_pk_code']=rrr[1]
            self.package={'id':rrr[2],'name':rrr[3]}
            return rrr[0]

        #2022-06-24 是否是垛标
        s="SELECT id,code,parent_id,location,qty_lmt,is_fixed,store_id,product_id,remark,code_is_permanent "+\
            "from inventory_stack where code='"+code+"' and is_delete=false"  
        cur.execute(s)
        rrr=cur.fetchone()
        if rrr:
            is_permanent=True
            self.package={'id':7,'name':'垛标'}     
            if rrr[2]:
                label_pk_id=rrr[2]
                cur.execute("select code,code_is_permanent from inventory_stack where id="+str(rrr[2]))
                r3=cur.fetchone()
                if r3:
                    sc=r3[0]
                    is_permanent=r3[1]
                else:
                    sc=''
            else:
                label_pk_id=rrr[0]
                sc=rrr[1]
                is_permanent=rrr[9]
            
            self.infor['stack']['id']=label_pk_id
            self.infor['stack']['code']=sc    
            self.infor['stack']['is_permanent']=is_permanent
            self.infor['label_pk_code']=sc
            return label_pk_id

        #查询的物流基础表是否存在    
        cur.execute("select count(*) from information_schema.tables where table_schema='label' and table_type='BASE TABLE' and table_name='t"+code[:4]+"'")       
        rr=cur.fetchone()  
        if rr[0]==0:
            #表不存在
            if self.infor['ab_bindding']:
                #基础数据是否在code_b
                tb="t"+self.infor['label_b'][:4]
                cur.execute("select count(*) from information_schema.tables where table_schema='label' and table_type='BASE TABLE' and table_name='"+tb+"'")
                rrr=cur.fetchone()
                if rrr[0]:
                    t='label.t'+self.infor['label_b'][:4]
                    code=self.infor['label_b']
                else:
                    cur.close()
                    return None 
            else:      
                #是否为第三方标签                                  
                cur.execute("select id from label.thirdparty where code='"+code+"' and cid="+str(aid))
                rrr=cur.fetchone()
                if rrr:
                        self.infor['is_thirdparty'] = True
                        t="label.thirdparty"
                else:
                        cur.close()
                        return None   
        else:
            #表存在，标不在表里 （可能是第三方标签）
            cur.execute("select id from "+t+" where code='"+code+"'")
            rrr=cur.fetchone()
            if not rrr:            
                tb="label.thirdparty"                
                cur.execute("select id from "+tb+" where code='"+code+"' and cid="+str(aid))
                rrr=cur.fetchone()
                if rrr:
                    self.infor['is_thirdparty'] = True
                    t="label.thirdparty"
                else:
                    cur.close()
                    return None  

        s="select p.id,p.name,coalesce(p.remark,''),p.outermost,p.innermost,p.binding,"+\
            "coalesce((select parent_id from " +t+ " where id=l.parent_id),l.parent_id,l.id),"+\
            "l.id,l.parent_tb,l.package_id,l.parent_id  from "+\
            "(select id,"+sPkg+",parent_id,parent_tb from "+t+" where code='"+code+"') l "+\
            "left outer join "+\
            "(SELECT id,name,remark,outermost,innermost,binding FROM label.lbl_package) p "+\
            "on l.package_id=p.id"
        cur.execute(s)
        r = cur.fetchone()             
        
        #因为有跨段后绑定、再绑定，只能 逐级查找 目的：找到主箱标物流码ID和号码
        #有父级ID或本身ID
        if r[6]:
            #2022-06-14 标签是否为跨段后绑定,非主箱标
            if r[8]:
                #1;"瓶标";"套标，无子级";FALSE;TRUE;TRUE
                #2;"盒标";"套标，有父级和子级";FALSE;FALSE;TRUE
                #3;"箱标";"套标，无父级";TRUE;FALSE;TRUE
                #4;"单枚标";"独立箱标或独立瓶标";TRUE;TRUE;FALSE
                #5;"条盒";"烟标，条盒";TRUE;FALSE;FALSE
                #6;"小盒";"烟标，小盒";FALSE;TRUE;FALSE
                #11;"独立瓶标";"瓶标，但生号时没有套标关系";FALSE;TRUE;FALSE
                #12;"独立盒标";"盒标，但生号时没有套标关系";FALSE;FALSE;FALSE
                #13;"独立箱标";"箱标，但生号时没有套标关系";TRUE;FALSE;FALSE
                #20;"外包码";"按包发货，如众茶国际，1包100套";TRUE;FALSE;TRUE
                #100;"活动码";"瓶盖内码,用于促销活动";FALSE;TRUE;FALSE               

                #当前标签为副箱标，或盒标
                if r[9] in [2,3,12,13]:                    
                    self.infor['carton']=r[8]
                    label_pk_id=r[10]                        
                    self.infor['label_pk_id']=label_pk_id
                elif r[9] in [1,11]:
                    ct=r[8]
                    #查询的是瓶标 如果三级绑定，可能瓶盒在一个号段，箱在另一个号段                    
                    s="select parent_id,parent_tb,package_id,code,id from label.t"+r[8]+" where id="+str(r[10])
                    cur.execute(s)
                    r10=cur.fetchone()    
                    if r10:
                        if r10[2] in [3,13]:                            
                            label_pk_id=r10[4]             
                            self.infor['carton']=ct
                            if r10[1]:
                                self.infor['carton']=r10[1]
            else: 
                if self.infor['is_thirdparty']:
                    label_pk_id=r[6]
                else:                              
                    cur.execute("select parent_id,parent_tb,package_id,code,id from "+t+" where id="+str(r[6])) 
                    r10=cur.fetchone()
                    if r10[2] in [3,13]:   
                        label_pk_id=r[6]  
                        #也可能查询的是主箱标,主箱标是否在 schema carton    
                        cur.execute("select count(*) from information_schema.tables where "\
                            "table_schema='carton' and table_type='BASE TABLE' and table_name='t"+r10[3][:4]+"'")
                        rr=cur.fetchone()  
                        if rr[0]>0:    
                            cur.execute("select id from carton.t"+code[:4]+" where code='"+r10[3]+"'")
                            rrr=cur.fetchone()
                            if rrr:
                                self.infor['carton']=r10[3][:4]                        
                    #可能返回的是盒标
                    elif r10[0]: 
                        if r10[1]:
                            cur.execute("select parent_id,parent_tb,package_id,code from label.t"+r10[1]+" where id="+str(r10[0]))
                            r11=cur.fetchone()
                            if r11:
                                label_pk_id=r11[0]
                                if r11[1]:
                                    self.infor['carton']=r11[1]
            #2022-02-23
            self.infor['label_id']=r[7]   
            #2022-06-17 
            if not label_pk_id:
                label_pk_id=r[6]
        else:           
            return None 
        self.package={'id':r[0],'name':r[1],'remark':r[2],'outermost':r[3],'innermost':r[4],'is_biding':r[5]}          
        #2022-06-15 是否有写入carton schema
        if self.infor['carton']:
            t='label.t'+self.infor['carton']     
        cur.execute("select code from "+t+" where id="+str(label_pk_id))
        r=cur.fetchone()        
        
        #2022-05-20 小型企业，套标再绑定，箱瓶可能不在一个表
        if r:
            self.infor['label_pk_code']=r[0]
        else:
            s="select parent_id,parent_code,parent_tb "+\
                "from  label.lbl_rebinding_details where code='"+code+"'"
            cur.execute(s)
            rr=cur.fetchone()
            if rr:
                label_pk_id=rr[0]
                self.infor['label_pk_code']=rr[1]
                self.tb_cross=rr[2]
        cur.execute("select id from inventory_stkdetails where label_pk_id="+str(label_pk_id)+" limit 1")
        r=cur.fetchone()
        if r:
            self.infor['is_active']=True        
        cur.close()        
        return label_pk_id     


    # 2022-06-25
    def get_stack(self):
        stack={}
        pk=str(self.infor['label_pk_id'])        
        if self.package['id']==3:
            cur=self.connection.cursor() 
            s="select s.id,s.code from "+\
                "(select stack_id from inventory_stackdetails where label_pk_id="+pk+") d "+\
                "left outer join "+\
                "(select id,code,parent_id from inventory_stack) s "+\
                "on d.stack_id=s.id"
            cur.execute(s)
            r=cur.fetchone()
            if r:
                stack={'id':r[0],'code':r[1]}
        return stack

    #获取套标关系，目前只考虑箱carton，盒box，瓶bottle 三级对应关系
    #2022-05-20 AB标，跟亮亮确认，肉眼看到的是B标，套标关系一律显示B标
    def get_relations(self):   
        data={'level':0}
        pk=self.infor['label_pk_id']
        if not pk:
            return data   
        pk=str(pk)    
        c=self.infor['wl']
        cur=self.connection.cursor()     
        sA="coalesce((select code_a from label.lbl_abcode where code_a=l.code or code_b=l.code),'')"
        sB="coalesce((select code_b from label.lbl_abcode where code_a=l.code or code_b=l.code),'')"
        sNFC="coalesce((select nfc from label.lbl_nfc where label_code=l.code order by label_code limit 1),'')"   

        # 2022-06-25 是否为垛标
        if self.package['id']==7:            
            data['level']=2
            #取垛内箱标（主箱标) 注意写入垛标明细时用主箱标ID   
            s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                sA+","+sB+","+sNFC+",label_pk_id "+\
                "from "+\
                "(select id,label_code code,(select max(id) from label.lbl_replace_details where code=a.label_code or code0=a.label_code) rid," +\
                    "label_pk_id,label_id "+\
                    "from inventory_stackdetails a where stack_id="+pk+" and is_delete=false"+\
                ") l "+\
                "left outer join "+\
                "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                "on l.rid=r.id"
            cur.execute(s)            
            cartons=[]
            for r1 in cur.fetchall():               
                cartons.append({'label':r1[1],'code0':r1[2],'code':r1[3],'dt_replace':r1[4],'bottlecap':{},'code_a':r1[5],'code_b':r1[6],'color':'','nfc':r1[7],'label_pk_id':r1[8]})  
            data['cartons']=cartons
            data['children']=[]            
            return data    

        #2022-06-16 为不影响以前代码，对跨段，后绑定、再绑定 启用schema cartons  的标签单独处理
        if self.infor['carton']:   
            cartons=[]  
            children=[]    
            code=self.infor['label_pk_code']           
            cur.execute("SELECT level,box_tb,bottle_tb FROM carton.t"+code[:4]+"  where code='"+code+"'")
            r=cur.fetchone()            
            lv=r[0]
            data['level']=lv            
            #先取箱标
            t='label.t'+code[:4]
            s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                sA+","+sB+","+sNFC+" "+\
                "from "+\
                "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid " +\
                    "from "+t+" a where (id="+pk+" or parent_id="+pk+") and package_id=3 order by is_pk desc) l "+\
                "left outer join "+\
                "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                "on l.rid=r.id"
            cur.execute(s)
            rs1=cur.fetchall()        
            for r1 in rs1:
                clr_x=''
                nfc_x=r1[7]
                if c in [ r1[1],r1[2],r1[3],r1[5],r1[6] ]:
                    clr_x='red'
                cartons.append({'label':r1[1],'code0':r1[2],'code':r1[3],'dt_replace':r1[4],'bottlecap':{},'code_a':r1[5],'code_b':r1[6],'color':clr_x,'nfc':nfc_x}) 
            sFw="'' fw_code"
            #箱瓶二级对应
            if lv==2:
                #取瓶标对应关系 一箱的瓶标有可能在多个号段表   
                aLbl=[]
                for lbl in r[2].split(','):
                    aLbl.append("select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid,"+sFw+" "+\
                        "from label.t"+lbl+" a where parent_id="+pk+" and package_id=1")                     
                sLbl=" union all ".join(aLbl)                             
                s="select l.id,coalesce((select code_b from label.lbl_abcode where code_a=l.code or code_b=l.code),l.code),"+\
                    "coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from label.bottlecap where bottle in (r.code0,r.code,l.code) order by dt limit 1),''),"+\
                    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from logistics.z_bottlecap_binding where bottle in (r.code0,r.code,l.code) order by id desc limit 1),''),"+\
                    sA+","+sB+","+sNFC+","+sFw+" "+\
                    "from "+\
                    "(select max(id) id,code,rid,"+sFw+" from ("+sLbl+") u group by code,rid) l "+\
                    "left outer join "+\
                    "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                    "on l.rid=r.id "+\
                    "order by l.code"                
                cur.execute(s)
                rs3=cur.fetchall()            
                for r3 in rs3:
                    cap={'code':''}               
                    if r3[5]:
                        cap={'complete':True,'code':r3[5]}
                    elif r3[6]:
                        cap={'complete':False,'code':r3[6]}  
                    clr_p=''                
                    if r3[1]==c:
                        clr_p='red'   
                    children.append({'label':r3[1],'code0':r3[2],'code':r3[3],'dt_replace':r3[4],'bottlecap':cap,'code_a':r3[7],'code_b':r3[8],'is_bottlecap':False,'fw':r3[10],'color':clr_p,'nfc':r3[9] }) 
            #箱盒瓶三级对应
            elif lv==3:
                #盒标                
                aLbl=[]
                for lbl in r[1].split(','):
                    aLbl.append("select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid,"+sFw+" "+\
                        "from label.t"+lbl+" a where parent_id="+pk+" and package_id=2")                     
                sLbl=" union all ".join(aLbl)  
                s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                    sA+","+sB+","+sNFC+" "+\
                    "from "+\
                    "(select max(id) id,code,rid,"+sFw+" from ("+sLbl+") u group by code,rid) l "+\
                    "left outer join "+\
                    "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                    "on l.rid=r.id"
                cur.execute(s)
                rs2=cur.fetchall()
                for r2 in rs2:
                    
                    h_id=str(r2[0])

                    clr_h=''
                    nfc_h=r2[7]
                    if c in [ r2[1],r2[2],r2[3],r2[5],r2[6] ] :
                        clr_h='red'
                    bottles=[]                  
                    processed=False      
                    aLbl=[]
                    for lbl in r[2].split(','):
                        aLbl.append("select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid,"+sFw+" "+\
                            "from label.t"+lbl+" a where parent_id="+h_id+" and package_id=1")                     
                    sLbl=" union all ".join(aLbl)  
                    s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                        "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from label.bottlecap where bottle in (r.code0,r.code,l.code) order by dt limit 1),''),"+\
                        "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from logistics.z_bottlecap_binding where bottle in (r.code0,r.code,l.code) order by id desc limit 1),''),"+\
                        sA+","+sB+","+sNFC+" "+\
                        "from "+\
                        "(select id,code,rid,"+sFw+" from ("+sLbl+") u group by code,rid,id) l "+\
                        "left outer join "+\
                        "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                        "on l.rid=r.id"
                    cur.execute(s)
                    
                   
                    
                    rs3=cur.fetchall()
                    
                    
                    #瓶标
                    for r3 in rs3:                    
                        clr_p=''
                        cap={'code':''}
                        nfc_p=r3[9]
                        if c in [ r3[1],r3[2],r3[7],r3[8] ]:
                            clr_p='red'                    
                        if r3[5]:                        
                            cap={'complete':True,'code':r3[5]}
                        elif r3[6]:
                            cap={'complete':False,'code':r3[6]}                                          
                        bottles.append({'label':r3[1],'code0':r3[2],'code':r3[3],'dt_replace':r3[4],'bottlecap':cap,'code_a':r3[7],'code_b':r3[8],'color':clr_p,'nfc':nfc_p})                
                    children.append({'label':r2[1],'code0':r2[2],'code':r2[3],'dt_replace':r2[4],'bottlecap':{},'code_a':r2[5],'code_b':r2[6],'children':bottles,'color':clr_h,'nfc':nfc_h})                
            cur.close()
            data['cartons']=cartons
            data['children']=children        
            return data
        else:        
            #2021-12-03
            if self.tb_cross:
                t=self.tb_cross   
            elif self.infor['is_thirdparty']: 
                t="label.thirdparty"
            else:
                t="label.t" +c[:4]    
        #箱标
        s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
            sA+","+sB+","+sNFC+" "+\
            "from "+\
            "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid " +\
                "from "+t+" a where (id="+pk+" or parent_id="+pk+") and package_id=3 order by is_pk desc) l "+\
            "left outer join "+\
            "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
            "on l.rid=r.id"
        cur.execute(s)
        rs1=cur.fetchall()
        cartons=[]  
        children=[]     

        
        for r1 in rs1:
            clr_x=''
            nfc_x=r1[7]
            if c in [ r1[1],r1[2],r1[3],r1[5],r1[6] ]:
                clr_x='red'
            cartons.append({'label':r1[1],'code0':r1[2],'code':r1[3],'dt_replace':r1[4],'bottlecap':{},'code_a':r1[5],'code_b':r1[6],'color':clr_x,'nfc':nfc_x})
        s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
            sA+","+sB+","+sNFC+" "+\
            "from "+\
            "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid " +\
                "from "+t+" a where parent_id="+pk+" and package_id=2"+\
            ") l "+\
            "left outer join "+\
            "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
            "on l.rid=r.id"
        cur.execute(s)
        rs2=cur.fetchall()
        if rs2:            
            data['level']=3  
            #盒标
            for r2 in rs2:
                clr_h=''
                nfc_h=r2[7]
                if c in [ r2[1],r2[2],r2[3],r2[5],r2[6] ] :
                    clr_h='red'
                bottles=[]                  
                processed=False                
                s="select l.id,l.code,coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from label.bottlecap where bottle in (r.code0,r.code,l.code) order by dt limit 1),''),"+\
                    "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from logistics.z_bottlecap_binding where bottle in (r.code0,r.code,l.code) order by id desc limit 1),''),"+\
                    sA+","+sB+","+sNFC+" "+\
                    "from "+\
                    "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid " +\
                        "from "+t+" a where parent_id="+str(r2[0])+" and package_id=1"+\
                    ") l "+\
                    "left outer join "+\
                    "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                    "on l.rid=r.id"
                cur.execute(s)
                rs3=cur.fetchall()
                #瓶标
                for r3 in rs3:                    
                    clr_p=''
                    cap={'code':''}
                    nfc_p=r3[9]
                    if c in [ r3[1],r3[2],r3[7],r3[8] ]:
                        clr_p='red'                    
                    if r3[5]:                        
                        cap={'complete':True,'code':r3[5]}
                    elif r3[6]:
                        cap={'complete':False,'code':r3[6]}                                          
                    bottles.append({'label':r3[1],'code0':r3[2],'code':r3[3],'dt_replace':r3[4],'bottlecap':cap,'code_a':r3[7],'code_b':r3[8],'color':clr_p,'nfc':nfc_p})                
                children.append({'label':r2[1],'code0':r2[2],'code':r2[3],'dt_replace':r2[4],'bottlecap':{},'code_a':r2[5],'code_b':r2[6],'children':bottles,'color':clr_h,'nfc':nfc_h})
        else:    
            #2021-11-29 第三方防伪码，目前只考虑二级对应
            data['level']=2
            sFw="'' fw_code"
            sUnionRebinding="union all select parent_id id,code,null rid,'' fw_code from label.lbl_rebinding_details "+\
                "where parent_id="+pk
            if self.infor['is_thirdparty']: 
                sFw="coalesce(fw_code,'') fw_code"
                sUnionRebinding=""   
            #2022-05-20
            s="select l.id,coalesce((select code_b from label.lbl_abcode where code_a=l.code or code_b=l.code),l.code),"+\
                "coalesce(r.code0,''),coalesce(r.code,''),coalesce(to_char(r.dt,'yyyy-mm-dd'),''),"+\
                "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from label.bottlecap where bottle in (r.code0,r.code,l.code) order by dt limit 1),''),"+\
                "coalesce((select code||' '||to_char(tm,'yyyy-mm-dd hh24:mi:ss') from logistics.z_bottlecap_binding where bottle in (r.code0,r.code,l.code) order by id desc limit 1),''),"+\
                sA+","+sB+","+sNFC+","+sFw+" "+\
                "from "+\
                "(select max(id) id,code,rid,"+sFw+" from "+\
                    "(select id,code,(select max(id) from label.lbl_replace_details where code=a.code or code0=a.code) rid,"+sFw+" "+\
                        "from "+t+" a where parent_id="+pk+" and package_id=1 "+\
                        sUnionRebinding+\
                    ") u "+\
                    "group by code,fw_code,rid "+\
                ") l "+\
                "left outer join "+\
                "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                "on l.rid=r.id "+\
                "order by l.code"       
            cur.execute(s)
            rs3=cur.fetchall()            
            for r3 in rs3:
                cap={'code':''}               
                if r3[5]:
                    cap={'complete':True,'code':r3[5]}
                elif r3[6]:
                    cap={'complete':False,'code':r3[6]}  
                clr_p=''                
                if r3[1]==c:
                    clr_p='red'   
                children.append({'label':r3[1],'code0':r3[2],'code':r3[3],'dt_replace':r3[4],'bottlecap':cap,'code_a':r3[7],'code_b':r3[8],'is_bottlecap':False,'fw':r3[10],'color':clr_p,'nfc':r3[9] })  

            #2022-04-25 诗仙太白 code_a,跨段 箱-箱 159箱
            if self.infor['sup_pk_id']:
                clr=''
                s="select code,"+sA+","+sB+","+sNFC+" "+\
                    "from "+self.infor['sup_pk_id']['tb']+" l where parent_id="+str(self.infor['sup_pk_id']['id'])   
                cur.execute(s)
                for r3 in cur.fetchall():
                    if r3[0]==c:
                        cls='red'
                    cap={'complete':False,'code':''}
                    children.append({'label':r3[0],'code0':'','code':'','dt_replace':'','bottlecap':cap,'code_a':r3[1],'code_b':r3[2],'is_bottlecap':False,'fw':'','color':clr,'nfc':r3[3] })
                #删除159箱 箱-箱 绑定关系里后补关联箱
                #cartons.append({'label':r1[1],'code0':r1[2],'code':r1[3],'dt_replace':r1[4],'bottlecap':r1[5],'code_a':r1[1],'code_b':r1[6]})  
                i=0
                for ct in cartons:                    
                    if ct['label'][:4]=='1044':
                        cartons.pop(i)
                    i=i+1              
            
            #2021-05-03 酒鬼酷客白在线绑定,把米多瓶盖码做为瓶标显示
            if not children:  
                cur.execute("select bottle from label.bottlecap where label_pk_id="+pk)
                rs4=cur.fetchall()                
                if rs4:
                    cap={'complete':True,'code':''}
                    for r4 in rs4:
                        clr=''
                        if r4[0]==c:
                            clr='red'
                        children.append({'label':r4[0],'code0':'','code':'','dt_replace':'','bottlecap':cap,'code_a':'','code_b':'','is_bottlecap':True,'color':clr,'nfc':''})
                else:
                    cur.execute("select bottle from logistics.z_bottlecap_binding where label_pk_id="+pk)
                    rs4=cur.fetchall()  
                    cap={'complete':False,'code':''}
                    for r4 in rs4:
                        clr=''
                        if r4[0]==c:
                            clr='red'
                        children.append({'label':r4[0],'code0':'','code':'','dt_replace':'','bottlecap':cap,'code_a':'','code_b':'','is_bottlecap':True,'color':clr,'nfc':''})
        cur.close()
        data['cartons']=cartons
        data['children']=children        
        return data

    def get_product(self):
        data={'name':'未知','price':'未知','property':[],'id':0,'external_code':'','photo':'','shelf_life':{},'barcode':'',
                'inbound_date':'','inbound_lot':'','inbound_aging':'','inbound_vendor':'','outbound_aging':''}
        pk=self.infor['label_pk_id']
        if not pk:
            return data     
        pk=str(pk)
        cur=self.connection.cursor()
        cur.execute("select ancestor_id from company_company where id="+str(self.company_id))
        r=cur.fetchone()
        aid=str(r[0])     
        
        # 2022-06-25 是否为垛标   
        if self.package['id']==7:            
            s="select s.product_id,coalesce(p.name,''),coalesce(to_char(p.price,'99999.09'),'未知'),p.contents,p.external_code,"+\
                "coalesce(p.photo,''),shelf_life,barcode from "+\
                "(select product_id from inventory_stack where id="+pk+") s "+\
                "left outer join "+\
                "(select id,name,price,coalesce(contents,'') contents,external_code,photo,shelf_life,barcode from product_product where company_id="+aid+") p "+\
                "on s.product_id=p.id"
        else:
            s="select s.product_id,coalesce(p.name,''),coalesce(to_char(p.price,'99999.09'),'未知'),p.contents,p.external_code,"+\
                "coalesce(p.photo,''),shelf_life,barcode from "+\
                "(select coalesce("+\
                        "(select product_id from inventory_stkdetails where company_id="+aid+" "+\
                            "and label_pk_id="+pk+" and vtype_id=1 and is_delete=false order by id limit 1),"+\
                        "(select product_id from inventory_stkdetails where company_id="+aid+" "+\
                            "and label_pk_id="+pk+" and  vtype_id=2 order by id limit 1), "+\
                        "(select product_id from z_bottle_cap_product where id="+\
                            "(select coalesce((select product_id from label.bottlecap where label_pk_id="+pk+" limit 1),"+\
                                "(select product_id from z_bottlecap_binding where label_pk_id="+pk+" limit 1))) "+\
                        ")"+\
                    ") product_id "+\
                ") s "+\
                "left outer join "+\
                "(select id,name,price,coalesce(contents,'') contents,external_code,photo,shelf_life,barcode from product_product where company_id="+aid+") p "+\
                "on s.product_id=p.id  where s.product_id>0"           
        
        cur.execute(s)
        r=cur.fetchone()
        if r: 
            # 2022-06-26 产品ID不为空
            if r[0]:
                data['name']=r[1]
                data['price']=r[2].strip()
                data['id']=r[0]
                data['external_code']=r[4]
                # 2022-07-27
                if r[5]:
                    data['photo']='/media/'+r[5]
                if r[6]:
                    data['shelf_life']=r[6]
                if r[7]:
                    data['barcode']=r[7]
                s="select coalesce(c.value,'') val,g.name,g.desc_cn,coalesce(g.unit,'') from "+\
                    "(SELECT * FROM product_prdprops where product_id="+str(r[0])+") p "+\
                    "left outer join "+\
                    "(SELECT * FROM product_productprop where company_id="+aid+") c "+\
                    "on p.prd_property_id=c.id "+\
                    "left outer join "+\
                    "(select * from company_categoryprop) g "+\
                    "on c.categoryprop_id=g.id"
                cur.execute(s)
                for rr in cur.fetchall():
                    data['property'].append({'desc_cn':rr[2],'unit':rr[3],'value':rr[0]})                
                #2021-08-05 颂恩在产品表添加contents字段，用于存放当前产品的多张图片
                contents=''
                if r[3]:
                    if r[4]:
                        contents=urllib.parse.quote(r[4])
                data['contents']=contents            
                #2022-04-18 取生产批次,采摘日期（入库）,入库日期，供应商           
                s="select coalesce(b.code,b.batch_no),coalesce(b.product_aging,''),"+\
                    "coalesce((select name from mes_vendor where id=vendor_id),''),to_char(b.dt,'yyyy-mm-dd') "+\
                    "from "+\
                    "(select batch_id from inventory_stkdetails where company_id="+aid+" and vtype_id=1 "+\
                        "and is_delete=false and label_pk_id="+pk+" order by id limit 1) d "+\
                    "left outer join "+\
                    "(select id,code,batch_no,product_aging,vendor_id,dt from inventory_batch where company_id="+aid+" and vtype_id=1) b "+\
                    "on d.batch_id=b.id"
                cur.execute(s)
                rr=cur.fetchone()
                if rr:
                    data['inbound_lot']=rr[0]
                    data['inbound_aging']=rr[1]
                    data['inbound_vendor']=rr[2]
                    data['inbound_date']=rr[3]
                #产品年份（内参销售出库）
                s="select coalesce(b.product_aging,'')    from "+\
                    "(select batch_id from inventory_stkdetails where company_id="+aid+" and vtype_id=2 "+\
                        "and is_delete=false and label_pk_id="+pk+" order by id desc limit 1) d "+\
                    "left outer join "+\
                    "(select id,code,batch_no,product_aging from inventory_batch where company_id="+aid+" and vtype_id=2) b "+\
                    "on d.batch_id=b.id"
                cur.execute(s)
                rr=cur.fetchone()
                if rr:
                    data['outbound_aging']=rr[0]  
        cur.close()            
        return data

    #2022-04-18 返回防伪查询信息
    def get_security_info(self):
        aid=str(self.company_id)
        data={"times":0,"image":""}        
        url_internal='http://www.china315net.com:35088/get/codes/from/wuliu/'+aid+'/'
        sK_internal='$internal&GLker5w3jtQLx#'
        #根据物流码取防伪码        
        wl_code=self.infor['wl']
        t = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        m2 = hashlib.md5((sK_internal + t).encode('utf8'))
        key = m2.hexdigest()
        d=[{'id':1,'label':wl_code}]
        r=requests.post(url_internal + '/fw/', json={'key': key, 'time': t, 'labels': d}) 
        if r.status_code==200:
            d = json.loads(r.text)
            fw_code=d['data'][0]['code']        
            url='http://www.china315net.com:35207/tjfw/get/'
            guid=str(uuid.uuid1())
            param={
                'fwcode':fw_code,   #防伪码
                'record':1,         #需要写入查询记录
                'uid':'hand_'+guid,       #用户名，上海汉得
                #'pid':,             #产品ID
                #'cid':1,            #酒鬼酒
                #'package':          #包装
            }
            r=requests.get(url,param) 
            #{
            # "err":错误信息,
            # "img":Base64,
            # "counter":{
            #   "tel":电话查询次数,
            #   "sms":短信查询次数,
            #   "net":网络查询次数
            #  },
            #  "am":暗码,
            #  "wz":文字,
            #  "company":公司名称,
            #  "product":产品名称,
            #  "QueryResult":查询结果,
            #  "CodeState":0出错,1正常,
            #  "history":[前10条查询记录]
            #}
            if r.status_code==200:
                d=json.loads(r.text)
                cnt=d['counter']['net']
                img=d['img']
                data={'times':cnt,'image':img}
        return data



    def get_replaced_labels(self):
        b=[]
        pk=self.infor['label_pk_id']
        if not pk:
            return b
        pk=str(pk)
        c=self.infor['label_pk_code']
        if self.tb_cross:
            tb=self.tb_cross
        elif self.infor['is_thirdparty']:
            tb="label.thirdparty"
        else:
            tb="label.t"+c[:4]

        s="select code from label.lbl_replace_details where code0 in "+\
            "(select code from "+tb+" where id="+pk+" or parent_id="+pk+") "+\
            "group by code"
        cur=self.connection.cursor()
        cur.execute(s)
        for r in cur.fetchall():
            b.append(r[0])
        cur.close()
        return b
    

    def get_stk_dev(self):
        data=[]
        pk=self.infor['label_pk_id']
        if not pk:
            return data
        pk=str(pk)
        
        #2022-07-21
        code=self.infor['code']
        if self.infor['label_a']:
            code=self.infor['label_a']

        # 2022-06-25 是否为垛标
        if self.package['id']==7: 
            return data

        cur=cur=self.connection.cursor()
        cur.execute("select ancestor_id from company_company where id="+str(self.company_id))
        r=cur.fetchone()
        aid=str(r[0])


        # 2022-07-19 同一族系，母公司可以查子公司物流 hierarchy_id
        #100424;"成义烧坊酒业股份有限公司" 111006;"成都成义烧坊电子有限公司"
        #1;"酒鬼酒股份有限公司" 1644;"湖南内参酒销售有限责任公司"        
        hierarchies={
            '1':['1','1644'],                   #酒鬼可查内参
            '100424':['100424','111006'],       #烧坊可查电子
        }
        if str(self.company_id)==aid:
            sAid=" and ancestor_id="+aid
            #if aid=='1':
            #    sAid=" and ancestor_id in (1,1644)"
            if str(self.company_id) in hierarchies:
                sAid=" and ancestor_id in ("+",".join(hierarchies[str(self.company_id)])+")"
        else:
            #经销商可查自己和下级经销商物流
            #sAid=" and company_id="+str(self.company_id)+" or (select parent_id from company_company where id=company_id)="+str(self.company_id) 
            #2022-06-15
            #sAid=" and (company_id="+str(self.company_id)+" and parent_id="+str(self.company_id)+")" 
            # 2022-07-06
            sAid=" and (company_id="+str(self.company_id)+" or (select parent_id from company_company where id=company_id)="+str(self.company_id)+")" 
        
        replaced_labels=self.get_replaced_labels()
        sRep=''
        if replaced_labels:
            sRep=" or label_code in ('"+"','".join(replaced_labels)+"')"
        s="select "+\
            "coalesce((select code_b from label.lbl_abcode where code_a=s.label_code or code_b=s.label_code limit 1),s.label_code),"+\
            "b.code,to_char(s.tm,'yyyy-MM-dd HH24:MI:ss'),"+\
            "(select name from inventory_voucher where id=s.vtype_id),"+\
            "(select name from product_product where id=s.product_id),"+\
            "(select username from company_user where id=b.user_id),"+\
            "(select name from company_company where id=s.company_id),"+\
            "coalesce(c.name,''),"+\
            "coalesce((select name from inventory_storehouse where id=s.store_id),''),"+\
            "coalesce((select name from inventory_storehouse where id=s.store_to_id),''),"+\
            "(select name from label.lbl_package where id=s.label_pkg),"+\
            "coalesce((select code_b from label.lbl_abcode where code_a=s.label_code),''),"+\
            "vtype_id,case when is_delete then 1 else 0 end,"+\
            "coalesce(c.external_code,''),b.id,coalesce(c.address,''),"+\
            "coalesce((select name from gis.adm where id=c.province_gis_id),c.province,''),"+\
            "coalesce((select name from gis.adm where id=c.city_gis_id),c.city,''),"+\
            "s.label_pkg,coalesce(b.rmk_name,'') "+\
            "from "+\
            "(select label_code,label_pkg,company_id,company_to_id,product_id,"+\
                "store_id,store_to_id,batch_id,tm,vtype_id,is_delete FROM inventory_stkdetails "+\
                "where (label_pk_id="+pk+sRep+" or label_code='"+code+"')"+sAid+") s "+\
            "left outer join "+\
            "(select id,code,user_id,rmk_name from inventory_batch) b "+\
            "on s.batch_id=b.id "+\
            "left outer join "+\
            "(select id,name,external_code,address,province,province_gis_id,city,city_gis_id "+\
                "from company_company where ancestor_id="+aid+\
            ") c "+\
            "on s.company_to_id=c.id "+\
            "order by s.tm "
        cur.execute(s)
        #print(s)
        bOut=False #是否需要查询酒鬼酒本地数据库
        for r in cur.fetchall():
            rmk=''
            if r[20]:
                rmk=' '+r[20]
            if r[12]==2:
                bOut=True
            data.append({
                'label_code':r[0],'bill_no':r[1],'tm':r[2],'voucher':r[3],'product':r[4],'user':r[5],'vtype_id':r[12],
                'company':r[6],'customer':r[7]+rmk,'store':r[8],'store_to':r[9],'label_pkg':r[10],"code_b":r[11],'is_delete':r[13],
                'customer_external_code':r[14],'batch_id':r[15],'label_pkg_id':r[19],
                'agent':{'name':r[7],'external_code':r[14],'address':r[16],'province':r[17],'city':r[18]}
            })
        if not bOut and aid=='1': 
            #dd=jiugui_local116(self.infor['label_pk_code']) 
            #2022-03-15 酒鬼酒本地sql svr数据已转入 pg jiugui_local            
            dd=get_jiugui_local(pk)            
            
            for d in dd['stock_dev']:
                data.append({ 
                    #'vtype_id':0,
                    'vtype_id':d['vtype_id'],
                    'label_code':d['label_code'],
                    'bill_no':d['voucher_no'],
                    'tm':d['time'],  
                    'voucher':d['voucher_type'],
                    'product':d['product'],                                  
                    'user':'',                    
                    'company':'酒鬼酒股份有限公司',                    
                    'customer':d['to_company'],
                    'store':d['store'],
                    'store_from':'',
                    'label_pkg':d['package'],
                    'label_pkg_id':3,
                    'code_b':'',
                    'is_delete':0,
                    'agent':{'name':'','external_code':'','address':'','province':'','city':''}
                }) 
                
        #2022-06-18
        elif aid in os_cids:
            ds=os_label_outbound(os_cids[aid],self.infor['label_pk_code'])
            _data = []
            # 循环找出不重复的单号 插入到_data
            for da in data:
                is_repeat = False
                for d in ds:
                    if da['bill_no'] == d['bill_no']:
                        is_repeat = True
                # 如果没有和os产生重复数据
                if not is_repeat:
                    _data.append(da)
                
            for d in ds:
                _data.insert(0,d)      
            data = _data
        cur.close()
        return data










#2021-07-05
@login_required
def get_label_infor(request):
    data={'e':''}
    u=request.user    
    cid=0
    if u.company:
        cid=u.company.id
    c=request.GET.get('code','')    
    q=LabelQuery(cid,c)
    if not q.infor['label_pk_id']:
        data['e']='标签号码错误'
        return JsonResponse(data)
    data['infor']=q.infor
    data['package']=q.package    
    what=request.GET.get('content','all') 

    if what=='relations':
        data['relations']=q.get_relations()
    elif what=='product':
        # 2022-06-25 品控部不能查询产品信息
        if u.id==4:
            data['product']={'name':'未知','price':'未知','property':[],'id':0,'external_code':'','inbound_date':'','inbound_lot':'','inbound_aging':'','inbound_vendor':'','outbound_aging':''}
        else:
            data['product']=q.get_product()
    elif what=='stock_development':
        data['stock_development']=q.get_stk_dev()
    else:   #没有传任何参数，默认，返回全部信息
        # 2022-06-25 品控部不能查询产品信息
        if u.id==4:
            data['product']={'name':'未知','price':'未知','property':[],'id':0,'external_code':'','inbound_date':'','inbound_lot':'','inbound_aging':'','inbound_vendor':'','outbound_aging':''}
        else:
            data['product']=q.get_product()
        data['stock_development']=q.get_stk_dev()   
        if data['stock_development']:               
            data['relations']=q.get_relations()           
        else:         
            if q.package['id']==7:
                data['relations']=q.get_relations() 
            else:    
                #查询的是垛码||五朵金花:27756  号段:9024 || 酒鬼酒套标查询组 || 海南天鉴品控部
                if u.id in [1,2] or (c[:4]=='9024' and cid==27756) or (cid==1  and u.groups.all().filter(id__in=[6,2])) or u.is_staff  or q.infor['is_thirdparty'] or q.infor['label_company_id']==q.company_id:
                    data['relations']=q.get_relations() 
                    data['relations']=q.get_relations() 
                else:
                    #data['e']='标签号码未激活'
                    data['e']='暂无物流数据'
                    data['relations']=[]      
    return JsonResponse(data)



@tj_login_required
@csrf_exempt
def kangnian_activation_page(request):
    if request.method == 'GET':
        return render(request, 'kangnian/activation.html', {})
         


#2021-08-18 扫码枪卷标在线绑定接口
@csrf_exempt
def label_binding(request,company_id,action): 
    rmk='扫码枪卷标在线绑定'
    #rmk='测试'    
    data={'e':'','warning':'','bottles':0,'bound':0}
    k = sK   
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    
    #瓶盖实时绑定数据存放的表名
    tb_cap='logistics.z_bottlecap_binding'
    #连接REDIS数据库,指定db10
    rd=redis.StrictRedis(host='localhost', port=settings.RD['port'], db=10, password=settings.RD['password'], decode_responses=True) 

    #是否为盖码，是否为临时标，扫码枪已做判断，接口不再做判断
    #process_id  1:瓶盖临时标 2:盒与临时标 3:扫箱码检查       
    
    #tmp=request.GET.get('temp','')
    #lbl=request.GET.get('label','')
    product=request.GET.get('product','')
    
    #2020-11-11
    pid=request.GET.get('product_id','')
    
    line=request.GET.get('line','')
    user=request.GET.get('user','0')
    batch_no=request.GET.get('batch_no','').upper()

    #2021-06-21    
    store_id=request.GET.get('store_id','null')
    qc=request.GET.get('qc','null')
    if qc!='null':
        qc="'"+qc+"'"

    #if process_id in ['1','2']:        
    #    if len(tmp)!=12 or len(lbl)!=12:
    #        data['e']='标签号码和临时标长度不正确'
    #        return JsonResponse(data)

    tm=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')    

    cur=connection.cursor()

    #只有瓶盖-临时标在REDIS设置键值对
    prfx='online_'+company_id+'_'
    #tmp=prfx+tmp
    #为提高效率，不考虑套标跨段，且只有箱/瓶二级套标关系
    #tb='label.t'+lbl[:4]  
    if action=='bindcap':     #瓶标-盖码    
        bottle=request.GET.get('bottle','')
        cap=request.GET.get('bottlecap','')
        if not bottle or not cap:
            data['e']='盒标和瓶盖码不能为空'
            return JsonResponse(data)       

        tmp=prfx+bottle
        #2021-03-19
        s="select to_char(tm,'yyyy-mm-dd HH24:MM:SS'),box_code,bottle,product,label from "+tb_cap+" where label='"+cap+"' or bottle='"+bottle+"'"
        cur.execute(s)
        r=cur.fetchone()
        if r:
            prd=''
            if r[3]:
                prd='('+r[3]+')'
            data['e']='盖码或盒标已绑定过,'+r[0]+'箱:'+r[1]+',盒码:'+r[2]+',盖码:'+r[4]+'('+prd+')'
        else:
            o=rd.hgetall(tmp)        
            if o:
                if o['label']!=bottle:                    
                    data['warning']='此临时标已于'+o['time']+'与盖码绑定过,现绑定为新盖码'       
            rd.hmset(tmp,{'label':cap,'product':product,'line':line,'user':user,'time':tm,'batch_no':batch_no})
    
    elif action=='checkcarton':   #检查箱标绑定过         
        carton=request.GET.get('carton','')
        if not carton:
            data['e']='carton 箱标不能为空'
            return JsonResponse(data)
        cur.execute("select tbname FROM label.lbl_tbcross where  segment='"+carton[:4]+"'")
        r=cur.fetchone()
        if r:
            tb=r[0]
            s="select to_char(tm,'yyyy-mm-dd HH24:MM:SS') from label."+tb+" where code='"+carton+"'"
            cur.execute(s)
            r=cur.fetchone()
            if r:    
                data['e']='此箱标已绑定过 '+r[0]
        else:
            data['e']='箱标不属于跨段后绑定号段范围'
        return JsonResponse(data)
    
    
    elif action=='checkcap':   #瓶标盖码检查 
        data['bottlecap']=''
        bottle=request.GET.get('bottle','')
        if not bottle:
            data['e']='bottle 盒码不能为空'
            return JsonResponse(data)
        tmp=prfx+bottle
        #2021-03-19
        s="select to_char(tm,'yyyy-mm-dd HH24:MM:SS'),box_code,bottle,product,label from "+tb_cap+" where bottle='"+bottle+"'"
        cur.execute(s)
        r=cur.fetchone()
        if r:
            prd=''
            if r[3]:
                prd='('+r[3]+')'
            data['e']='此盒标已绑定过,'+r[0]+' 箱:'+r[1]+',盒码:'+r[2]+',盖码:'+prd
        else:
            o=rd.hgetall(tmp)        
            if o:                      
                data['bottlecap']=o['label']
            else:                
                data['e']=bottle+' 此盒末绑定盖码'
        return JsonResponse(data)
        
    elif action=='upload': #上传绑定好的套标数据        
        d=json.loads(request.body)
        if 'product_id' not in d or 'line' not in d or 'user' not in d or 'batch_no' not in d or 'store_id' not in d or 'qc' not in d or 'relations' not in d:
            data['e']="parameters of procut_id,line,user,batch_no,store_id,qc,data required"
            return JsonResponse(data)        
        rls=d['relations']
        if len(rls['cartons'])==0:
            data['e']="主箱标不能为空"
            return JsonResponse(data)
        else:
            pk_code=rls['cartons'][0]
        #cur.execute("select tbname FROM label.lbl_tbcross where segment='"+rls['cartons'][0][:4]+"'")
        #r=cur.fetchone()
        #if not r:
        #    data['e']='箱标不属于跨段后绑定号段范围'
        #    return JsonResponse(data)        
        
        
        pid=str(d['product_id']) 
        line=d['line'] 
        user=str(d['user']) 
        batch=d['batch_no'].upper()        
        store_id=str(d['store_id']) 
        qc=d['qc']

        if len(rls['cartons'])>1:
            if rls['cartons'][0]==rls['cartons'][1]:
                data['e']="主箱标与关联标不能相同"
                return JsonResponse(data)
        cur.execute("select product_name,bottle_cnt,box_cnt,carton_cnt FROM z_bottle_cap_product where id="+pid)
        r=cur.fetchone()
        if r:
            prd=r[0]
            bottle_cnt=str(r[1])    #1箱几个瓶标
            box_cnt=str(r[2])       #1箱几个盒标
            carton_cnt=str(r[3])    #1箱几个箱标 
        else:
            data['e']='产品ID不存在'    
            return JsonResponse(data)        

        #卷标跨段表名
        tb_cross='label.lbl_binding_jg'    

        

        
        #tb_range='label.t'+rls['cartons'][0]
        #s="select arrary_to_string(array("+\
        #        "select code from "+tb_range+" where code in ('"+"','".join(rls['cartons'])+"') "+\
        #        "union "+\
        #        "select code from "+tb_cross+" where code in ('"+"','".join(rls['cartons'])+"') "+\
        #    "),',')"    
        #s="select array_to_string(array("+\
        #        "select code from "+tb_cross+" where code in ('"+"','".join(rls['cartons'])+"') "+\
        #    "),',')"    
        #cur.execute(s)        
        #r=cur.fetchone()
        #if r:
        #    if r[0]:
        #        data['e']="箱码"+r[0]+"已存在绑定关系"
        #        return JsonResponse(data)            
        
        
        #跨段标签基础数据表插入主箱标
        s="INSERT INTO "+tb_cross+"(code,package_id,category_id,parent_id,is_pk,is_related,is_active,type_id)  VALUES "+\
            "('"+rls['cartons'][0]+"',3,1,null,true,false,true,2) returning id"
        try:
            cur.execute(s)
        except IntegrityError:
            s="INSERT INTO z_bottlecap_binding_err(type,remark,company_id,product,prd_line,username,"+\
                "bottles_cnt,batch_no,binding_type,store_id,qc,contents)  values "+\
                "(999,'箱码"+rls['cartons'][0]+"已存在绑定关系',"+company_id+",'"+prd+"','"+line+"','"+user+"',"+\
                    bottle_cnt+",'"+batch+"',2,"+store_id+",'"+qc+"','"+json.dumps(rls)+"')"
            cur.execute(s)
            data['e']='箱码'+rls['cartons'][0]+"已存在绑定关系"
            return JsonResponse(data)

        r = cur.fetchone()
        pk_id = str(r[0])
        if len(rls['cartons'])==2:
            #跨段标签基础数据表插入主箱标
            s="INSERT INTO "+tb_cross+"(code,package_id,category_id,parent_id,is_pk,is_related,is_active,type_id)  VALUES "+\
                "('"+rls['cartons'][1]+"',3,1,"+pk_id+",false,true,true,2)"
            try:
                cur.execute(s)            
            except IntegrityError:
                s="INSERT INTO z_bottlecap_binding_err(type,remark,company_id,product,prd_line,username,"+\
                    "bottles_cnt,batch_no,binding_type,store_id,qc,contents)  values "+\
                    "(999,'箱码"+rls['cartons'][1]+"已存在绑定关系',"+company_id+",'"+prd+"','"+line+"','"+user+"',"+\
                        bottle_cnt+",'"+batch+"',2,"+store_id+",'"+qc+"','"+json.dumps(rls)+"')"
                cur.execute(s)
                data['e']='箱码'+rls['cartons'][1]+"已存在绑定关系"
                return JsonResponse(data)

        a_rg=[]
        a_bd=[]
        s_bd="INSERT INTO "+tb_cap+"(label,code,bottle,type,remark,company_id,product,prd_line,username,label_pk_id,"+\
                "box_code,bottles_cnt,batch_no,product_id,binding_type,store_id,qc) values "
        s_rg="INSERT INTO "+tb_cross+"(code,package_id,category_id,parent_id,is_pk,is_related,is_active,type_id)  VALUES "       

        #目前只考虑箱-瓶二级绑定关系 
        if box_cnt=='0':                
            for b in rls['bottles']:
                #{'bottle':盒标1, 'bottlecap':盖码1},
                b_label=b['bottlecap']
                b_code=decrypt_11h(b_label)
                bt=b['bottle']
                a_bd.append("('"+b_label+"','"+b_code+"','"+bt+"',999,'在线绑定',"+company_id+",'"+prd+"','"+line+"','"+user+"',"+pk_id+","+\
                    "'"+pk_code+"',"+bottle_cnt+",'"+batch+"',"+pid+",2,"+store_id+",'"+qc+"')")
                a_rg.append("('"+bt+"',1,1,"+pk_id+",false,false,true,2)")  
            try:                
                cur.execute(s_rg+",".join(a_rg)) 
            except IntegrityError:
                s="INSERT INTO z_bottlecap_binding_err(type,remark,company_id,product,prd_line,username,"+\
                    "bottles_cnt,batch_no,binding_type,store_id,qc,contents)  values "+\
                    "(999,'盒标内有标签已绑定',"+company_id+",'"+prd+"','"+line+"','"+user+"',"+\
                        bottle_cnt+",'"+batch+"',2,"+store_id+",'"+qc+"','"+json.dumps(rls)+"')"                
                cur.execute(s)
                data['e']='盒标内有标签已绑定'
                return JsonResponse(data)              
            cur.execute(s_bd+",".join(a_bd))
        #delete redis's data
        for b in rls['bottles']:
            rd.delete('online_'+company_id+'_'+b['bottle'])
        return JsonResponse(data)     

    #2022-05-23
    elif action=='nfc_binding': #上传绑定好的套标数据
        #2022-05-23 扫码枪NFC绑定上传，指定JSON格式,不考虑企业的标签替换
        d=json.loads(request.body)
        #用户ID必传
        user_id=str(d['user_id'])
        product_id='null'
        if 'product_id' in d:
            product_id=str(d['product_id'])
        store_id='null'
        if'store_id' in d:
            store_id=str(d['store_id'])
        plant_id='null'
        if 'plant_id' in d:
            plant_id=str(d['plant_id'])
        batch_no='null'
        if 'batch_no' in d:
            batch_no="'"+d['batch_no']+"'"
        prd_line='null'
        if 'line' in d:
            prd_line="'"+d['line']+"'"
        prd_team='null'
        if 'team' in d:
            prd_team="'"+d['team']+"'"
        qc='null'
        if 'qc' in d:
            qc="'"+d['qc']+"'"        
        #写入BATCH    
        s="INSERT INTO z_labelnfc_batch("+\
            "company_id,product_id,user_id,prd_plant_id,store_id,"+\
            "batch_no,prd_line,prd_team,qc "+\
            ") values ("+\
            company_id+","+product_id+","+user_id+","+plant_id+","+store_id+","+\
            batch_no+","+prd_line+","+prd_team+","+qc+\
            ") returning id"
        cur.execute(s)
        r = cur.fetchone()
        batch_id=str(r[0])  
        #写入nfc绑定明细
        a=[]
        for dd in d['details']:
            tm=dd['time']
            dt=tm[:10]
            lbl=dd['label']           
            nfc=dd['nfc']
            cd=lbl[-12:]
            #确认AB标扫码枪只上传B标，即物流标
            a.append("("+batch_id+","+company_id+",'"+lbl+"','"+cd+"','"+nfc+"','"+tm+"','"+dt+"')")
        #防止传数据量过大，每次插入1000条记录
        cnt=0
        for j in range(0,len(a),1000):  
            s="INSERT INTO z_labelnfc_details("+\
                "batch_id,company_id,label,code,nfc,tm_binded,dt_binded) values "+\
                ",".join( a[j:j+1000] )
            cur.execute(s)
            cnt=cnt+cur.rowcount    
        #AB标不能排除扫码枪传B标到服务器，此处label_code转换成A标
        s="update z_labelnfc_details set label_code="+\
            "coalesce((select code_a from label.lbl_abcode where code_b=code),code) "+\
            "where batch_id="+batch_id
        cur.execute(s)
        #根据号段取标签ID,主箱标ID,标签类型。
        s="update z_labelnfc_details set tb=coalesce("+\
            "(SELECT tbname FROM label.lbl_tbcross where segment=left(label_code,4)),'t'||left(label_code,4))"
        cur.execute(s)
        s="select tb from z_labelnfc_details where batch_id="+batch_id+" group by tb"
        cur.execute(s)
        rs=cur.fetchall()
        for rr in rs:
            tb=rr[0]            
            cur.execute("select count(*) from information_schema.tables where table_schema='label' "+\
                "and table_type='BASE TABLE' and  table_name='"+rr[0]+"'" )            
            r0 = cur.fetchone()        
            if r0[0]:            
                s="update z_labelnfc_details d set "+\
                    "label_id=b.id,"+\
                    "label_pkg=b.package_id,"+\
                    "label_pk_id=coalesce(b.parent_id,b.id) "+\
                    "from "+\
                    "(SELECT id,label_code from z_labelnfc_details where batch_id="+batch_id+" and tb='"+tb+"') a "+\
                    "left outer join "+\
                    "(select id,code,parent_id,package_id,is_pk from label."+tb+") b "+\
                    "on a.label_code=b.code "+\
                    "where batch_id="+batch_id+" and tb='"+tb+"' and d.id=a.id"                
                cur.execute(s)
        #将写入的明细group去重后,写入标签库  注:如果有重复绑定,以最后绑定时间的记录为准    
        s="INSERT INTO label.lbl_nfc(company_id,label_code,nfc,label_pk_id,label_id,label_pkg) select "+\
            company_id+",d.label_code,d.nfc,d.label_pk_id,d.label_id,d.label_pkg "+\
            "from "+\
            "(select gg.label_code,gg.tm,"+\
                "(select max(id) from z_labelnfc_details where batch_id="+batch_id+" and label_code=gg.label_code and tm_binded=gg.tm) id "+\
                "from (select label_code,max(tm_binded) tm from z_labelnfc_details where batch_id="+batch_id+" group by label_code) gg "+\
            ") g "+\
            "left outer join "+\
            "(select id,nfc,label_code,label_id,label_pk_id,label_pkg from z_labelnfc_details where batch_id="+batch_id+") d "+\
            "on g.id=d.id "+\
            "on conflict (nfc) do update set label_code=EXCLUDED.label_code"            
        cur.execute(s)
        data={'e':'','cnt':cnt}    

    cur.close()
    return JsonResponse(data)

    




    



#对指定公司做指定月份期结操作 yr,mn 年份月份：整型
def do_closing(company_id,user_id,yr,mn,redo=False,prv_cls_id=None):
    cid=str(company_id)
    uid=str(user_id)
    data={'e':'','closing_id':None}     
    #会计期 第1天 最后一天（字符串)
    dt1=datetime.date(yr,mn,1).strftime('%Y-%m-%d')
    dt2=datetime.date(yr,mn,calendar.monthrange(yr,mn)[1]).strftime('%Y-%m-%d')
    cur=connection.cursor()
    cur.execute("select ancestor_id from company_company where id="+cid)
    r=cur.fetchone()
    aid=str(r[0])
    #当前会计期是否已做期结
    s="select id,(select username from company_user where id=user_id),"+\
        "to_char(tm_edit,'yyyy-mm-dd HH24:MI:SS') from inventory_stkclosingperiod where company_id="+cid+" and dt_fr='"+dt1+"' and dt_to='"+dt2+"'"
    cur.execute(s)
    r=cur.fetchone()
    if r: 
        cls_id=str(r[0]) 
        if redo:    #已做过期结，但要求重新期结
            id=str(r[0])   
            #删除当期变动明细
            cur.execute("delete from inventory_stkclosingperioddetails where stkclosing_id="+id)
            #删除当期期末明细
            cur.execute("delete from inventory_stkclosingdetails where stkclosing_id="+id)            
            #修改会计期 操作员 时间
            cur.execute("update inventory_stkclosingperiod set user_id="+uid+",tm_edit=now() where id="+cls_id)
        else:
            data['e']="期计期 "+str(yr)+"年"+str(mn)+"月 已做结期("+r[1]+" "+r[2]+")"
            return data
    else:
        s="INSERT INTO inventory_stkclosingperiod(ancestor_id,company_id,user_id,yr,mn,dt_fr,dt_to) select "+\
            aid+","+cid+","+str(uid)+","+str(yr)+","+str(mn)+",'"+dt1+"','"+dt2+"' returning id"
        cur.execute(s)
        r = cur.fetchone()
        cls_id=str(r[0])   

    #2021-10-22
    #当期变动明细
    s="INSERT INTO inventory_stkclosingperioddetails(stkclosing_id,product_id,vtype_id,store_id,store_fr_id,"+\
        "label_pk_id,label_code,label_pkg,qty_tt,qty_act,qty_adj) select "+cls_id+","+\
        "product_id,vtype_id,store_id,store_fr_id,label_pk_id,label_code,label_pkg,cnt,case when cnt>0 then 1 else 0 end,"+\
        "case when cnt>0 then 1 else 0 end-cnt from "+\
        "(select product_id,vtype_id,store_id,store_fr_id,label_pk_id,min(label_code) label_code,label_pkg,count(*) cnt "+\
            "from inventory_stkdetails where company_id="+cid+" and is_delete=false and (dt between '"+dt1+"' and '"+dt2+"') "+\
            "group by product_id,vtype_id,store_id,store_fr_id,label_pk_id,label_pkg"+\
        ") g "
    cur.execute(s)

    #期末明细
    sPrv=""    
    if prv_cls_id:
        sPrv=" union all "+\
            "select product_id,store_id,label_pk_id,label_code,label_pkg,qty_act cnt from inventory_stkclosingstkdetails "+\
            "where company_id="+cid+" and stkclosing_id="+str(prv_cls_id)     
    s="INSERT INTO inventory_stkclosingdetails(ancestor_id,company_id,stkclosing_id,"+\
        "store_id,product_id,label_pk_id,label_code,label_pkg,qty_tt,qty_adj,qty_act) "+\
        "select "+aid+","+cid+","+cls_id+","+\
        "store_id,product_id,label_pk_id,min(label_code),label_pkg,sum(cnt),"+\
        "case when sum(cnt)>0 then 1 else 0 end-sum(cnt),case when sum(cnt)>0 then 1 else 0 end "+\
        "from "+\
        "(select product_id,store_id,label_pk_id,label_code,label_pkg,"+\
            "(select direction from inventory_voucher where id=vtype_id) cnt "+\
            "from inventory_stkdetails where company_id="+cid+" and is_delete=false "+\
            "and vtype_id in (1,2,4) and (dt between '"+dt1+"' and '"+dt2+"')  "+\
            "union all "+\
            "select product_id,store_id,label_pk_id,label_code,label_pkg,"+\
            "1 cnt "+\
            "from inventory_stkdetails where company_id="+cid+" and is_delete=false "+\
            "and vtype_id=3 and (dt between '"+dt1+"' and '"+dt2+"')  "+\
            "union all "+\
            "select product_id,store_fr_id store_id,label_pk_id,label_code,label_pkg,"+\
            "-1 cnt "+\
            "from inventory_stkdetails where company_id="+cid+" and is_delete=false "+\
            "and vtype_id=3 and (dt between '"+dt1+"' and '"+dt2+"') "+\
        ") d "+\
        "group by store_id,product_id,label_pk_id,label_pkg having sum(cnt)>0"
    cur.execute(s)    
    sPrv=""    
    if prv_cls_id:
        sPrv=" union all "+\
            "select label_pk_id,label_code,product_id,store_id,label_pkg,1 direction from inventory_stkclosingstkdetails "+\
            "where company_id="+cid+" and stkclosing_id="+str(prv_cls_id)             
    s="INSERT INTO inventory_stkclosingdetails(ancestor_id,company_id,stkclosing_id,"+\
        "label_pk_id,label_code,label_pkg,product_id,store_id,qty_tt,qty_adj,qty_act) "+\
        "select "+aid+","+cid+","+cls_id+","+\
        "label_pk_id,min(label_code),label_pkg,product_id,store_id,sum(direction),1-sum(direction),1 "+\
        "from "+\
        "(select label_pk_id,label_code,product_id,store_id,label_pkg,"+\
            "(select direction from inventory_voucher where id=vtype_id) direction from inventory_stkdetails "+\
            "where company_id="+cid+" and is_delete=false and (dt between '"+dt1+"' and '"+dt2+"')"+sPrv+\
        ") d "+\
        "group by label_pk_id,label_code,product_id,store_id,label_pkg having sum(direction)>0"
    cur.execute(s)      

    #设置公司当前会计期
    cur.execute("select id from inventory_stkclosingcurrent where company_id="+cid)
    r=cur.fetchone()
    if r:        
        s="update inventory_stkclosingcurrent set stkclosing_id="+cls_id+",user_id="+uid+" "+\
            "where id="+str(r[0])
    else:
        s="insert into inventory_stkclosingcurrent(ancestor_id,company_id,stkclosing_id,dt0,user_id) select "+\
            aid+","+cid+","+cls_id+",(select min(dt) from inventory_batch where company_id="+cid+"),"+uid
    cur.execute(s)   
    
    #2022-06-01 返回已期结的会计期
    data['closing_id']=int(cls_id)
    return data


#库存期结
def period_closing(user_id,company_id,yr,mn,recursive=False,redo=False):
    data={'e':''}
    cid=str(company_id)
    uid=str(user_id)    
    td=datetime.date.today()
    y=td.year
    m=td.month

    #本月 第1天（日期型)
    dt1=datetime.date(y,m,1)
    #dt2=datetime.date(y,m,calendar.monthrange(y,m)[1])    
    prv_lst=dt1-datetime.timedelta(1)
    #上月 第1天 最后一天 (字符串）
    prv_dt1=datetime.date(prv_lst.year,prv_lst.month,1).strftime('%Y-%m-%d')
    prv_dt2=lst.strftime('%Y-%m-%d')      
    
    cur=connection.cursor()
    #取上月期结会计期id
    prv_cls_id=None
    s="select c.stkperiod_id from "+\
        "(select dt0,stkperiod_id from inventory_stkclosingcurrent where company_id="+str(cid)+") c "+\
        "left outer join "+\
        "(select id,yr,mn from inventory_stkclosingperiod where company_id="+str(cid)+" and dt_fr='"+prv_dt1+"' and dt_to='"+prv_dt2+"') s "+\
        "on c.stkperiod_id=s.id"
    cur.execute(s)
    r=cur.fetchone()
    if r:
        if r[0]:
            #has_set_period=True
            prv_cls_id=r[0]
    
    if prv_cls_id:
        cur_prvdt1=prv_dt1
    #上月未做期结
    else:
        if not recursive:
            data['e']='上期未做期结'
            cur.close()
            return data        
        else:  #需要逐期期结
            s="select (select dt_fr from inventory_stkclosingperiod where id=stkclosing_id) from inventory_stkclosingcurrent where company_id="+cid            
            cur.execute(s)
            r=cur.fetchone()
            if r:
                #has_set_period=True
                dt0=r[1]
            if redo:
                #从最早发货日期到现在
                #取物流数据最早日期
                cur.execute("select min(dt) from inventory_batch where company_id="+str(cid))
                r=cur.fetchone()
                if not r:
                    data['e']="没有发现任何物流数据"
                    return data
                dt0=r[0]
            cur_prvdt1=datetime.date(dt0.year,dt0.month,1)    
    while cur_prvdt1<prv_dt1:
        do_closing(cid,uid,cur_prvdt1.year,cur_prvdt1.month,redo,prv_cls_id)
        cur_prvdt1=cur_prvdt1+datetime.timedelta(months=1)
    #期结当月
    do_closing(cid,uid,yr,mn,redo,cur_prvdt1)
    
        

    return data


#2021-10-20
@csrf_exempt
def stk_close(request):
    data = {'e':''}
    r=json.loads(request.body)
    
    
    

    if request.user.is_authenticated:
        uid=request.user.id
        cid=request.user.company.id
    else:
        k = sK
        e = time_key_check(request, k)
        if e:
            data['e'] = e
            return JsonResponse(data)
        cid=r['company_id']
        uid=r['user_id']
    
    yr=int(r['year'])
    mn=int(r['month'])
    prv_cls_id=None
    redo=False
    if 'prv_cls_id' in r:
        if r['prv_cls_id']:
            prv_cls_id=r['prv_cls_id']
    if 'redo' in r:
        if r['redo']:
            redo=True
    d=do_closing(cid,uid,yr,mn,redo,prv_cls_id)
    data['e']=d['e']   
    return JsonResponse(data)



@login_required
def stock_report(request,what):
    years=[]
    dt=datetime.datetime.now()
    u=request.user
    c=u.company
    cid=str(c.id)   

    cur=connection.cursor()
    if what=='preclose':
        return render(request,'inventory/stock/report/'+what+'.html')
    elif what=='preclose_data':
        data={'periods':[],'to_close':0}
        to_close=False
        cur.execute("select id,yr,mn,to_char(tm,'yyyy-mm-dd HH24:MI:SS')||' '||(select username from company_user where id=user_id),dt_fr,dt_to "+\
            "from inventory_stkclosingperiod where company_id="+cid+" order by id desc")
        rs=cur.fetchall()
        r0=rs[0]
        for r in rs:
            data['periods'].append([ r[0],str(r[1])+'年'+str(r[2])+'月',r[4].strftime('%Y-%m-%d'),r[5].strftime('%Y-%m-%d'),r[3] ])
        
        if dt.year>r0[1]:
            to_close=True
        else:
            if dt.month-r0[2]>1:
                to_close=True      
        if to_close:
            data['to_close']=1
            dt1=r0[5]+datetime.timedelta(days=1)
            dt2=datetime.date(dt1.year,dt1.month,calendar.monthrange(dt1.year,dt1.month)[1])
            data['periods'].append([0,str(dt1.year)+'年'+str(dt1.month)+'月',dt1.strftime('%Y-%m-%d'),dt2.strftime('%Y-%m-%d'),
                '<button class="btn btn-xs btn-primary" yr="'+str(dt1.year)+'" mn="'+str(dt1.month)+'">期结</button>' ])  
        return JsonResponse(data)          


    elif what=='development':
        #cid='19318'
        cy=0
        cm=0
        show_close=False
        cur.execute("select min(yr),max(id) from inventory_stkclosingperiod where company_id="+cid)
        r=cur.fetchone()
        if r[0]:
            y=r[0]
            while y<=dt.year:
                years.append(y)
                y=y+1            
            s="select yr,mn from inventory_stkclosingperiod where id="+str(r[1])
            cur.execute(s)
            r=cur.fetchone()
            cy=r[0]
            cm=r[1]
            if dt.year>cy:
                show_close=True
            else:
                if dt.month>cm:
                    show_close=True
        else:
            show_close=True

        return render(request,'inventory/stock/report/'+what+'.html',
            {'years':years,'month':dt.month,'show_close':False,'last_period':{'year':cy,'month':cm}})




@login_required
def ajax_stock_report_new(request,what):
    data={'e':'','clmns':[],'data':[]}   
    cid=str(request.user.company_id)  
    td=datetime.datetime.now()
    yr=request.GET.get('year',str(td.year))
    mn=request.GET.get('month',str(td.month))
    dt1=datetime.date(int(yr),int(mn),1)    
    dt2=datetime.date(int(yr),int(mn),calendar.monthrange(int(yr),int(mn))[1])

    prv_lst=dt1-datetime.timedelta(1)
    #上月 第1天 最后一天 (字符串）
    prv_dt1=datetime.date(prv_lst.year,prv_lst.month,1).strftime('%Y-%m-%d')
    prv_dt2=prv_lst.strftime('%Y-%m-%d')  

    sAnd=''    
    store_id=request.GET.get('store_id','')    
    product_id=request.GET.get('product_id','')   
    if store_id:
        sAnd=sAnd+" and g.store_id="+store_id
    if product_id:
        sAnd=sAnd+" and g.product_id="+product_id    

    cur=connection.cursor()      
    #本期及上期期结ID    
    prv_cls_id='0'
    s="select (select id from inventory_stkclosingperiod where company_id="+cid+" and yr="+yr+" and mn="+mn+"),"+\
        "(select id from inventory_stkclosingperiod where company_id="+cid+" and dt_fr='"+prv_dt1+"' and dt_to='"+prv_dt2+"')"
    cur.execute(s)
    r=cur.fetchone()         
   
    #查询在期结范围内
    if r[0]:             
        if r[1]:
            prv_cls_id=str(r[1])        
    #查询不在期结范围内
    else:              
        #公司最后一次期结
        s="select id,dt_fr FROM inventory_stkclosingperiod where id="+\
            "(select max(stkclosing_id) from inventory_stkclosingcurrent where company_id="+cid+")"
        cur.execute(s)
        r=cur.fetchone()
        if r:
            ds=(dt1-r[1]).days    
            if ds<0:
                data['e']='查询会计期早于最早期结日期'            
            elif ds>31:
                data['e']='查询会计期尚末期结，请期结后再做查询'
            else:                
                #查询的是最后期结1个月内库存数据
                prv_cls_id=str(r[0])                
                sWhere=" where company_id="+cid+" and is_delete=false and label_pkg=3 "+\
                    "and (dt between '"+dt1.strftime('%y-%m-%d')+"' and '"+dt2.strftime('%y-%m-%d')+"')"
        else:
            data['e']='从末做过库存期结，请期结后再做查询'    
    if data['e']:
        return JsonResponse(data)   

    dt1=dt1.strftime('%y-%m-%d')
    dt2=dt2.strftime('%y-%m-%d')
    data['clmns']=['产品名称','仓库名称','期初库存','成品入库','销售出库','销售退库','标签退库','转入','转出','期末库存']
    sTbOpen='inventory_stkclosingtt'
    sTbStk='inventory_stkdetails'    
    sWhere=" where company_id="+cid+" and label_pkg=3 and (dt between '"+dt1+"' and '"+dt2+"')"
    #库存变动表
    s="select (select name from product_product where id=g.product_id) product,"+\
        "coalesce((select name from inventory_storehouse where id=g.store_id),'') store,"+\
        "coalesce(p.qty,0),coalesce(i.qty,0),coalesce(s.qty,0),coalesce(t.qty,0),coalesce(b.qty,0),coalesce(zi.qty,0),coalesce(zo.qty,0),"+\
        "coalesce(p.qty,0)+coalesce(i.qty,0)-coalesce(s.qty,0)+coalesce(t.qty,0)-coalesce(b.qty,0)+coalesce(zi.qty,0)-coalesce(zo.qty,0),"+\
        "g.product_id,g.store_id from "+\
        "(select product_id,store_id from "+\
            "(select product_id,store_id from "+sTbOpen+" where stkclosing_id="+str(prv_cls_id)+" "+\
                "union all "+\
                "select product_id,store_id from "+sTbStk+sWhere+" group by product_id,store_id "\
                "union all "+\
                "select product_id,store_fr_id store_id from "+sTbStk+sWhere+" and vtype_id=3 "+\
                    "group by product_id,store_fr_id"+\
            ") u "+\
            "group by product_id,store_id"+\
        ") g "+\
        "left outer join "+\
        "(select product_id,store_id,sum(qty) qty from "+sTbOpen+" where stkclosing_id="+str(prv_cls_id)+" "+\
            "group by product_id,store_id) p "+\
        "on g.product_id=p.product_id and g.store_id=p.store_id "+\
        "left outer join "+\
        "(select product_id,store_id,count(*) qty  from "+sTbStk+sWhere+" and vtype_id=1 "+\
            "group by product_id,store_id) i "+\
        "on g.product_id=i.product_id and g.store_id=i.store_id "+\
        "left outer join "+\
        "(select product_id,store_id,count(*) qty  from "+sTbStk+sWhere+" and vtype_id=2 "+\
            " group by product_id,store_id) s "+\
        "on g.product_id=s.product_id and g.store_id=s.store_id "+\
        "left outer join "+\
        "(select product_id,store_id,count(*) qty from "+sTbStk+sWhere+" and vtype_id=4 "+\
            " group by product_id,store_id) t "+\
        "on g.product_id=t.product_id and g.store_id=t.store_id "+\
        "left outer join "+\
        "(select product_id,store_id,count(*) qty from "+sTbStk+sWhere+" and vtype_id=5 "+\
            " group by product_id,store_id) b "+\
        "on g.product_id=b.product_id and g.store_id=b.store_id "+\
        "left outer join "+\
        "(select product_id,store_id,count(*) qty from "+sTbStk+sWhere+" and vtype_id=3 "+\
            " group by product_id,store_id) zi "+\
        "on g.product_id=zi.product_id and g.store_id=zi.store_id "+\
        "left outer join "+\
        "(select product_id,store_fr_id store_id,count(*) qty from "+sTbStk+sWhere+" and vtype_id=3 "+\
            " group by product_id,store_fr_id) zo "+\
        "on g.product_id=zo.product_id and g.store_id=zo.store_id "+\
        "where (p.qty<>0 or i.qty<>0 or s.qty<>0 or t.qty<>0 or b.qty<>0 or zi.qty<>0 or zo.qty<>0) "+\
            sAnd+" order by product,store"
    cur.execute(s)
    for r in cur.fetchall():
        data['data'].append([
           r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],r[8],r[9]    
        ])   
    return JsonResponse(data)











@login_required
def ajax_stock_report(request,what):
    data={'e':''}
    u=request.user
    c=u.company
    uid=str(u.id)
    cid=str(c.id)      

    
    td=datetime.datetime.now()
    yr=request.GET.get('year',str(td.year))
    mn=request.GET.get('month',str(td.month))
    dt1=datetime.date(int(yr),int(mn),1)    
    dt2=datetime.date(int(yr),int(mn),calendar.monthrange(int(yr),int(mn))[1])


    prv_lst=dt1-datetime.timedelta(1)
    #上月 第1天 最后一天 (字符串）
    prv_dt1=datetime.date(prv_lst.year,prv_lst.month,1).strftime('%Y-%m-%d')
    prv_dt2=prv_lst.strftime('%Y-%m-%d')  

    #是否只显示指定仓库库存
    store_id=request.GET.get('store_id','')
    #是否只显示指定产品库存
    product_id=request.GET.get('product_id','')
    #是否区分仓库，默认分库显示
    b_store=request.GET.get('b_store_id','1')    
    #报表是否包含瓶，默认只看整箱产品库存
    b_bottle=request.GET.get('bottle','0')  
    cur=connection.cursor()   
    
    #本期及上期期结ID
    cls_id='0'
    prv_cls_id='0'
    s="select "+\
        "(select id from inventory_stkclosingperiod where company_id="+cid+" and yr="+yr+" and mn="+mn+"),"+\
        "(select id from inventory_stkclosingperiod where company_id="+cid+" and dt_fr='"+prv_dt1+"' and dt_to='"+prv_dt2+"')"
    cur.execute(s)
    r=cur.fetchone()     
    
    tb=''
    fld=''
    #查询在期结范围内
    if r[0]:
        cls_id=str(r[0])        
        if r[1]:
            prv_cls_id=str(r[1])
        tb='inventory_stkclosingperioddetails'
        fld=',sum(qty_act) qty'
        sWhere=" where stkclosing_id="+cls_id
    #查询不在期结范围内
    else:              
        #公司最后一次期结
        s="select id,dt_fr FROM inventory_stkclosingperiod where id="+\
            "(select max(stkclosing_id) from inventory_stkclosingcurrent where company_id="+cid+")"
        cur.execute(s)
        r=cur.fetchone()
        if r:
            ds=(dt1-r[1]).days    
            if ds<0:
                data['e']='查询会计期早于最早期结日期'
            
            elif ds>31:
                data['e']='查询会计期尚末期结，请期结后再做查询'
            else:                
                #查询的是最后期结1个月内库存数据
                prv_cls_id=str(r[0])
                tb='inventory_stkdetails'
                fld=',count(*) qty'
                sWhere=" where company_id="+cid+" and is_delete=false and label_pkg=3 "+\
                    "and (dt between '"+dt1.strftime('%y-%m-%d')+"' "+\
                        "and '"+dt2.strftime('%y-%m-%d')+\
                    "')"
        else:
            data['e']='从末做过库存期结，请期结后再做查询'
    
    if data['e']:
        return JsonResponse(data)
    
    #if tb=='' or fld=='':
    #    data['e']='数据错误'


    clmns=[]
    #库存变动表
    if what=='development':      
        aSel=[]
        aSelWhere=[]
        aSelTop=[]
        aOrderTop=[]
        #转出
        aSelOUT=[] 
        aGrgOUT=[]
        aSelWhereOUT=[]    

        aSelOnOO=[]
        aSelOnI=[]
        aSelOnO=[]
        aSelOnR=[]
        aSelOnTIN=[]
        aSelOnTOUT=[]
        #分仓库
        if b_store=='1':
            #查询指定仓库
            if store_id:
                aSelWhere.append('store_id='+store_id)                              
                aSelWhereOUT.append("store_fr_id="+store_id)                
            #查询所有仓库
            else:      
                aSelOUT.append('store_fr_id store_id')    
                aGrgOUT.append('store_fr_id')
                aSel.append('store_id')
                aSelTop.append('(select name from inventory_storehouse where id=f.store_id)')
                aOrderTop.append('f.store_id')
                clmns.append('仓库名称')
                aSelOnOO.append('f.store_id=oo.store_id')
                aSelOnI.append('f.store_id=i.store_id')
                aSelOnO.append('f.store_id=o.store_id')
                aSelOnR.append('f.store_id=r.store_id')
                aSelOnTIN.append('f.store_id=tin.store_id')
                aSelOnTOUT.append('f.store_id=tout.store_id')             
        if product_id:
            aSelWhere.append('product_id='+product_id)
            aSelWhereOUT.append("product_id="+product_id)            
        else:      
            aSelOnOO.append('f.product_id=oo.product_id')               #期初
            aSelOnI.append('f.product_id=i.product_id')                 #入库
            aSelOnO.append('f.product_id=o.product_id')                 #出库
            aSelOnR.append('f.product_id=r.product_id')                 #退库
            aSelOnTIN.append('f.product_id=tin.product_id')             #转入
            aSelOnTOUT.append('f.product_id=tout.product_id')           #转出   
            aSel.append('product_id')
            aSelOUT.append('product_id')
            aGrgOUT.append('product_id')
            aSelTop.append('(select name from product_product where id=f.product_id)')    
            clmns.append('产品名称')
            aOrderTop.append('f.product_id')
        
        aSelTop.append('coalesce(oo.qty,0)')
        aSelTop.append('coalesce(i.qty,0)')
        aSelTop.append('coalesce(o.qty,0)')
        aSelTop.append('coalesce(r.qty,0)')
        aSelTop.append('coalesce(tin.qty,0)')
        aSelTop.append('coalesce(tout.qty,0)')
        aSelTop.append('coalesce(oo.qty,0)+coalesce(i.qty,0)-coalesce(o.qty,0)+coalesce(r.qty,0)+coalesce(tin.qty,0)-coalesce(tout.qty,0)')
        clmns.append('期初')
        clmns.append('入库')
        clmns.append('出库')
        clmns.append('退库')
        clmns.append('转入')
        clmns.append('转出')
        clmns.append('期末')

        #先暂不考虑瓶标
        #if b_bottle!='0':
        #    sPkg=",label_pkg"
        #    sWherePkg=""

        #上期期末库存明细
        sPrvCls=''
        sPrvClsQty=''
        if prv_cls_id: 
            sPrvCls=" union all select "+\
                ','.join(aSel)+" from inventory_stkclosingperioddetails where stkclosing_id="+prv_cls_id      


        s="select "+",".join(aSelTop)+" "+\
            "from "+\
            "(select "+",".join(aSel)+" from (select "+",".join(aSel)+" from "+tb+sWhere+sPrvCls+") u "+\
                " group by "+",".join(aSel)+\
            ") f "+\
            "left outer join "+\
            "(select "+",".join(aSel)+fld+" from "+tb+sWhere+\
                " and vtype_id=1 "+" and ".join(aSelWhere)+" group by "+",".join(aSel)+\
            ") i "+\
            "on "+" and ".join(aSelOnI)+\
            " left outer join "+\
             "(select "+",".join(aSel)+fld+" from "+tb+sWhere+\
                " and vtype_id=2 "+" and ".join(aSelWhere)+" group by "+",".join(aSel)+\
            ") o "+\
            "on "+" and ".join(aSelOnO)+\
            " left outer join "+\
             "(select "+",".join(aSel)+fld+" from "+tb+sWhere+\
                " and vtype_id=4 "+" and ".join(aSelWhere)+" group by "+",".join(aSel)+\
            ") r "+\
            "on "+" and ".join(aSelOnR)+\
            " left outer join "+\
             "(select "+",".join(aSel)+fld+" from inventory_stkclosingperioddetails where stkclosing_id="+prv_cls_id+\
                " and ".join(aSelWhere)+" group by "+",".join(aSel)+\
            ") oo "+\
            "on "+" and ".join(aSelOnOO)+\
            " left outer join "+\
             "(select "+",".join(aSel)+fld+" from "+tb+sWhere+\
                ' and '.join(aSelWhere)+" and vtype_id=3 group by "+",".join(aSel)+\
            ") tin "+\
            "on "+ " and ".join(aSelOnTIN)+\
            " left outer join "+\
            "(select "+",".join(aSelOUT)+fld+" from "+tb+sWhere+\
                ' and '.join(aSelWhereOUT)+" and vtype_id=3 group by "+",".join(aGrgOUT)+\
            ") tout "+\
            "on "+" and ".join(aSelOnTOUT)+\
            " order by "+",".join(aOrderTop)    
        cur.execute(s)
        d=[]
        l=len(aSelTop)
        for r in cur.fetchall():
            dd=[]
            for i in range(l):
                dd.append(r[i])            
            d.append(dd)
        data['data']=d
        data['clmns']=clmns
        cur.close()   


    #产品库存
    elif waht=='productstock':
        pass

    return JsonResponse(data)






'''
    class StkClosingPeriod(models.Model):  
    ancestor = models.ForeignKey('company.Company', verbose_name=_('企业名称'),related_name='stkclosingperiod_ancestoer', on_delete=models.PROTECT) 
    company = models.ForeignKey('company.Company', verbose_name=_('公司名称'), related_name='stkclosingperiod_company', on_delete=models.PROTECT) 
    user=models.ForeignKey('company.Company',verbose_name='操作人',related_name='stkclosingperiod_user',on_delete=models.PROTECT)
    yr = models.SmallIntegerField(_('年'))
    mn = models.SmallIntegerField(_('月'))
    dt_fr=models.DateField(_('开始日期'))
    dt_to=models.DateField(_('结束日期'))
    dt = models.DateField(_('创建日期'), auto_now_add=True)
    tm = models.DateTimeField(_('创建时间'), auto_now_add=True)
    tm_edit = models.DateTimeField(_('修改时间'), auto_now=True)
    remark = models.CharField(_('备注说明'), max_length=100, blank=True, null=True)

    class Meta:
        verbose_name = _('库存期结会计期')
        verbose_name_plural = _('库存期结会计期')


class StkClosingCurrent(models.Model):
    dt0=models.DateField(_('物流数据最早日期'),blank=True,null=True)
    stkperiod=models.ForeignKey(StkClosingPeriod,verbose_name=_('当前会计期'),related_name='stkclosingcurrent_period',on_delete=models.PROTECT)
    ancestor = models.ForeignKey('company.Company', verbose_name=_('企业名称'),  related_name='stkclosingcurrent_company', on_delete=models.PROTECT)

    class Meta:
        verbose_name = _('企业当前会计期')
        verbose_name_plural = _('企业当前会计期')
'''





# 2022-09-07
def custom_label_infor(company_id,label_id,label_pk_id,label_pkg,label_code,vtype_id=2):
    data={'e':'','product':{},'outbound':{},'package_id':0}
    cur=connection.cursor()    
    if int(company_id)==19267:     
        cid=str(company_id)  
        '''
        #rd=redis.StrictRedis(host='localhost', port=settings.RD['port'], db=4, password=settings.RD['password'], decode_responses=True) 
        rd = redis.StrictRedis(connection_pool=settings.LABEL_PRODUCT_POOL )
        d=rd.hgetall('yz:label_product:'+label_code)
        if d:            
            data['product']={'id':d['product_id'],'name':d['product_name']}
            data['package_id']=int(d['label_pkg'])    
            
        '''
        
        # 先判断标签是否在盘点表内
        t='z_warehouse_repeatless'
        t='temp.z_warehouse_9_5_repeatless'

        if label_id and label_pk_id:
            sW=" where company_id="+cid+" and label_id in ("+str(label_id)+","+str(label_pk_id)+")"
        else:
            sW=" where company_id="+cid+"and label_code='"+label_code+"'"
        s="select product_id,(select name from product_product where company_id="+cid+" and id=product_id) "+\
            "from "+t+sW+" order by label_pkg desc"

        
        

        cur.execute(s)
        r=cur.fetchone()
        if r:
            data['product']={'id':r[0],'name':r[1]}
        else:
            # 取入库产品信息            
            s="select product_id,(select name from product_product where company_id="+cid+" and id=product_id) "+\
                "from inventory_stkdetails"+sW+" and vtype_id=1 and is_delete=false"          
            cur.execute(s)
            r=cur.fetchone()
            if r:                
                data['product']={'id':r[0],'name':r[1]}

        # 是否已出库
        s="select to_char(tm,'yyyy-mm-dd hh24:mi:ss'),(select name from company_company where id=company_to_id) "+\
            "from inventory_stkdetails "+sW+" and vtype_id=2  "+\
            "and (select vtype_id from inventory_stkdetails "+sW+" order by id desc limit 1)<>4 "+\
            "order by id desc limit 1"
        cur.execute(s)
        r=cur.fetchone()
        if r:
            data['outbound']={'time':r[0],'customer':r[1]}
        cur.close()   
        

    return data       


#2022-01-25
def product_check_online(request,company_id):
    data={
        'e':'','package_id':0,
        'suggestion':{'id':0,'name':'','time':''}
    }
    e = time_key_check(request, sK)
    if e:
        data['e'] = e
        return JsonResponse(data)

    product_id=request.GET.get('product_id','')
    label=request.GET.get('label','')
    if not product_id or not label:
        data['e']='product_id/label missing'
        return JsonResponse(data)    
    '''
    q=LabelQuery(company_id,label)     
    
    pk=q.infor['label_pk_id']      
    d=custom_label_infor(company_id,q.infor['label_id'],q.infor['label_pk_id'],q.package['id'],label,vtype_id=2)
    if d['product']:
        if d['product']['id']!=int(product_id):
            data['suggestion']=d['product']
        if d['outbound']:
            data['e']='此标签已于'+d['outbound']['time']+"出库 "+d['outbound']['customer']
    '''


    d=custom_label_infor(company_id,0,0,0,label,vtype_id=2)   
    if d['product']:
        data['package_id']=d['package_id']
        if d['product']['id']!=int(product_id):
            data['suggestion']=d['product']

        if d['outbound']:
            data['e']='此标签已于'+d['outbound']['time']+"出库 "+d['outbound']['customer']    
    return JsonResponse(data)
    




#前端标签查询接口 2022-03-25 重要：今后所有前端（扫码枪，小程序）统一使用这一个接口
def frontend_label_infor(request,user_id):
    data={
        'e':'',
        'infor':{},
        'package':{},
        'relations':{},
        'product':{},
        'stock_development':[]
    }  
    e = time_key_check(request, sK)
    if e:
        data['e'] = e
        return JsonResponse(data)    

    #参数检查
    label=request.GET.get('label','')
    content=request.GET.get('content','')
    if not label or not content:
        data['e']="参数错误"
        return JsonResponse(data)    

    a_contents=content.split(',')
    contents=['relations','product','stock_development']
    for c in a_contents:
        if c not in contents:
            data['e']="无效的content"
            return JsonRespons(data)      
    us=User.objects.filter(id=int(user_id))
    if not us:
        data['e']='用户不存在'
        return JsonResponse(data)
    
    u=us[0]
    #可以在这里根据用户权限, 做查询限制        
    
    if not u.company:
        data['e']='帐号信息错误'
        return JsonResponse(data)
    cid=u.company.id       
    q=LabelQuery(cid,label)
    if not q.infor['label_pk_id']:
        data['e']='标签号码错误'
        return JsonResponse(data)
    data['infor']=q.infor
    data['package']=q.package    
    for what in a_contents:
        if what=='relations':
            data['relations']=q.get_relations()
        elif what=='product':
            data['product']=q.get_product()
        elif what=='stock_development':
            data['stock_development']=q.get_stk_dev()
    return JsonResponse(data)





#2022-04-12 生产批次查询 目前只查询箱标
def PrdBatchQry(company_id,product_id,batch_no):
    company_id=str(company_id)
    data={
        "e":"",        
        "inbound":[],
        "outbound":[],   
        "qty_stk":0
    }
    cur=connection.cursor()   
    #先只查询箱标记录 有些公司用BATCH_NO字段，有些用CODE做为入库时生产批次
    sWhere=" where company_id="+company_id+" and vtype_id=1 and product_id="+product_id+" and code='"+batch_no+"'"
    s="select id,product_id,to_char(tm,'yyyy-mm-dd hh24:mi:ss'),"+\
        "array_to_string(array(select coalesce((select code_a FROM label.lbl_abcode where code_b=label_code),label_code) "+\
            "from logistics.inventory_stkdetails where batch_id=b.id and is_delete=false and label_pkg=3),','),"+\
        "coalesce((select name from inventory_storehouse where id=store_fr_id),''),"+\
        "(select last_name from company_user where id=user_id),"+\
        "(select name from product_product where id="+product_id+") "+\
        "from inventory_batch b "+sWhere
    cur.execute(s)
    rs=cur.fetchall()
    if not rs:    
        data['e']="生产批次 "+batch_no+" 不存在"
        return data
    qty_in=0
    qty_out=0
    ids=[]
    for r in rs:
        if r[3]:
            ids.append(str(r[0]))
            a=r[3].split(',')
            cnt=len(a)
            qty_in=qty_in+cnt
            data['inbound'].append({
                "batch_id":r[0],
                #目前，入库批次即为入库单单号
                "code":batch_no,
                "labels":a,
                "time":r[2],
                "qty":"<a href='"+str(r[0])+"'>"+str(cnt)+"</a>",
                "storehouse":r[4],
                "user":r[5]
            })
    s="create temp table lbls("+\
        "id serial,"+\
        "tb character varying(20),"+\
        "label_pk_id0 bigint,"+\
        "label_code0 character varying(20),"+\
        "label_pkg int,"+\
        "label_pk_id bigint,"+\
        "label_code character varying(20) "+\
    ")"
    cur.execute(s)  
    cur.execute("CREATE INDEX label_pk_id0_idx ON lbls(label_pk_id0)")


    sWhere=" where company_id="+company_id+" and vtype_id=1 and label_pkg=3 and batch_id in ("+','.join(ids)+")"   
    s="insert into lbls(label_pk_id0,label_code0,label_code,label_pkg) select label_pk_id,label_code,"+\
        "coalesce((select code from label.lbl_replace_details where code0=label_code),label_code),"+\
        "label_pkg from inventory_stkdetails "+sWhere
    #AB标标签，跟徐芝亮说好，A标是标签上可以看见的号码
    s="insert into lbls(label_pk_id0,label_code0,label_code,label_pkg) select label_pk_id,"+\
        "coalesce((select code_a FROM label.lbl_abcode where code_b=label_code),label_code),"+\
        "coalesce((select code from label.lbl_replace_details where code0=label_code),label_code),"+\
        "label_pkg from inventory_stkdetails "+sWhere
    cur.execute(s)
    #qty_in=cur.rowcount

    #目前只有酒鬼酒工厂有标签替换
    if company_id=='0': #这里预设酒鬼酒公司ID=1，处理酒鬼工厂标签替换（可能在销售出库前替换，也可能出库后再返厂替换），目前先不做处理
        s="update lbls set tb=coalesce("+\
            "(SELECT tbname FROM label.lbl_tbcross where segment=left(label_code,4)),'label.t'||left(label_code,4))"
        cur.execute(s)
        cur.execute("select tb from lbls group by tb")
        rs=cur.fetchall()
        for r in rs:                    
            s="update lbls set "+\
                "label_pk_id=coalesce(b.parent_id,b.id) "+\
                "from "+\
                "(SELECT label_code from lbls where tb='"+r[0]+"') a "+\
                "left outer join "+\
                "(select id,code,parent_id from "+r[0]+") b "+\
                "on a.label_code=b.code "+\
                "where tb='"+r[0]+"' and lbls.label_code=a.label_code"
            cur.execute(s)   
    
        #查询出库记录 箱
        s="select b.code,b.tm,o.labels,o.batch_id,"+\
            "(select name from company_company where id=b.company_to_id) "+\
            "from "+\
            "(select batch_id,array_to_string(array_agg(label_code),',') labels from "+\
                "(select batch_id,label_pk_id,label_code from inventory_stkdetails s where "+\
                    "company_id="+company_id+" and vtype_id=2 and is_delete=false and label_pkg=3 and ("+\
                        "(select id from lbls where label_pk_id=s.label_pk_id)>0 or "+\
                        "(select id from lbls where label_pk_id0=s.label_pk_id)>0 "+\
                    ") "+\
                    "group by batch_id,label_pk_id,label_code"+\
                ") d group by batch_id"+\
            ") o "+\
            "left outer join "+\
            "(select id,company_to_id,code,to_char(tm,'yyyy-mm-dd hh24:mi:ss') tm from inventory_batch where company_id="+company_id+" and vtype_id=2) b "+\
            "on o.batch_id=b.id "+\
            "order by b.tm"
    else:        
        s="select b.code,b.tm,o.labels,o.batch_id,"+\
            "(select name from company_company where id=b.company_to_id),"+\
            "(select last_name from company_user where id=b.user_id) "+\
            "from "+\
            "(select batch_id,array_to_string(array_agg(label_code),',') labels from "+\
                "(select batch_id,label_pk_id,"+\
                    "coalesce((select code from label.lbl_replace_details where code0=label_code),label_code) label_code "+\
                    "from inventory_stkdetails s where company_id="+company_id+" and vtype_id=2 and is_delete=false "+\
                        "and label_pkg=3 and (select id from lbls where label_pk_id0=s.label_pk_id limit 1)>0 "+\
                    "group by batch_id,label_pk_id,label_code"+\
                ") d group by batch_id"+\
            ") o "+\
            "left outer join "+\
            "(select id,company_to_id,code,user_id,to_char(tm,'yyyy-mm-dd hh24:mi:ss') tm from inventory_batch where company_id="+company_id+" and vtype_id=2) b "+\
            "on o.batch_id=b.id "+\
            "order by b.tm"


    cur.execute(s)
    for r in cur.fetchall():
        if r[2]:
            a=r[2].split(',')
            cnt=len(a)
            qty_out=qty_out+cnt            
            data["outbound"].append({
                "batch_id":r[3],
                "code":r[0],
                "time":r[1],
                "user":r[5],
                "labels":a,
                "customer":r[4],
                "qty":"<a href='"+str(r[3])+"'>"+str(cnt)+"</a>"
            })
    qty_stk=max(qty_in-qty_out,0)
    data['qty_stk']=qty_stk
    return data



@login_required
def production_batch_query(request):
    batch_no=request.GET.get('batch_no','')
    product_id=request.GET.get('product_id','')
    u=request.user
    data=PrdBatchQry(u.company_id,product_id,batch_no)
    return JsonResponse(data)

@login_required
def production_batch(request):
    #batch_no=request.GET.get('batch_no','')    
    #u=request.user
    #data=PrdBatchQry(u.company_id,batch_no)
    #return JsonResponse(data)
    return render(request,'inventory/production_batch_query.html')



# 2022-06-08 查看推送异常的出库单
@login_required
def hand_request(request):
    company_id=str(request.user.company.id)
    vendor = ''
    if company_id == '1':
        vendor = 'hand'
    elif company_id == '1644':
        vendor = 'bz'
    data = []
    clmns = ['上传时间', '单据编号', '客户名称', '产品名称', "错误原因"]
    dt = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr = request.GET.get('date_fr', dt)
    dt_to = request.GET.get('date_to', dt)
    dt_max = max(dt_fr, dt_to)
    dt_min = min(dt_fr, dt_to)
    dt_fr = dt_min
    dt_to = dt_max
    cur = connection.cursor()


    params = {
        'dt_fr': dt_fr,
        'dt_to': dt_to,
    } 
    s = " select a.batch_id,a.batch_code,coalesce(a.err_msg,''),coalesce(a.results,'{}'),b.tm,c.name,coalesce(d.name,'') from  " + \
        " (SELECT batch_id,batch_code,results,err_msg FROM log.sync_inventory_batch where company_id = "+company_id+" and  " + \
        " dt between '" + dt_min + "' and '" + dt_max + "' and is_ok = false and cnt_ok = 0 and vendor = '"+vendor+"' " \
        " and batch_id not in (SELECT a.id FROM (SELECT id from logistics.inventory_batch WHERE  company_id = "+company_id+" and vtype_id =2  )a " + \
        " left outer JOIN (SELECT batch_id from log.sync_inventory_batch where vendor = '"+vendor+"' and is_ok = true)b " + \
        " on b.batch_id = a.id where b.batch_id is not null GROUP BY a.id))a  " + \
        " left outer join  (SELECT id,tm,company_to_id,product_id from logistics.inventory_batch) b " + \
        " on a.batch_id = b.id " + \
        " left outer join (SELECT id,name from logistics.product_product)c  " + \
        " on c.id =	b.product_id " + \
        " left outer join (SELECT id,name from logistics.company_company)d " + \
        " on d.id =	b.company_to_id  where b.id is not null order by b.tm"
    cur.execute(s)
    errs = cur.fetchall()
    for err in errs:
        if err[2]:
            err_msg = err[2]
        elif len(err[3]) > 2:
            err_msg = err[3]
        else:
            err_msg = ''
        tm = "<a href='/inventory/batch/details/" + str(err[0]) + "/' target='_blank'>" + err[4].strftime('%Y-%m-%d %H:%M:%S') + "</a>"
        data.append([tm,err[1],err[6],err[5],err_msg])

    return render(request,'inventory/hand_request_query.html',{
        'data':SafeString(data),
        'clmns':clmns,
        'params': params
    })



#对指定公司做指定月份期结操作 yr,mn 年份月份：整型
#为方便库存批次和保质期管理，先对箱标明细期结(主箱标有企业1箱贴2个标签)，再按产品、仓库汇总。
#生产批次取入库时的code;生产日期取入库时的日期
#先只处理箱标。后期再考虑瓶标发货（只要有1瓶发货，即视为整箱已出库）
def do_closing_new(company_id,user_id,yr,mn,redo=False,prv_cls_id=None):
    cid=str(company_id)
    uid=str(user_id)
    data={'e':'','closing_id':None}     
    #会计期 第1天 最后一天（字符串)
    dt1=datetime.date(yr,mn,1).strftime('%Y-%m-%d')
    dt2=datetime.date(yr,mn,calendar.monthrange(yr,mn)[1]).strftime('%Y-%m-%d')
    cur=connection.cursor()
    cur.execute("select ancestor_id from company_company where id="+cid)
    r=cur.fetchone()
    aid=str(r[0])
    #当前会计期是否已做期结
    s="select id,(select username from company_user where id=user_id),"+\
        "to_char(tm_edit,'yyyy-mm-dd HH24:MI:SS') from inventory_stkclosingperiod where company_id="+cid+" and dt_fr='"+dt1+"' and dt_to='"+dt2+"'"
    cur.execute(s)
    r=cur.fetchone()
    if r: 
        cls_id=str(r[0]) 
        if redo:    #已做过期结，但要求重新期结
            id=str(r[0])            
            #删除当期期末库存明细
            cur.execute("delete from inventory_stkclosingdetails where stkclosing_id="+id) 
            #删除当期期末库存汇总
            cur.execute("delete from inventory_stkclosingtt where stkclosing_id="+id) 
            #修改会计期 操作员 时间
            cur.execute("update inventory_stkclosingperiod set user_id="+uid+",tm_edit=now() where id="+cls_id)
        else:
            data['e']="期计期 "+str(yr)+"年"+str(mn)+"月 已做结期("+r[1]+" "+r[2]+")"
            return data
    else:
        s="INSERT INTO inventory_stkclosingperiod(ancestor_id,company_id,user_id,yr,mn,dt_fr,dt_to) select "+\
            aid+","+cid+","+str(uid)+","+str(yr)+","+str(mn)+",'"+dt1+"','"+dt2+"' returning id"
        cur.execute(s)
        r = cur.fetchone()
        cls_id=str(r[0])   

    tb="temp_stk_closing"
    #判断临时表是否存在（可能一个会话期结多个会计期）
    cur.execute("SELECT * FROM pg_catalog.pg_class WHERE relkind = 'r' AND  relname = '"+tb+"'")
    rr=cur.fetchone()
    if rr:
        cur.execute("truncate table "+tb)
    else:
        s="CREATE temp TABLE "+tb+"("+\
            "label_code character varying(20),"+\
            "label_pk_id bigint,"+\
            "store_id integer,"+\
            "product_id integer,"+\
            "production_batch character varying(50),"+\
            "production_date date,"+\
            "qty smallint"+\
        ")"
        cur.execute(s)
        cur.execute("CREATE INDEX lbl_pk_id ON "+tb+"(label_pk_id)")    

    #上期期结库存明细写入
    if prv_cls_id:
        s="insert into "+tb+"(label_code,label_pk_id,store_id,product_id,qty,production_date,production_batch) "+\
            "select label_code,label_pk_id,store_id,product_id,qty,production_date,production_batch "+\
            "from inventory_stkclosingdetails where company_id="+cid+" and stkclosing_id="+str(prv_cls_id)
        cur.execute(s)
    #处理本期数据
    sWhere=" where company_id="+cid+" and label_pkg>2 and (dt between '"+dt1+"' and '"+dt2+"')"
    sProductionBatch="(select production_batch from "+tb+" where label_pk_id=d.label_pk_id and production_batch is not null limit 1)"
    if prv_cls_id:
        sProductionBatch=sProductionBatch+","+\
            "(select production_batch from inventory_stkclosingdetails where label_pk_id=d.label_pk_id and production_batch is not null limit 1)"
    sProductionBatch="coalesce("+sProductionBatch+",null)"
    sProductionDate="(select production_date from "+tb+" where label_pk_id=d.label_pk_id and production_batch is not null limit 1)"
    if prv_cls_id:
        sProductionDate=sProductionDate+","+\
            "(select production_date from inventory_stkclosingdetails where label_pk_id=d.label_pk_id and production_batch is not null limit 1)"
    sProductionDate="coalesce("+sProductionDate+",null)"
    #入库 vtype_id=1
    s="insert into "+tb+"(label_code,label_pk_id,store_id,product_id,qty,production_date,production_batch) "+\
        "select label_code,label_pk_id,store_id,product_id,1,dt,"+\
            "(select code from inventory_batch where id=batch_id) "+\
        "from inventory_stkdetails "+sWhere+" and vtype_id=1"
    cur.execute(s)
    #转库 vtype_id=3
    s="insert into "+tb+"(label_code,label_pk_id,store_id,product_id,qty,production_date,production_batch) "+\
        "select label_code,label_pk_id,store_to_id,product_id,1,"+sProductionDate+","+sProductionBatch+" "+\
        "from inventory_stkdetails d "+sWhere+" and vtype_id=3"
    cur.execute(s)
    s="insert into "+tb+"(label_code,label_pk_id,store_id,product_id,qty,production_date,production_batch) "+\
        "select label_code,label_pk_id,store_fr_id,product_id,-1,"+sProductionDate+","+sProductionBatch+" "+\
        "from inventory_stkdetails d "+sWhere+" and vtype_id=3"        
    cur.execute(s)
    #其它
    s="insert into "+tb+"(label_code,label_pk_id,store_id,product_id,qty,production_date,production_batch) "+\
        "select label_code,label_pk_id,store_id,product_id,"+\
        "(select direction from inventory_voucher where id=vtype_id),"+\
        sProductionDate+","+sProductionBatch+" "+\
        "from inventory_stkdetails d "+sWhere+" and vtype_id not in (1,3)"
    cur.execute(s)

    #将临时表合并到当期期结库存明细
    s="insert into inventory_stkclosingdetails(ancestor_id,company_id,stkclosing_id,"+\
        "product_id,store_id,label_pk_id,label_code,production_batch,production_date,qty) "+\
        "select "+aid+","+cid+","+cls_id+","+\
        "product_id,store_id,label_pk_id,min(label_code),production_batch,production_date,sum(qty)  "+\
        "from "+tb+" group by product_id,store_id,label_pk_id,production_batch,production_date "+\
        "having sum(qty)<>0"
    cur.execute(s)
    
    #将本期库存明细按产品、仓库汇总
    s="INSERT INTO inventory_stkclosingtt("+\
        "ancestor_id,company_id,stkclosing_id,product_id,store_id,qty) select "+\
        aid+","+cid+","+str(cls_id)+",product_id,store_id,sum(qty) "+\
        "from inventory_stkclosingdetails where company_id="+cid+" and stkclosing_id="+str(cls_id)+" "+\
        "group by product_id,store_id having sum(qty)<>0"
    cur.execute(s)

    data['closing_id']=int(cls_id)
    return data
    



# 2022-06-28 扫码枪扫码标签在线检查
def online_labelcheck(request,company_id,vtype_id):
    data={
        'e':'',
        'package': {},
        'product': {},
    }

    e = time_key_check(request, sK)
    if e:
        data['e'] = e
        return JsonResponse(data)
    tm = request.GET.get('time','')
    label = request.GET.get('label','')
    if not label:
        data['e']='label missing'
        return JsonResponse(data)

    # rd = redis.StrictRedis(host='localhost', port=settings.RD['port'], db=2, password=settings.RD['password'], decode_responses=True)
    # pool = redis.ConnectionPool(host='localhost', port=settings.RD['port'],db=2, password=settings.RD['password'], decode_responses=True)
    rd = redis.StrictRedis(connection_pool=settings.LABEL_CHECK_POOL ) 

    if vtype_id == '2' or  vtype_id == 2:
        user_id = request.GET.get('user_id','')
        user_name = request.GET.get('user_name','')
        q=LabelQuery(company_id,label.strip())
        if q.infor['label_id'] == 0 and len(q.infor['stack']) == 0 :
            data['e'] = '标签错误'
            return JsonResponse(data)

        cur=connection.cursor()
        stack = '0'
        relations = q.get_relations()
        if q.get_stack() :
            stack =  q.get_stack()['code']
        package_id = q.package['id']
        children = relations['cartons']


        # 若为箱标，则以主箱标为key的一部分
        if q.infor['label_pk_code']  and (package_id == 3 or package_id == 7 ):
            label = q.infor['label_pk_code']
        cur=connection.cursor()

        data['package'] = q.package
        label_pk_id = '0'
        if q.get_label_pk():
            label_pk_id = q.get_label_pk()

        product = q.get_product()
        if len(product['name']) != 0:
            data['product'] = {"product_id": product['id'], "product_name": product['name']}

        tmp =stack+ ":" +label+":"+str(label_pk_id)
        users = {'user_id':user_id,'user_name':user_name,'tm':tm}

        # 先判断标签是否在redis中存在
        # 不管什么标签，只要标签号存在redis记录，即有人在操作
        label_pk_ids = []
 
        keys = redis_keys_check(rd,"*:" + label + ":*")

        if keys :
            op = rd.hgetall(keys)
            data['e'] = '该套标签已于'+ eval(op['users'])['tm'] +'被'+ eval(op['users'])['user_name']+'扫描'
            return JsonResponse(data)

        # 当前标签号不存在记录，则需要细化校验
        else:
            sWhere = ''
            # 当前标签为箱标
            if package_id == 3:
                keys = redis_keys_check(rd, "*:*:" + str(label_pk_id))
                # 判断与瓶标是否冲突
                if keys:
                    op = rd.hgetall(keys)
                    data['e'] = '该套标签已于'+ eval(op['users'])['tm'] +'被' + eval(op['users'])['user_name'] + '扫描'
                    return JsonResponse(data)

                # 判断与垛标是否冲突
                # label:company_id:stack:stack:* 肯定为垛标
                keys = redis_keys_check(rd,stack+":"+stack+":*")
                if keys:
                    op = rd.hgetall(keys)
                    data['e'] = '该箱上级垛标'+stack+'已于'+ eval(op['users'])['tm'] +'被' + eval(op['users'])['user_name'] + '扫描'
                    return JsonResponse(data)
                s=" select a.id as chuku ,b.id as tuiku from (select max(id)id,label_pk_id from logistics.inventory_stkdetails where vtype_id = 2 and " + \
                   "( label_code = '"+ label +"' or (label_pk_id  = "+ str(label_pk_id) +" and label_pkg = 3)) GROUP BY label_pk_id )a " + \
                    " left outer join (select max(id)id ,label_pk_id from logistics.inventory_stkdetails where vtype_id = 4 GROUP BY label_pk_id)b  " + \
                    " on a.label_pk_id = b.label_pk_id and b.id > a.id " + \
                    " where b.id is  null "
                cur.execute(s)
                r = cur.fetchall()
                if r:
                    data['e'] = '该箱已出库'
                    return JsonResponse(data)
            # 当前标签为瓶标
            elif package_id == 1:
                keys = redis_keys_check(rd, "*:"+ q.infor['label_pk_code']+":"+str(label_pk_id))
                # 判断与箱标是否冲突
                if keys:
                    op = rd.hgetall(keys)
                    data['e'] = '该套标签已于'+eval(op['users'])['tm']+'被' + eval(op['users'])['user_name']  + '扫描'
                    return JsonResponse(data)
                s = " select a.id as chuku ,b.id as tuiku from (select max(id)id,label_pk_id from logistics.inventory_stkdetails where vtype_id = 2 and "+\
                  " label_code = '"+ label +"' GROUP BY label_pk_id )a " + \
                    " left outer join (select max(id)id ,label_pk_id from logistics.inventory_stkdetails where vtype_id = 4 GROUP BY label_pk_id)b  " + \
                    " on a.label_pk_id = b.label_pk_id and b.id > a.id " + \
                    " where b.id is  null union "+ \
                    " select a.id as chuku ,b.id as tuiku from (select max(id)id,label_pk_id from logistics.inventory_stkdetails where vtype_id = 2 and " + \
                    " label_pk_id ="+ str(label_pk_id) +" and label_pkg = 3 GROUP BY label_pk_id )a " + \
                    " left outer join (select max(id)id ,label_pk_id from logistics.inventory_stkdetails where vtype_id = 4 and"+\
                    " label_pk_id ="+ str(label_pk_id) +" and label_pkg = 3  GROUP BY label_pk_id)b  " + \
                    " on a.label_pk_id = b.label_pk_id and b.id > a.id " + \
                    " where b.id is  null  "
                cur.execute(s)
                r = cur.fetchall()
                if r:
                    data['e'] = '该瓶已出库'
                    return JsonResponse(data)
            # 当前标签为垛标
            elif package_id == 7:
                tmp = label + ":" + label + ":" + str(label_pk_id)
                keys = redis_keys_check(rd, label+":*:*")
                # 判断与箱标是否冲突
                if keys:
                    op = rd.hgetall(keys)
                    data['e'] = '该垛中存在部分箱标已于'+ eval(op['users'])['tm'] +'被' +eval(op['users'])['user_name'] + '扫描'
                    return JsonResponse(data)
                if relations['cartons'] :
                    for i in relations['cartons']:
                        # sqr_pks = ",".join(('%s' %x for x in label_pk_ids))
                        label_pk_ids.append(str(i['label_pk_id']))
                    sqr_pks = ",".join(label_pk_ids)
                    sWhere = "and   label_pk_id in (" + sqr_pks + ")"
                else:
                    data['e'] = '该垛标内无可用标签'
                    return JsonResponse(data)

                s = " select a.id as chuku ,b.id as tuiku from (select max(id)id,label_pk_id from logistics.inventory_stkdetails where vtype_id = 2 and label_pkg =3 "+sWhere+" GROUP BY label_pk_id )a " + \
                    " left outer join (select max(id)id ,label_pk_id from logistics.inventory_stkdetails where vtype_id = 4 and label_pkg =3 GROUP BY label_pk_id)b  " + \
                    " on a.label_pk_id = b.label_pk_id and b.id > a.id " + \
                    " where b.id is  null "
                cur.execute(s)
                r = cur.fetchall()
                if r:
                    data['e'] = '该垛中有'+str(len(r))+'箱已出库'
                    return JsonResponse(data)
            # 存入redis
            rd.hmset(tmp, {'label': label, 'label_pk_id': label_pk_id, 'package_id': package_id, 'children': children, 'users': users})
            # 设置过期时间 三天
            rd.expire(tmp ,259200)

        return JsonResponse(data)


def redis_keys_check(redis,match):
    cursor = 0
    count = 2000
    res = redis.scan(cursor, match, count)
    flag = False
    if res[1] != []:
        return res[1][0]
    while True:
        if res[0] != 0:
            cursor = res[0]
            res = rd.scan(cursor, match, count)
            if res[1] != [] : 
                return res[1][0]
        else:
            return flag



def online_test(request,company_id,vtype_id):
    data={
        'e':'',
        'package': {},
        'product': {},
    }

    e = time_key_check(request, sK)
    if e:
        data['e'] = e
        return JsonResponse(data)
    tm = request.GET.get('time','')
    label = request.GET.get('label','')
    if not label:
        data['e']='label missing'
        return JsonResponse(data)

    # rd = redis.StrictRedis(host='localhost', port=settings.RD['port'], db=2, password=settings.RD['password'], decode_responses=True)
    #   pool = redis.ConnectionPool(host='localhost', port=settings.RD['port'],db=2, password=settings.RD['password'], decode_responses=True)
    rd = redis.StrictRedis(connection_pool=settings.LABEL_CHECK_POOL )

    if vtype_id == '2' or  vtype_id == 2:
        user_id = request.GET.get('user_id','')
        user_name = request.GET.get('user_name','')
        q=LabelQuery(company_id,label)
        if q.infor['label_id'] == 0 and len(q.infor['stack']) == 0 :
            data['e'] = '标签错误'
            return JsonResponse(data)

        cur=connection.cursor()
        stack = '0'
        relations = q.get_relations()
        if q.get_stack() :
            stack =  q.get_stack()['code']
        package_id = q.package['id']
        children = relations['cartons']


        # 若为箱标，则以主箱标为key的一部分
        if q.infor['label_pk_code']  and (package_id == 3 or package_id == 7 ):
            label = q.infor['label_pk_code']
        cur=connection.cursor()

        data['package'] = q.package
        label_pk_id = '0'
        if q.get_label_pk():
            label_pk_id = q.get_label_pk()

        product = q.get_product()
        if len(product['name']) != 0:
            data['product'] = {"product_id": product['id'], "product_name": product['name']}

        tmp =stack+ ":" +label+":"+str(label_pk_id)
        users = {'user_id':user_id,'user_name':user_name,'tm':tm}

        # 先判断标签是否在redis中存在
        # 不管什么标签，只要标签号存在redis记录，即有人在操作
        label_pk_ids = []

        keys = rd.keys("*:" + label + ":*")
        if len(keys) >=1 :
            op = eval(rd.hget(keys[0],'users'))
            data['e'] = '该套标签已于'+ op['tm'] +'被'+ op['user_name']+'扫描'
            return JsonResponse(data)

        # 当前标签号不存在记录，则需要细化校验
        else:
            sWhere = ''
            # 当前标签为箱标
            if package_id == 3:
                keys = rd.keys("*:*:" + str(label_pk_id))
                # 判断与瓶标是否冲突
                if len(keys) >= 1:
                    op = eval(rd.hget(keys[0], 'users'))
                    data['e'] = '该套标签已于'+ op['tm'] +'被' + op['user_name'] + '扫描'
                    return JsonResponse(data)

                # 判断与垛标是否冲突
                # label:company_id:stack:stack:* 肯定为垛标
                keys = rd.keys(stack+":"+stack+":*")
                if len(keys) >= 1:
                    op = eval(rd.hget(keys[0], 'users'))
                    data['e'] = '该箱上级垛标'+stack+'已于'+ op['tm'] +'被' + op['user_name'] + '扫描'
                    return JsonResponse(data)
                s=" select a.id as chuku ,b.id as tuiku from (select max(id)id,label_pk_id from logistics.inventory_stkdetails where vtype_id = 2 and " + \
                   "( label_code = '"+ label +"' or (label_pk_id  = "+ str(label_pk_id) +" and label_pkg = 3)) GROUP BY label_pk_id )a " + \
                    " left outer join (select max(id)id ,label_pk_id from logistics.inventory_stkdetails where vtype_id = 4 GROUP BY label_pk_id)b  " + \
                    " on a.label_pk_id = b.label_pk_id and b.id > a.id " + \
                    " where b.id is  null "
                cur.execute(s)
                r = cur.fetchall()
                if r:
                    data['e'] = '该箱已出库'
                    return JsonResponse(data)
            # 当前标签为瓶标
            elif package_id == 1:
                keys = rd.keys("*:"+ q.infor['label_pk_code']+":"+str(label_pk_id))
                # 判断与箱标是否冲突
                if len(keys) >= 1 :
                    op = eval(rd.hget(keys[0], 'users'))
                    data['e'] = '该套标签已于'+ op['tm'] +'被' + op['user_name'] + '扫描'
                    return JsonResponse(data)
                s = " select a.id as chuku ,b.id as tuiku from (select max(id)id,label_pk_id from logistics.inventory_stkdetails where vtype_id = 2 and "+\
                  " label_code = '"+ label +"' GROUP BY label_pk_id )a " + \
                    " left outer join (select max(id)id ,label_pk_id from logistics.inventory_stkdetails where vtype_id = 4 GROUP BY label_pk_id)b  " + \
                    " on a.label_pk_id = b.label_pk_id and b.id > a.id " + \
                    " where b.id is  null union "+ \
                    " select a.id as chuku ,b.id as tuiku from (select max(id)id,label_pk_id from logistics.inventory_stkdetails where vtype_id = 2 and " + \
                    " label_pk_id ="+ str(label_pk_id) +" and label_pkg = 3 GROUP BY label_pk_id )a " + \
                    " left outer join (select max(id)id ,label_pk_id from logistics.inventory_stkdetails where vtype_id = 4 and"+\
                    " label_pk_id ="+ str(label_pk_id) +" and label_pkg = 3  GROUP BY label_pk_id)b  " + \
                    " on a.label_pk_id = b.label_pk_id and b.id > a.id " + \
                    " where b.id is  null  "
                cur.execute(s)
                r = cur.fetchall()
                if r:
                    data['e'] = '该瓶已出库'
                    return JsonResponse(data)
            # 当前标签为垛标
            elif package_id == 7:
                tmp = label + ":" + label + ":" + str(label_pk_id)
                keys = rd.keys(label+":*:*")
                if len(keys) >= 1 :
                    op = eval(rd.hget(keys[0], 'users'))
                    data['e'] = '该垛中存在部分箱标已于'+ op['tm'] +'被' + op['user_name'] + '扫描'
                    return JsonResponse(data)
                if relations['cartons'] :
                    for i in relations['cartons']:
                        # sqr_pks = ",".join(('%s' %x for x in label_pk_ids))
                        label_pk_ids.append(str(i['label_pk_id']))
                    sqr_pks = ",".join(label_pk_ids)
                    sWhere = "and   label_pk_id in (" + sqr_pks + ")"
                else:
                    data['e'] = '该垛标内无可用标签'
                    return JsonResponse(data)

                s = " select a.id as chuku ,b.id as tuiku from (select max(id)id,label_pk_id from logistics.inventory_stkdetails where vtype_id = 2 and label_pkg =3 "+sWhere+" GROUP BY label_pk_id )a " + \
                    " left outer join (select max(id)id ,label_pk_id from logistics.inventory_stkdetails where vtype_id = 4 and label_pkg =3 GROUP BY label_pk_id)b  " + \
                    " on a.label_pk_id = b.label_pk_id and b.id > a.id " + \
                    " where b.id is  null "
                cur.execute(s)
                r = cur.fetchall()
                if r:
                    data['e'] = '该垛中有'+str(len(r))+'箱已出库'
                    return JsonResponse(data)
            # 存入redis
            rd.hmset(tmp, {'label': label, 'label_pk_id': label_pk_id, 'package_id': package_id, 'children': children, 'users': users})
            # 设置过期时间 三天
            rd.expire(tmp ,259200)

        return JsonResponse(data)






"""
# test 2022-07-20
@csrf_exempt
def test_log(request):
    cid='1'
    s = request.body.decode('utf8')   
    pth="F:\\hzy\\log\\inventory_update\\"
    if not os.path.exists(pth+cid):
        os.mkdir(pth+cid)
    fn='test.txt'
    fn=datetime.datetime.now().strftime('%Y_%m_%d')+".txt"
    f=open(pth+cid+'\\'+fn,'a',encoding='utf-8')
    f.write(s+'\n')
    f.close()
    return JsonResponse({'e':''})
"""

@csrf_exempt
def near_stock(request, company_id=None):
    warn_max = ""
    data = {'e': '', 'stock': []}
    
    if not company_id:
        company_id = request.user.company.id
    
    cs = Company.objects.filter(id=company_id)
    c = cs[0]
    package_units = get_package_name(c.ancestor_id)
    # 进销商层级，工厂
    if c.level.sn == 0:
        sWhere = " where ancestor_id=" + str(c.ancestor_id) + " and company_id<>" + str(c.id)
    else:
        sWhere = " where ancestor_id=" + str(c.ancestor_id) + " and company_id in (select id from company_company where id=" + str(
                c.id) + " or parent_id=" + str(c.id) + ")"

    s = "SELECT tbl.company, tbl.product, tbl.x, tbl.h, tbl.P, tbl.company_id, tbl.product_id, tbl.NAME, COALESCE(tbl.days::text,''), coalesce(tbl.warn_type,''), coalesce(tbl.warn_color,'') FROM (SELECT * FROM (SELECT(SELECT NAME FROM company_company WHERE ID = b.company_id) company, (SELECT NAME FROM product_product WHERE ID = b.product_id) product, b.x, b.h, b.P, b.company_id, b.product_id, (SELECT NAME FROM company_level WHERE ID = ( SELECT level_id FROM company_company WHERE ID = b.company_id ) ), b.days FROM (SELECT A.product_id, A.company_id, SUM(A.x) x, SUM(A.h) h, SUM(A.P) P, A.days,	A.dt FROM	(SELECT ID, dt, product_id, company_id, CASE WHEN label_pkg IN (3,4) THEN (SELECT direction FROM inventory_voucher WHERE ID = vtype_id) ELSE 0  END x, CASE WHEN label_pkg = 2 THEN (SELECT direction FROM inventory_voucher WHERE ID = vtype_id) ELSE 0 END h, CASE WHEN label_pkg = 1 THEN (SELECT direction FROM inventory_voucher WHERE ID = vtype_id) ELSE 0 END P, round((EXTRACT ( epoch FROM ( dt - now() + ((((SELECT shelf_life FROM product_product WHERE id =  product_id) ->> 'value')||' '||((SELECT shelf_life FROM product_product WHERE id = product_id)->>'period'))::INTERVAL)) ))/3600/24.0) days FROM inventory_stkdetails d " \
	+ sWhere + \
    ") A GROUP BY A.product_id, A.company_id, A.days, A.dt) b ORDER BY days, company, product) ta LEFT JOIN inventory_stkexp tb ON ta.days > tb.warn_min_day AND ta.days <= tb.warn_max_day) tbl where x>0 or h>0 or p>0" + warn_max
    
    #print(s)
    cur = connection.cursor()                         
    cur.execute(s)
    if c.level.sn == 0:
        data = {'data': [], 'clmns': [], 'e': [],'subtt': ['', ''], 'murl': '',
                'dt': False, 'add': True}
        data['subtt'] = ['进销存报表','过期预警']
        data['clmns'] = ['经销商','层级', '产品','数量','剩余保质期天数']
          
        #data['dt']=True
    
        #dt_default = datetime.datetime.now().strftime('%Y-%m-%d')
        #dt_fr_default = (datetime.datetime.now() - datetime.timedelta(days=15)).strftime('%Y-%m-%d')
        #dt_fr = request.GET.get('date_from', dt_fr_default)
        #dt_to = request.GET.get('date_to', dt_default)
        #data["date_from"] = dt_fr
        #data["date_to"] = dt_to 
        
        for r in cur.fetchall():
            qty = ''
            a = []
            warn = r[9]
            days = f'<span class=" ant-tag ant-tag-{warn}">{r[8]}</span>'
            if r[2]:
                a.append(str(r[2]) + package_units[2])
            if r[3]:
                a.append(str(r[3]) + package_units[1])
            if r[4]:
                a.append(str(r[4]) + package_units[0])
            if a:
                qty = ",".join(a)

            data['data'].append([
                r[0],  # agent
                r[7],  # level
                r[1],  # product
                qty,  # qty
                days  # 剩余保质期天数
            ])
            
        return render(request, 'obj/list_obj.html', data)
    else:
        data = {"data": []}
        for r in cur.fetchall():
            days = r[8]
            warn = r[10]
            sub_data = {"company": r[0], "level": r[7], "product": r[1], "x": str(r[2]) + package_units[2], "h": str(r[3]) + package_units[1], "p": str(r[4]) + package_units[0], "days_to_expire": str(days), "color": str(warn),"company_id":r[5],"product_id":r[6],'type':r[9]}
            data['data'].append(sub_data)

    return JsonResponse(data)


# 订单(发货单)发货状态查询
def delivery_status(request):
    data={'data':[],'clmns':["发货单号","创建时间","发货单状态","出库单号","出库单状态","产品编码","产品名称", "应发数量", "单位",
                     "实发数量"]}
    company_id = request.user.company.id
    dt_default = datetime.datetime.now().strftime('%Y-%m-%d')
    dt_fr_default = (datetime.datetime.now() - datetime.timedelta(days=7)).strftime('%Y-%m-%d')
    dt_fr = request.GET.get('date_from', dt_fr_default)
    dt_to = request.GET.get('date_to', dt_default)
    dt_max = max(dt_fr, dt_to)
    dt_min = min(dt_fr, dt_to)
    start = dt_min
    end = dt_max
    data["date_from"] = start
    data["date_to"] = end


    sql = """
        SELECT
            n.dn_id,n.product_id,d.dn_number,n.qty,COALESCE(n.unit_name,''),n.product_name,n.external_code,n.qty_x,n.qty_h,n.qty_p,d.x,d.h,d.P,
            coalesce((CASE
                WHEN unit_name='瓶' THEN x*(CASE WHEN qty_h IS NOT NULL AND qty_h <> 0 THEN qty_h ELSE 1 END) * (CASE WHEN qty_p IS NOT NULL AND qty_p <> 0 THEN qty_p ELSE 1 END)/(CASE WHEN qty_x IS NOT NULL AND qty_x <> 0 THEN qty_x ELSE 1 END) + h * (CASE WHEN qty_h IS NOT NULL AND qty_h <> 0 THEN qty_h ELSE 1 END)/(CASE WHEN qty_x IS NOT NULL AND qty_x <> 0 THEN qty_x ELSE 1 END) + p
                WHEN unit_name='盒' THEN x*(CASE WHEN qty_h IS NOT NULL AND qty_h <> 0 THEN qty_h ELSE 1 END) / (CASE WHEN qty_x IS NOT NULL AND qty_x <> 0 THEN qty_x ELSE 1 END) + p
                WHEN unit_name='箱' THEN x
                else x
            END),0) qty_done,(select tm from inventory_deliverynote where id = n.dn_id)
        FROM
            (SELECT nn.*,pd.name AS product_name,pd.external_code as external_code, qty_x, qty_h, qty_p FROM
                (
                SELECT deliverynote_id AS dn_id,
                    (SELECT code FROM logistics.inventory_deliverynote WHERE ID = deliverynote_id and code is not null) dn_number,
                    product_id, 
                    SUM(qty) qty, unit_name
                FROM
                    logistics.inventory_dndetails 
                WHERE
                    company_id = """ + str(company_id) + """
                    AND (unit_name IS NOT NULL AND UNIT_NAME <> '')
                    AND product_id IS NOT NULL 
                    AND (dt BETWEEN '""" + start + """' AND '""" + end + """')
                GROUP BY
                    dn_id, product_id, unit_name
                ORDER BY dn_number
                ) nn -- 从发货单详情表拿到：发货单id、发货单号、产品id、数量和单位。
            -- 各发货单对应哪些产品，要发多少货。
                LEFT OUTER JOIN
                (
                SELECT
                    id, name,external_code, qty_x, qty_h, qty_p
                FROM
			        product_product
			    WHERE
			        company_id = """ + str(company_id) + """
				)pd
				ON nn.product_id = pd.id
			)n
        LEFT OUTER JOIN
        (
        SELECT
            (SELECT dn_number FROM logistics.inventory_batch WHERE ID = batch_id and dn_number is not null) dn_number, -- 公司1644出库的批次对应的发货单号
            product_id, SUM (x) x, SUM (h) h, SUM (P) P
        FROM
            (
            SELECT
                batch_id, product_id,
                CASE
                    WHEN label_pkg = 3 THEN
                    1 ELSE 0 
                END x,
                CASE
                    WHEN label_pkg = 2 THEN
                    1 ELSE 0 
                END h,
                CASE
                    WHEN label_pkg = 1 THEN
                    1 ELSE 0 
                END P
            FROM
                logistics.inventory_stkdetails
            WHERE
                company_id = """ + str(company_id) + """
                AND vtype_id = 2 
                AND batch_id IN (
                    SELECT id FROM logistics.inventory_batch WHERE dn_number IN 
                        (
                        SELECT code
                        FROM logistics.inventory_deliverynote
                        WHERE company_id = """ + str(company_id) + """
                            AND (dt BETWEEN '""" + start + """' AND '""" + end + """')
                        ) -- 公司1644的发货单号。
                    ) -- 公司1644所对应的发货批次id
            ) dd -- 从stkdetails表拿到：公司1644所对应的出库的batch_id、产品id、箱、盒、瓶信息。
            GROUP BY
                dn_number, product_id
        ) d -- 按照订单号和产品id分组，将箱、盒、瓶加起来。(stkdetails表，公司1644所对应的出库的batch_id、产品id、箱、盒、瓶信息。)
        -- 哪个单的哪些产品发了多少
    ON
        n.dn_number = d.dn_number
        AND n.product_id = d.product_id
    where d.dn_number is not null
        order by d.dn_number;
    """

    cur = connection.cursor()
    cur.execute(sql)
    res = cur.fetchall()
    for r in res:
        if r[3] > r[-2]:
            status = '<span style="color:red;/* line-height: 28px; */">未完成</span>'
        elif r[3] <= r[-2]:
            status = '<span style="color:green;/* line-height: 28px; */">已完成</span>'
        else:
            status = ''

        data['data'].append([r[2],r[-1].strftime("%Y-%m-%d %H:%M:%S"),status,"出库单编号","出库单状态",r[6],r[5],str(r[3]).split(".")[0],r[4],r[-2]])

    return render(request, 'inventory/list_dn_number.html', data)

    # jsonDict = datacenter.common.query_json(sql)
    # for row in jsonDict:
    #     ratio = 0
    #     if row["unit_name"] == "瓶":
    #         ratio = (row["qty_p"] if row["qty_p"] else 1) * (row["qty_h"] if row["qty_h"] else 1) / row["qty_x"]
    #     if row["unit_name"] == "盒":
    #         ratio = (row["qty_h"] if row["qty_h"] else 1) / row["qty_x"]
    #     if row["unit_name"] == "箱":
    #         ratio = 1
    #     # amount = ratio * row["qty"]
    #     row["qty"] = float(row["qty"]) * ratio
    # data = {"data": jsonDict}
    # data = {"data": common.query_json(sql)}
    # print(json.dumps(data,ensure_ascii=False))
    # return JsonResponse(data)

@csrf_exempt
def product_deliver_details(request, company_id=None, product_id=None):
    if not company_id:
        return JsonResponse({"code": 500, "info": "company_id or product_id required! "})
    
    cs = Company.objects.filter(id=company_id)
    c = cs[0]
    package_units = get_package_name(c.ancestor_id)
    
    limit = request.GET.get("page_size") if request.GET.get("page_size") else 20
    offset = int(request.GET.get("page_num")) - 1 if request.GET.get("page_num") else 0
    period = request.GET.get("period") if request.GET.get("period") else '30 day'
    sql = f"""SELECT product_id,
        CASE WHEN vtype_id = 1 THEN '入库' WHEN vtype_id = 2 THEN '出库' WHEN vtype_id = 3 THEN '转库' WHEN vtype_id = 4 THEN '退库' ELSE '未知' END vtype,
        (SELECT name FROM product_product WHERE id = product_id) product_name,
        (SELECT code FROM inventory_batch WHERE id = batch_id) batch_number,
        COUNT(label_id) qty,
        CASE WHEN label_pkg = 3 THEN '{package_units[2]}' WHEN label_pkg = 2 THEN '{package_units[1]}' ELSE '{package_units[0]}' END unit,
        dt
    FROM
        inventory_stkdetails
    WHERE
        product_id = """ + str(product_id) + """
        AND company_id = """ + str(company_id) + """
        AND dt > ( now() - '""" + period + """' :: INTERVAL )
    GROUP BY product_id, batch_number, product_name, unit, vtype, dt
    LIMIT """ + str(limit) + """
    OFFSET """ + str(int(limit) * int(offset))
    data = query_json(sql)
    return JsonResponse(
        {
            "code": 200,
            "info": "success",
            "data": data
        }
    )
