# -*- 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,request_rebate_points
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 *

# 2022-11-24
import io
from PIL import Image
from base64 import b64encode, b64decode


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

# 2023-01-14 
from system.views import sys_log
from system.models import Log

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,agent_id=None):
        if not conn:
            conn=connection
        self.code=code    
        self.tb_cross=''    #卷标跨段表名
        self.company_id=int(company_id)
        self.connection=conn 
        self.package={}
        if agent_id:
            self.agent_id = int(agent_id)        
        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()

        aid=str(company.ancestor_id)

        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+"' "
                #)

                # 2022-12-16
                # 酒鬼今后会有直接扫临时标代替瓶盖码 (盖内码解密=瓶盖上贴的44开头临时标) 
                # 目前瓶盖码加密方式只能从加密码得到明码,不能从明码得到加密码(盖内码) 
                baid=aid
                if int(company_id)==1644:
                    baid=1
                s="select a.bottle,a.id from "+\
                    "(select   bottle,id from label.bottlecap       where company_id="+str(baid)+" and label='"+code+"'"+\
                        " union all "+\
                        "select bottle,id from z_bottlecap_binding  where company_id="+str(baid)+" and label='"+code+"'"+\
                        " union all "+\
                        "select   bottle,id from label.bottlecap    where company_id="+str(baid)+" and code='"+d_code+"'"+\
                        " union all "+\
                        "select bottle,id from z_bottlecap_binding  where company_id="+str(baid)+" and code='"+d_code+"'"+\
                    ") a order by id desc"
                cur.execute(s)

                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]

        # 2022-10-29 stkdetails分表
        tb_stk="stkdetails.c"+aid

        cur.execute("select id from "+tb_stk+" 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     

    # 2023 07-14 经销商查询标签信息
    #判断是否是该经销商标签
    def get_agent_label(self):
        flag = False
        agent_id = self.agent_id
        label_pk_id = self.infor['label_pk_id']
        tb = "stkdetails.c"+str(self.company_id)
        cur = self.connection.cursor()
        s = "SELECT * from " +tb+ " WHERE company_to_id = "+str(agent_id)+" and vtype_id = 2 and label_pk_id = "+str(label_pk_id)+" ;"
        cur.execute(s)
        r = cur.fetchone()
        if r:
            flag = True
        return flag

    #获取套标关系，目前只考虑箱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])

        tb_stk="stkdetails.c"+aid
        
        #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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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)+"')"

        # 2022-10-29
        tb_stk='stkdetails.c'+aid

        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 "+tb_stk+" "+\
                "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,
        'label_id':0,
        'label_pk_id':0,
        'label_pkg_id':0,
        'product_id':0,
        'code_a':'',
        'code_b':'',
        '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))
    

    # 2023-06-12 为保证接口数据统一，这个今后要改成 LabelQuery
    d=label_sys_info(code,c,has_price=True)   
    
    
    if d['e']:
        data['e']=d['e']
        return JsonResponse(data)  

    # 2023-03-07
    data['code_a']=d['code_a']
    data['code_b']=d['code_b']
    data['label_id']=d['label_id']
    data['label_pk_id']=d['label_pk_id']
    data['label_pkg_id']=d['package']['id']
    data['inboud_ticket']=d['inboud_ticket']
    data['replace']=d['replace']
    data['package']=d['package']['name']
    data['product']=d['product']['name']
    data['product_id']=d['product']['id']
    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']


    # 2023-06-12
    # 收藏码
    cur=connection.cursor()
    s="select item_code from collection_binding where "+\
        "company_id="+company_id+" and label_code='"+code+"'"
    cur.execute(s)
    r=cur.fetchone()
    if r:
        data['item_code']=r[0]
    else:
        data['item_code']=''
    cur.close()

    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,
        'label_id':0,
        'code_a':'',
        'code_b':'',
        '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]:
    # 2023-03-07
    cur.execute("select code_a,code_b FROM label.lbl_abcode where code_b='"+code+"' or code_a='"+code+"'")
    r=cur.fetchone()
    if r:
        code=r[0]  
        data['code_a']=r[0]
        data['code_b']=r[1]    
    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]
    data['label_id']=r[0]
    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)  

    # 2022-10-29 stkdetails分表
    aid=str(company.ancestor_id)
    tb_stk="stkdetails.c"+aid

    #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 "+tb_stk+" "+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,a.company_to_id,coalesce((select cell_phone from company_company where id=a.company_to_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 "+tb_stk+" "+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],
            'to_company_id': r[25],
            'to_company_phone': r[26],
            '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




# 2023-07-25 所有需要推送第三方的batch写入batchpost表
def batch_post(company_id,batch_id,vendor_id,customer_id,product_id,vtype_id):
    bid=str(batch_id)       #batch_id        
    cid=str(company_id)     #企业id
    aid=str(customer_id)    #经销商id
    vid=str(vendor_id)      #第三方id
    pid=str(product_id)     #产品id
    tid=str(vtype_id)       #单据类型id
    cur=connection.cursor()
    s="select "+\
        "(select json_build_object('id',id,'name',name,'external_code',external_code) from company_company where id="+aid+"),"+\
        "(select json_build_object('id',id,'name',name,'external_code',external_code) from product_product where id="+pid+")"
    cur.execute(s)
    r=cur.fetchone()
    s="INSERT INTO thirdparty_batchpost(company_id,batch_id,vendor_id,customer,product,vtype_id) values "+\
        "("+cid+","+bid+","+vid+",'"+json.dumps(r[0])+"','"+json.dumps(r[1])+"',"+tid+") "+\
        "on conflict (batch_id) do nothing"
    cur.execute(s)    
    cur.close()
    return 0

# 2023-07-25 发货batch是发送给异步任务服务 
def taskman_post(batch):
    '''
    :batch:inveontory.Batch对像
    '''    
    cid=str(batch.company_id)       #企业id
    pid=str(batch.product_id)       #产品id
    aid=str(batch.company_to_id)    #经销商id
    vid=str(batch.vtype_id)         #单据类型id 2:销售出库 4:销售退库
    bid=str(batch.id)               #Batch id
    bcd=batch.code

    cur=connection.cursor()
    result=None    
    acts=[]
    if vid=='2':
        acts=['relations','delivery']
    elif vid=='4':
        acts['return']
    data={'batch':{'id':bid,'code':bcd},  'actions':acts}
    
    #3;"上海汉得信息技术股份有限公司"
    #6;"成都博智维讯信息技术股份有限公司"
    #7;"HiShop海商"      
    if cid=='1':               # 酒鬼        
        if vid in ('2','4'):            
            # 指定产品出库退库，除特定经销商外，要推送给汉得
            s='select products @> '+"'"+'[{"id":"'+pid+'"}]'+"',"+\
                "(select "+aid+" in (SELECT customer_id FROM thirdparty_exemption where company_id=1)) "+\
                "from thirdparty_redirect where company_id=1 and code='HD'"
            cur.execute(s)
            r=cur.fetchone()
            if r[0] and not r[1]:
                batch_post(company_id=cid,batch_id=bid,vendor_id=3,customer_id=aid,product_id=pid,vtype_id=vid)                 
                
                #推送 汉得
                result=tasks.post_hand.delay(data)
                #print('post hand:',data)
    elif cid=='1644':           # 内参
        if vid in ('2'):                        
            batch_post(company_id=cid,batch_id=bid,vendor_id=6,customer_id=aid,product_id=pid,vtype_id=vid)             
            #所有销售出库要推送给博智
            result=tasks.post_bz.delay(data) 
            #print('post bz:',data)

            if batch.rmk_name:
                if batch.rmk_name[-2:]=='赋码':
                    batch_post(company_id=cid,batch_id=bid,vendor_id=7,customer_id=aid,product_id=pid,vtype_id=vid) 
                    
                    #推送海商
                    result=tasks.post_hs.delay(data)
                    #print('post hs:',data)
    cur.close()
    return result




#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'])
    
    #if vch_id == 4:
    #    data['e'] = '系统维护中'
    #    return JsonResponse(data)
    
    
    #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

    # 2023-01-11
    aid=str(c.ancestor_id)

    # 2022-10-29    stkdetails分表
    tb_stk='stkdetails.c'+aid

    #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



    # 2023-06-10 是否存在借货信息
    if 'borrowing' in r:
        if r['borrowing']:
            #borrowing=[{
            #    'agent_id':143859,  #1919二级
            #    'product_id':2674,  #天鉴老酒
            #    'codes':[
            #        {'label_code':'667538771386','label_id':745375008,'label_pk_id':745375008,'label_pkg':3},
            #        {'label_code':'667538771317','label_id':745375006,'label_pk_id':745375006,'label_pkg':3},
            #        {'label_code':'667538771245','label_id':745375005,'label_pk_id':745375005,'label_pkg':3},           
            #    ],
            #}
            try:
                # 处理借货数据：先做第三方借货出库，再做当前经销商借货入库
                product_borrowing(ancestor_id=int(aid), agent_id=cmp_id, borrowing=r['borrowing'])                
            except Exception:
                pass




    #2020-08-29 是否强制发货
    force=False
    if 'force' in r:
        force=r['force']
    # 2023-02-27 酒鬼酒今后也做重复发货检查，如果要再次发货，要先做退货
    #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

    # 2022-11-24
    # 易臻，灸贴、眼贴、艾饼，2022年9月27号前，套标工厂在随意贴标不，套标关系混乱，先设置force=True，否则仓库发不了货
    if c.id in [19267]:
        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   

    # 2023-03-03 此笔发货是否指定了对应平台商id
    distributor_id=None
    if 'original_agent_id' in r:
        if r['original_agent_id']:
            try:
                distributor_id=int(r['original_agent_id'])
            except Exception:
                pass
    batch.distributor_id=distributor_id


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

    # 2022-09-27
    remark=None
    if 'remark' in r:
        remark=r['remark']
    batch.remark=remark

    
    #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-11-15
    if 'stacks' in r and r['stacks']:
        batch.stacks = r['stacks']
    elif 'stack_binding' in r and r['stack_binding']:
        batch.stacks = r['stack_binding']

    #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:         # 产成品入库
        # 成品入库，号码唯一
             
        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(32),"+\
        "tb character varying(20),"+\
        "product_id integer,"+\
        "stack_id integer,"+\
        "wrapper_id integer,"+\
        "code character varying(32),"+\
        "label_id bigint,"+\
        "label_pk_id bigint,"+\
        "label_pkg smallint,"+\
        "err character varying(100),"+\
        "label_code0 character varying(32),"+\
        "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 "+tb_stk+" where label_code = '{code['code']}' and vtype_id = 1 ORDER BY id desc LIMIT 1 ")
                
            #    if rr:
            #       from_agent_id = rr[0]
            # 2022-10-19 以上带order by id desc语句执行非常慢，改成以下语句
            if from_agent_id == 'null':
                rr = cur.execute(f"select company_id from "+tb_stk+" where label_code = '"+code['code']+"' and vtype_id = 1  LIMIT 1 ")
                # 如果有记录的话，再加order by 就非常快
                if rr:                    
                    cur.execute(f"select company_id from "+tb_stk+" where label_code = '"+code['code']+"' and vtype_id = 1 ORDER BY id desc LIMIT 1 ")
                    rrr=cur.fethone()
                    from_agent_id = rrr[0]

            # 2023-01-11 诗仙太白会扫小圆标(盒标加密码)  重庆焱翕盛商贸有限公司	19318
            if aid in ['19318'] and code['code'][0]=='h':
                code['code']=decrypt_11h(code['code'])


            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 "+tb_stk+" 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])
                rr = cur.execute(f"select company_id from "+tb_stk+" where label_code = '"+code['code']+"' and vtype_id = 1  LIMIT 1 ")
                # 如果有记录的话，再加order by 就非常快
                if rr:                    
                    cur.execute(f"select company_id from "+tb_stk+" where label_code = '"+code['code']+"' and vtype_id = 1 ORDER BY id desc LIMIT 1 ")
                    rrr=cur.fethone()
                    from_agent_id = rrr[0]


            # 2023-01-11 诗仙太白会扫小圆标(盒标加密码)  重庆焱翕盛商贸有限公司	19318
            if aid in ['19318'] and  code[0]=='h':
                code=decrypt_11h(code)

                 
            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)
    '''
    
    stacks = []
    stack_binding = ''
    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)
    if vch_id == 1 and 'stack_binding' in r:
        st = r['stack_binding']
        if len(st) > 0:
            stack_binding = jcs_virtual_stack_binding(batch, r['stack_binding'],cmp_id)


    #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(32),"+\
            "wl character varying(32)"+\
            ")"
        )
        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)   
    


    # 2022-09-17 酒鬼酒，内参，6个年份重新包装，基础数据写入了标准跨段表    
    if c.ancestor_id in [1,1644]:
        cur.execute("update codes set tb='t'||left(code,4) where label_id is null")
        cur.execute("select tb from codes where label_id is null 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 and label_id is null"      
                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-10-19 为提高速度，把所有相关记录复制到临时表
    t_stk='tstkdetails'
    s="CREATE temp TABLE tstkdetails("+\
            "id integer NOT NULL,"+\
            "voucher_type character varying(3),"+\
            "voucher_id integer,"+\
            "label_id bigint NOT NULL,"+\
            "label_code character varying(32) NOT NULL,"+\
            "label_pkg smallint NOT NULL,"+\
            "dt date NOT NULL DEFAULT now(),"+\
            "is_delete boolean DEFAULT false,"+\
            "company_id integer NOT NULL,"+\
            "company_to_id integer,"+\
            "product_id integer NOT NULL,"+\
            "store_id integer,"+\
            "store_fr_id integer,"+\
            "batch_id integer,"+\
            "tm timestamp with time zone NOT NULL DEFAULT now(),"+\
            "vtype_id smallint,"+\
            "store_to_id integer,"+\
            "label_pk_id bigint,"+\
            "ancestor_id integer,"+\
            "label_old character varying(32),"+\
            "stack_id integer,"+\
            "from_agent_id integer,"+\
            "parent_id integer"+\
        ")"
    cur.execute(s)
    sFlds="id,voucher_type,voucher_id,label_id,label_code,label_pkg,"+\
        "dt, is_delete, company_id, company_to_id, product_id, store_id,"+\
        "store_fr_id, batch_id, tm, vtype_id, store_to_id, label_pk_id,"+\
        "ancestor_id, label_old, stack_id, from_agent_id, parent_id"
    s="insert into "+t_stk+"("+sFlds+") select "+ sFlds+" from "+tb_stk+" d where "+\
        "ancestor_id="+str(c.ancestor_id)+" and ("\
        "EXISTS(select 1 from codes where label_pk_id=d.label_pk_id)  or "+\
        "EXISTS(select 1 from codes where label_code=d.label_code) )"
    cur.execute(s)
    """
    # 2022-11-02
    t_stk=tb_stk



   
    #2022-01-14 产品名称
    if cfg.product_depend_on==1:
        #以入库时产品名称优先
        s="update codes c set product_id=coalesce("+\
            "(select product_id from "+t_stk+" where vtype_id=1 and label_pk_id=c.label_pk_id and is_delete=false order by id desc limit 1),product_id)"   
        #2022-10-19
        #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  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 "+tb_stk+" 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)"  
        
        # 2022-09-15
        product = "coalesce((select product_id from "+t_stk+" 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),product_id)" 
        #2022-10-19
        #product = "coalesce((select product_id from "+tb_stk+" 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  limit 1),product_id)" 

    if vch_id == 5:     # 标签退库
        d = "true"
        store = "(select store_id from "+t_stk+" where voucher_type='grn' " + \
            "and  label_code=a.label_code and store_id is not null order by id desc limit 1)"
        # 2022-10-19
        #store = "(select store_id from "+tb_stk+" where voucher_type='grn' " + \
        #    "and  label_code=a.label_code and store_id is not null  limit 1)"
    elif vch_id == 3:    # 成品转库
        store = str(batch.store_to_id)        
        store_fr = "coalesce(" + str(store_fr_id_o) + "," + \
                "(select store_id from "+t_stk+" 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 "+t_stk+" where voucher_type='grn' " + \
                "and  label_code=a.label_code and store_id is not null order by id desc limit 1))" 
        # 2022-10-19
        #store_fr = "coalesce(" + str(store_fr_id_o) + "," + \
        #        "(select store_id from "+tb_stk+" where voucher_type='gtn' " + \
        #        "and  label_code=a.label_code and store_id is not null  limit 1)," + \
        #        "(select store_id from "+tb_stk+" where voucher_type='grn' " + \
        #        "and  label_code=a.label_code and store_id is not null  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 "+t_stk+" 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 "+t_stk+" where vtype_id="+str(vch_id)+\
                        " and company_id="+str(c.id)+" and label_code=b.label_code),0)"+\
                    ">coalesce("+\
                    "(select max(id) from "+t_stk+" where vtype_id=4 "+\
                        " and company_id="+str(c.id)+" and label_code=b.label_code),0)"   
                # 2022-10-19
                #s="update logistics.inventory_batchdetails b set err='此标签已于'||("+\
                #    "select to_char(tm,'yyyy-mm-dd HH24:MI:SS') from "+tb_stk+" 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 "\
                #    "coalesce((select max(id) from "+tb_stk+" where vtype_id="+str(vch_id)+\
                #        " and company_id="+str(c.id)+" and label_code=b.label_code),0)"+\
                #    ">coalesce("+\
                #    "(select max(id) from "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+t_stk+" 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 "+t_stk+" 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 "
                # 2022-10-19
                #s="update logistics.inventory_batchdetails b set err='此标签已于'||("+\
                #        "select to_char(tm,'yyyy-mm-dd HH24:MI:SS') from "+tb_stk+" where "+\
                #        "vtype_id="+str(vch_id)+" and company_id="+str(c.id)+\
                #        " and is_delete=false and label_pk_id=b.label_pk_id "+\
                #        "  limit 1)||'"+rmk+"' "+\
                #    " where batch_id="+b_id+" and err is null "\
                #    " and (select tm from "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+"(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 "+tb_stk+" (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 "+tb_stk+" (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 "+tb_stk+" (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 "+tb_stk+"(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 and agent_id != 157124): 
                if r[0]:  
                    tm=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')      
                    
                    if tm>'2021-12-01 00:00:00':
                        # 2023-6-17
                        # 重复发货，stk表没数据则不调用
                        cur.execute("select count(*) from stkdetails.c1 where batch_id = "+str(batch.id))
                        rs = cur.fetchone()
                        if rs[0] > 0:
                            #2021-12-14
                            #异步任务服务器发送 汉得
                            result=tasks.post_hand.delay({
                                'batch':{'id':batch.id,'code':batch.code},
                                'actions':['relations','delivery'],
                                'orderType':'03'
                            }) 
                            
        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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+"(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 "+tb_stk+" 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 "+tb_stk+"(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 "+tb_stk+" 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 "+tb_stk+" set dt='"+dt0+"',tm='"+tm0+"' where batch_id="+b_id)

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




    # 2022-11-03 是否有产品生产批次管理（保质期）  
    try:       
        if cmp_id in [19267,] and vch_id==1:
            # 19267;"易臻生物科技（上海）有限公司"
            if batch_no:
                no=batch_no
            else:
                no=batch.code        
            s="INSERT INTO batchlot.c"+str(cmp_id)+"("+\
                    "product_id,batch_no,label_code,label_pk_id,label_id,label_pkg,dt_inbound,user_id,vtype_id"+\
                ") select "+\
                    "product_id,'"+no+"',label_code,label_pk_id,label_id,label_pkg,dt,"+str(usr_id)+",1 "+\
                "from "+tb_stk+" where batch_id="+b_id
            cur.execute(s)
    except Exception as e:
        #print('错误类型是',e.__class__.__name__)#except:#jia
        #print('错误明细是',e.__class__.__name__,e)   #continue#jia
        ff=open('F:\\hzy\\log\\err.txt','a+')
        ff.write(str(e)+'\n')
        ff.close()



    
    #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.ancestor_id ==19318:
            #宴席活动发货 只区分一级和终端 除了一级经销商意外全部默认为终端去要确认收货
            s = "select count(*) from company_company where ancestor_id = 19318 and level_id !=2  and  id = "+str(batch.company_to_id)
            cur.execute(s)
            is_t = cur.fetchone()

            # 是否是宴席活动产品
            s = "select products  from sales_channelpromotions  WHERE company_id = 19318  and (triggers @> '[{\"id\":\"2\"}]' ::jsonb or triggers @> '[{\"id\":\"3\"}]' ::jsonb)"+\
                " and    NOW() BETWEEN tm_start and tm_end  and products  != '{}' and status = 1 and is_delete = false "
            cur.execute(s)
            ps = cur.fetchall()
            pro_products=[]
            sAnd=""
            if ps :
                for i in ps:
                    pro_products.append(i[0][0])
            if pro_products:
                sAnd = " and product_id in "+str(pro_products).replace('[','(').replace("]",")")
            if is_app:
                s = "SELECT count(*) from stkdetails.c19318 where ancestor_id = 19318 "+sAnd+" and batch_id = "+str(batch.id)
                cur.execute(s)
                p = cur.fetchone()
                if p :
                    if p[0] >0:
                        auto_inbound = False
            else:
                if batch.product_id in pro_products and is_t[0]>0:
                    auto_inbound = False                    
        #酒鬼公司发给内参，发货直接作为内参入库
        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 "+tb_stk+" (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:
                if c.ancestor_id == 19318:
                    # 是否已经做过收货确认
                    r = Receipt(ancestor_id=c.ancestor_id, company_id=c.id, batch_id=batch.id, user_id=int(usr_id))
                    r.save()
                #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 "+tb_stk+" (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 "+tb_stk+" 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 "+tb_stk+" a where batch_id="+str(batch.id)+" and (select id from "+tb_stk+""+\
        #        " 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 "+tb_stk+" where "+\
        #                " company_id="+c_id+" and vtype_id=1 and label_code=a.label_code) is null"
        #        cur.execute(sql)
        #        #stkdetails
        #        sql = "INSERT INTO "+tb_stk+" (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 "+tb_stk+" (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()   

    
    if vch_id == 2:
        try:
            if cmp_id in [20324]:
                stack_log(b_id,cmp_id)
        except Exception as e:
            with open ('C:\\Users\\frank\\Desktop\\stack_log\\stack_log.log','a+') as f :
                f.write(str(e))
    
    #2021-04-01 垛标数据处理
    if stacks:
        s=''
        if vch_id==1:
            s="INSERT INTO inventory_stackdetails(company_id,product_id,label_pk_id,label_id,label_pkg,label_code,tm,stack_id) "+\
                "select company_id,product_id,label_pk_id,label_id,label_pkg,label_code,now(),stack_id "+\
                "from "+tb_stk+" 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 "+tb_stk+" where batch_id="+str(batch.id)+" and  label_pk_id=a.label_pk_id limit 1)>0"
        if s:
            cur.execute(s)
    
    # 更新垛标下箱标数量
    if vch_id == 1 and stack_binding:
        cur.execute("(select count(*)lmt,stack_id from inventory_stackdetails  "
                    " where label_pk_id in (select label_pk_id from "+tb_stk+" where batch_id = " + str(
            batch.id) + ")   GROUP BY stack_id  )")
        rs = cur.fetchall()
        if rs:
            for r in rs:
                cur.execute("update inventory_stack set qty_lmt = " + str(r[0]) + " where id = " + str(r[1]))
    
    #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 "+tb_stk+" WHERE "
            	"label_code in (SELECT label_code from "+tb_stk+" 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)

    aid=str(request.user.company.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)
    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
    """

    # 2022-10-29 stkdetails分表
    tb_stk='stkdetails.c'+aid

    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 "+tb_stk + 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 "+tb_stk + 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 "+tb_stk + 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 "+tb_stk + 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 "+tb_stk + 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 "+tb_stk + 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
    
    

    # 2022-10-29 stkdetails分表
    tb_stk="stkdetails.c"+str(ancestor_id)


    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 company_id=='111072':
                    clmns = ['上传时间', '生产批次', '产品名称', '仓库名称', '操作人', package_units[2], package_units[1],
                             package_units[0], '备注']
            

        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 company_id == '19267':
                clmns.append("批次信息")
                clmns.append("是否收货")
            if company_id=='111072':
                clmns = ['上传时间', '单据编号', '客户名称', '产品名称', '仓库名称', '操作人', package_units[2], package_units[1],
                         package_units[0], '备注']              
        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 coalesce(last_name,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 "+tb_stk+" 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 ,"+\
            "b.remark "+\
            "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,remark "+\
                "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 "+tb_stk+" "+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 "+tb_stk+" "+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] ])
                if company_id=='111072':
                    remark=''
                    if r[19]:
                        remark=r[19]
                    data.append([tm, r[1], r[2], r[3], r[4], r[5], r[6], r[7], remark])
            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:
                        if company_id =='19267':
                            # 易臻显示是否确认收货
                            is_receipt = '是' if Receipt.objects.filter(batch__id=r[10]) else '否'
                            btn = '<button style="margin:0;padding:1px 10px;" onclick="catDetails(this)" class="update btn btn-sm btn-warning">详情</button>'
                            data.append([tm, r[1], r[8], r[2], r[3], r[4], r[5], r[6], r[7], btn, is_receipt])
                        elif company_id=='111072':
                            remark=''
                            if r[19]:
                                remark=r[19]
                            data.append([tm, r[1], r[8], r[2], r[3], r[4], r[5], r[6], r[7], remark])
                        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','')

    # 2022-10-29 stkdetails分表
    aid=str(u.company.ancestor_id)
    tb_stk="stkdetails.c"+aid

    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 "+tb_stk+" 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 "+tb_stk+" 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:
            package_units = get_package_name(u.ancestor_id)
            for r in cur.fetchall():
                if show_orig:
                    data['dataset'].append([ r[0],r[1],r[2],r[3] ])
                else:
                    lp = r[2]
                    if lp == '箱标':
                        lp = package_units[2]
                    elif lp == '盒标':
                        lp = package_units[1]
                    elif lp == '瓶标':
                        lp = package_units[0]
                    data['dataset'].append([ r[1],lp,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):
    # 2023-01-14
    usr=request.user

    # 2022-10-29 stkdetails分表
    aid=str(request.user.company.ancestor_id)
    tb_stk="stkdetails.c"+aid

    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,is_delete=False).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,''), "+\
            "coalesce(remark,'')"+\
            "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],'remark':r[18]
            }      
            #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','')    
        #2023-05-06
        remark=request.POST.get('remark','')    
        
        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
        if remark:
            b.remark=remark
        else:
            b.remark=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 "+tb_stk+" 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 "+tb_stk+" 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()



        
        #if True:
        # 2023-01-14 保存修改到系统日志 sys_log(user, obj, action='edit') 为了保证上传数据都能原样保存inventory.Batch没有使用外键 
        try:
            d=b.changed_data
            aFld=[]
            dWhat={
                'product_id':'product_product',
                'store_fr_id':'inventory_storehouse',
                'store_to_id':'inventory_storehouse',
                'company_to_id':'company_company'
            }
            for f in d:
                if f in dWhat:
                    aFld.append("'"+f+"',row("+\
                        "(select name from "+dWhat[f]+" where id="+str(d[f]['old']['value'])+"),"+\
                        "(select name from "+dWhat[f]+" where id="+str(d[f]['new']['value'])+")"+\
                    ")")
            aFld.append(
                "'vtype_id',(select name from inventory_voucher where id=vtype_id),"+\
                "'qty',(select json_build_object('x',sum(d.x),'h',sum(d.h),'p',sum(d.p)) from "+\
                    "(select 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 "+tb_stk+" a where batch_id="+str(b.id)+") d)"
            )
            s="select json_build_object("+",".join(aFld)+") from inventory_batch where id="+str(b.id)
            cur.execute(s)
            dct=cur.fetchone()[0]
            for f in d:
                if f in dct:
                    d[f]['old']['display']=dct[f]['f1']
                    d[f]['new']['display']=dct[f]['f2']
            d['vtype_id']={
                'title':'单据类型',
                'new':{'value':dct['vtype_id'],'display':dct['vtype_id']},
                'old':{'value':dct['vtype_id'],'display':dct['vtype_id']}
            }
            qty=''
            if dct['qty']['x']:
                qty=str(dct['qty']['x'])+'箱'
            if dct['qty']['h']:
                qty=str(dct['qty']['h'])+'盒'
            if dct['qty']['p']:
                qty=str(dct['qty']['p'])+'瓶'
            d['qty']=qty
            l=Log(ancestor_id=usr.ancestor_id, company_id=usr.company_id, user_id=usr.id, object_id=b.id, contenttype_id=19, action_id=3, changed_data=d)
            l.save()
        except Exception:
            pass




        #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()

               
                #'orderType':'03'
                if (r and agent_id != 157124): 
                    if r[0]:                                     
                        # 2023-6-17
                        # 重复发货，stk表没数据则不调用
                        cur.execute("select count(*) from stkdetails.c1 where batch_id = "+str(b.id))
                        rs = cur.fetchone()
                        if rs[0] > 0:
                            #2021-12-14
                            result=tasks.post_hand.delay({
                                'batch':{'id':b.id,'code':b.code},
                                'actions':['relations','delivery'],
                                'orderType':'03'
                            })   
            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']
                })

                # 2023-07-13                
                #print("id:",b.id, 'rmk:',b.rmk_name)
                if b.rmk_name:
                    if b.rmk_name[-2:]=='赋码':
                        result=tasks.post_hs.delay({
                            'batch':{'id':b.id,'code':b.code},
                            'actions':['delivery']
                        })
                        #print(result)

                #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','') 

    # 2022-10-29 stkdetails分表
    # aid=s


    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:
        
        # 2022-10-29 stkdetails分表
        batch=Batch.objects.get(id=int(batch_id))
        aid=str(batch.ancestor_id)
        tb_stk="stkdetails.c"+aid

        cur.execute("select count(*) from "+tb_stk+" 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 "+tb_stk+" WHERE batch_id = "+batch_id+") and package_id=1");
        r = cur.fetchone()
        if r[0] == 0:
            cur.execute(f"""
                select count(*) from label.labelinfo where parent_id in (
                    select id from label.labelinfo where parent_id in (
                        SELECT label_id from {tb_stk} 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
def inventory_html(request, what):    
    if what == 'label_query':
        package_units = get_package_name(request.user.ancestor_id)
        default_show_related=True
        if request.user.company_id in [19267]:
            # 2022-11-24 易臻默认不显示关联标物流信息
            default_show_related=False
        h = 'inventory/label_infor.html'
        return render(request, h,{'package_3':package_units[2],'package_2':package_units[1],'package_1':package_units[0],'default_show_related':default_show_related})
    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'

        # 2022-10-29 stkdetails分表
        tb_stk='stkdetails.c'+str(a_company_id)

        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 "+tb_stk+" "+\
                "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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" "+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)
    rs=json.loads(request.body)
    u_id=str(rs['user_id'])
    c_id=str(rs['company_id'])
    cur=connection.cursor()
    codes=[]
    src=json.dumps(rs['codes'])
    # 2022-12-02 酒鬼标签替换可能会传防伪
    fws=[]
    fwwl={}
    for r in rs['codes']:
        if int(c_id) in [1,1644]:
            # 酒鬼和内参，二维码是防伪码的情况,号段400
            if r[0][0]=='4' and {'id':1,'label':r[0]} not in fws:  
                fws.append({'id':1,'label':r[0]})
            if r[1][0]=='4' and {'id':1,'label':r[1]} not in fws:  
                fws.append({'id':1,'label':r[1]})
    if fws:       
        tm=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        m2=hashlib.md5((settings.INTERNAL_SK+tm).encode('utf8'))
        key=m2.hexdigest()
        rr = requests.post(settings.INTERNAL_URL + '/wl/', json={'key': key, 'time': tm, 'labels': fws})
        if rr.status_code == 200:
            d = json.loads(rr.text)                        
            for cc in d['data']:
                if cc['code']:                    
                    fwwl[cc['label']]=cc['code']   
    for r in rs['codes']:
        c_o=r[0]
        c_n=r[1]
        if fwwl:
            if r[0] in fwwl:
                c_o=fwwl[r[0]]
            if r[1] in fwwl:
                c_n=fwwl[r[1]]
        codes.append("('"+c_o+"','"+c_n+"')")          

    
    #cur.execute("create temp table tmp(code0 character varying(20),code character varying(20))")
    # 2023-07-18 添加label_pkg,label_pkg0字段
    cur.execute("create temp table tmp(code0 character varying(20),code character varying(20),code0_pkg smallint,code_pkg smallint)")


    cur.execute("insert into tmp(code0,code) values "+",".join(codes))
    # 写入BATCH    
    # 2023-07-19 是否有备注说明
    rmk='null'
    if 'remark' in rs:
        if rs['remark']:
            rmk="'"+rs['remark']+"'"
    s = "insert into label.lbl_replace_batch(user_id,company_id,txt_file,src,remark) values " + \
            "(" + u_id + "," + c_id + ",'扫码枪上传','"+src+"',"+rmk+") 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)
   
    # 2023-07-18 更新label_pkg和label_pkg0,用于比较新旧标签类型是否一致
    # 常规情况下，查询号段表
    s="select left(code0,4) from tmp group by left(code0,4)"
    cur.execute(s)
    rs=cur.fetchall()
    for r in rs:
        if r[0].isdigit():            
            t="label.t"+r[0]
            # 基础表是否存在
            cur.execute("select count(*) from information_schema.tables where table_schema='label' and table_type='BASE TABLE' and  table_name='t" +r[0]+"'")
            rr=cur.fetchone()
            if rr[0]:
                s="update tmp t set code0_pkg=(select package_id from "+t+" where code=code0) "+\
                    "where left(code0,4)='"+r[0]+"'"  
                cur.execute(s)        
    s="select left(code,4) from tmp group by left(code,4)"
    cur.execute(s)
    rs=cur.fetchall()
    for r in rs:
        if r[0].isdigit():            
            t="label.t"+r[0]
            # 基础表是否存在
            cur.execute("select count(*) from information_schema.tables where table_schema='label' and table_type='BASE TABLE' and  table_name='t" +r[0]+"'")
            rr=cur.fetchone()
            if rr[0]:
                s="update tmp t set code_pkg=(select package_id from "+t+" where code=t.code) "+\
                    "where left(code,4)='"+r[0]+"'"  
                cur.execute(s)  
    # 如酒鬼，标签可能在酒鬼跨段表
    if c_id=='1':
        t='label.lbl_binding_jg'
        s="update tmp t set code_pkg=(select package_id from "+t+" where code=t.code) where code_pkg is null"  
        cur.execute(s)
        s="update tmp t set code0_pkg=(select package_id from "+t+" where code=t.code0) where code0_pkg is null"  
        cur.execute(s)



    # 是否为盖内码 100;"盖内码"
    aCodes=[]
    cur.execute("select code0 from tmp where left(code0,1) in ('h','g')")
    for r in cur.fetchall():
        if decrypt_11h(r[0]):
            aCodes.append("'"+r[0]+"'")   
    if aCodes:
        s="update tmp set code0_pkg=100 where code0 in ("+",".join(aCodes)+")"
        cur.execute(s)
    aCodes=[]
    cur.execute("select code from tmp where left(code,1) in ('h','g')")
    for r in cur.fetchall():
        if decrypt_11h(r[0]):
            aCodes.append("'"+r[0]+"'")        
    if aCodes:
        s="update tmp set code_pkg=100 where code in ("+",".join(aCodes)+")"
        cur.execute(s)

    s="INSERT INTO label.lbl_replace_details(code0,code,batch_id,company_id,code0_pkg,code_pkg) "+\
        "select code0,code,"+id+","+c_id+",code0_pkg,code_pkg 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])

        # 2022-11-15 直接从tmp写入不做任何其它动作及检查
        s = "INSERT INTO label.lbl_replace_log(code0, code, batch_id, company_id) " + \
            "select code0,code," + id + "," + c_id + " from tmp"
        cur.execute(s)
        s = "INSERT INTO label.lbl_replace_details(code0, code, batch_id, company_id) " + \
            "select code0,code," + id + "," + c_id + " from tmp"
        cur.execute(s)
        tt=cur.rowcount
        ok=tt

        '''
        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)+",tm_handled=now() 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)

    # 2022-10-29 stkdetails分表
    aid=str(b.ancestor_id)
    tb_stk="stkdetails.c"+aid

    # 2022-12-15 酒鬼酒、内参防伪码转物流码
    if str(b.ancestor_id) in ("1","1644"):
        fws=[] #保存防伪码
        cur.execute("select id,label_code from inventory_batchdetails where batch_id="+batch_id+" and left(label_code,2)='40'")
        for r in cur.fetchall():            
            fws.append({'id':r[0],'label':r[1]})
        if fws:       
            cur.execute("create temp table fg_fw("+\
                    "id integer,"+\
                    "fw character varying(32),"+\
                    "wl character varying(32)"+\
                ")"
            )
            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("("+str(cc['id'])+",'" + cc['label'] + "','" + cc['code'] + "')")
                if a:
                    cur.execute("insert into fg_fw(id,fw,wl) values " + ",".join(a))            
                    s="update inventory_batchdetails b set label_code=coalesce("+\
                        "(select wl from fg_fw where id=b.id),label_code) "+\
                        "where batch_id="+batch_id+"  and left(label_code,2)='40'"
                    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 "+tb_stk+" where batch_id="+batch_id)


    if b.vtype_id==5:
        sql = "INSERT INTO "+tb_stk+" (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 "+tb_stk+" 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 "+tb_stk+" where vtype_id=1 and label_pk_id=b.label_pk_id limit 1) is not null"
    else:
        sql = "INSERT INTO "+tb_stk+" (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 "+tb_stk+" 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]
        # 2022-10-29 stkdetails分表
        aid=str(b.company.ancestor_id)
        tb_stk="stkdetails.c"+aid


        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 "+tb_stk+" 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 "+tb_stk+" 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]   
    
    # 2022-10-29 stkdetails分表
    aid=str(company.ancestor_id)
    tb_stk="stkdetails.c"+aid


    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)
   
    abWhere = ''
    if q.infor['label_a'] and q.infor['label_b']:
        abWhere =" or label_code in ('"+q.infor['label_a']+"','"+q.infor['label_b']+"') "
    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 "+tb_stk+" 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]

    package_units = get_package_name(company.ancestor_id)
    parent_id=q.get_parent_id()
    if not parent_id:
        parent_id = 0
    data['parent_id']=parent_id
    data['label_id']=q.infor['label_id']


    # 2023-06-08
    # 如茗酒荟业务员可以替经销商做分销,若当前标签库存在其它经销商,可以借货出库
    # 接口返回当前产品所在经销商信息 只允许借箱 
    if int(vtype_id)==2 and q.package['id']==3:
        # 发货明细按id倒排序，取最后一次发货记录 且经销商不是当前经销商
        s="select label_code,to_char(tm,'yyyy-mm-dd HH24:mi:ss'),id,name,level_id,"+\
            "(select name from company_level where id=level_id),parent_id,"+\
            "(select name from company_company where id=c.parent_id) "+\
            "from "+\
            "(select label_code,tm,company_to_id from "+tb_stk+" "+\
                "where label_pk_id="+lbl_pk_id+" and vtype_id=2 and is_delete=false and label_pkg=3 "+\
                "order by id desc limit 1"+\
            ") d "+\
            "left outer join "+\
            "(select id,name,level_id,parent_id from company_company where ancestor_id="+aid+") c "+\
            "on d.company_to_id=c.id "+\
            "where company_to_id<>"+c_id       
        cur.execute(s)
        rr=cur.fetchone()
        if rr:            
            data['location']={
                'dt_delivery':rr[1],
                'agent':{
                    'id':rr[2],
                    'name':rr[3],
                    'level':{
                        'id':rr[4],
                        'name':rr[5]
                    },
                    'parent':{
                        'id':rr[6],
                        'name':rr[7]
                    }
                }
            }                



    if vtype_id in ['1','2']:
        #箱标,瓶标同一标签都只能入/出一次
        s="select label_pkg,tm from "+tb_stk+" where vtype_id="+vtype_id+\
            " and label_code='"+c+"' and company_id="+c_id
        s="select label_pkg,tm,"+\
            "(select vtype_id from "+tb_stk+" where company_id="+c_id+" and ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '"+ c +"' or ( label_pkg = 2 AND label_id = "+str(parent_id)+" ) ) order by id desc limit 1) "+\
            "from "+tb_stk+" where vtype_id="+vtype_id+\
            " and ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '"+ c +"' or ( label_pkg = 2 AND label_id = "+str(parent_id)+" )) and company_id="+c_id
        s = "select label_pkg,tm," + \
            "(select vtype_id from " + tb_stk + " where company_id=" + c_id + " and ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '" + c + "' "+ abWhere+" or ( label_pkg = 2 AND label_id = " + str(
            parent_id) + " ) ) order by id desc limit 1) " + \
            "from " + tb_stk + " where (select vtype_id from " + tb_stk + " where company_id=" + c_id + " and ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '" + c + "' "+ abWhere+" or ( label_pkg = 2 AND label_id = " + str(
            parent_id) + " ) ) order by id desc limit 1) =" + vtype_id + \
            " and ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '" + c + "' "+ abWhere+" or ( label_pkg = 2 AND label_id = " + str(
            parent_id) + " )) and company_id=" + c_id
        sAnd = ' and company_id = ' + c_id
        if int(vtype_id) == 2 and company.ancestor_id == 19318:
            if company.level_id ==1:
                sAnd = ' and company_id = '+c_id
            elif company.level_id == 2:
                # 一级经销商发货模式
                if cfg.outbound_cretiria_lv1 == 0:
                    # 严格
                    sAnd = ''
                else:
                    # 宽松
                    sAnd = ' and company_id = ' + c_id
            else:
                sAnd = ' and company_id = ' + c_id
        else:
            sAnd = ' and company_id = ' + c_id
        
        s = "select label_pkg,tm," + \
            "(select vtype_id from " + tb_stk + " where   ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '" + c + "' " + abWhere + " or ( label_pkg = 2 AND label_id = " + str(
            parent_id) + " ) ) "+ sAnd + " order by id desc limit 1) " + \
            "from " + tb_stk + " where (select vtype_id from " + tb_stk + " where   ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '" + c + "' " + abWhere + " or ( label_pkg = 2 AND label_id = " + str(
            parent_id) + " ) ) "+ sAnd + " order by id desc limit 1) =" + vtype_id + \
            " and ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '" + c + "' " + abWhere + " or ( label_pkg = 2 AND label_id = " + str(
            parent_id) + " ))  " + sAnd
        #print(s)
        cur.execute(s)
        r=cur.fetchone()
        if r:
            if r[2] == 4:
                return JsonResponse(data)
            #最后一次不是销售退库,也不是标签退库
            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)
        else:
            if int(vtype_id) == 2 and company.ancestor_id == 19318:
                if company.level_id == 2:
                    s = "select label_pkg,tm," + \
                        "(select vtype_id from " + tb_stk + " where   ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '" + c + "' " + abWhere + " or ( label_pkg = 2 AND label_id = " + str(
                        parent_id) + " ) ) " + sAnd + " order by id desc limit 1) " + \
                        "from " + tb_stk + " where (select vtype_id from " + tb_stk + " where   ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '" + c + "' " + abWhere + " or ( label_pkg = 2 AND label_id = " + str(
                        parent_id) + " ) ) " + sAnd + " order by id desc limit 1) =" + vtype_id + " and ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '" + c + "' " + abWhere + " or ( label_pkg = 2 AND label_id = " + str(
                        parent_id) + " ))  " + sAnd

                    s ="SELECT a.*,b.level_id,(select vtype_id from " + tb_stk + " where   ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") " +\
                       "or label_code = '" + c + "' " + abWhere + " or ( label_pkg = 2 AND label_id = " + str(parent_id) + " ) )order by tm DESC limit 1) from (SELECT company_id,vtype_id,tm "+ \
                       " from " + tb_stk + " where   ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") " +\
                       "or label_code = '" + c + "' " + abWhere + " or ( label_pkg = 2 AND label_id = " + str(parent_id) + " ) ) and vtype_id = 2  and tm > (select tm from " + tb_stk + " where   " +\
                        "((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '" + c + "' " + abWhere + " or ( label_pkg = 2 AND label_id = " + str(
                        parent_id) + " ) )  and company_id = 19318 and vtype_id = 2  order by id desc limit 1)order by id desc ) A "+\
                        " left outer JOIN (SELECT id,level_id from logistics.company_company )b on b.id =a.company_id "+\
                        "where b.level_id = 2 and vtype_id not in (4 ,40) "
                    cur.execute(s)
                    r = cur.fetchone()
                    if r :
                        if r[4] !=4 and r[4]!=40:
                            t1 = _('此标签已出库')
                            data['err_code'] = 10001
                            data['e'] = t1 + '(' + r[2].strftime('%Y-%m-%d %H:%M:%S') + ')'
                            return JsonResponse(data)
                        if r[4] == [40]:
                            t1 = _('此标签已做退货处理')
                            data['err_code'] = 10001
                            data['e'] = t1 + '(' + r[2].strftime('%Y-%m-%d %H:%M:%S') + ')'
        #2021-07-29 工厂用小程序入库出库标签检查
        if company.level.sn==0:
            
            
            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 "+tb_stk+" where vtype_id=1 and label_pk_id="+lbl_pk_id+" and company_id="+c_id
                if company.ancestor_id == 19318:
                    s = "select id from " + tb_stk + " where ((vtype_id=1 and label_pkg= 3 and label_pk_id=" + lbl_pk_id + ") or" + \
                        " (vtype_id=1 and label_pkg= 1  and (label_code = '" + c + "'" + abWhere + " ))) and company_id=" + c_id
                else:
                    s = "select id from " + tb_stk + " where vtype_id=1 and label_pk_id=" + lbl_pk_id + " and company_id=" + c_id
                cur.execute(s)
                r=cur.fetchone()
                
                if company.ancestor_id == 19318:
                    if company.level_id==2:
                        if cfg.outbound_cretiria_lv1==0:
                            if not r:
                            #if cfg.lv1_pkg_split==0:
                                data['e'] = _('此'+package_units[0]+'所在箱没有入库记录')
                                data['err_code']=10002
                                return JsonResponse(data)
                    else:   
                        if cfg.outbound_cretiria_lv2 == 0:
                            if not r:
                                # if cfg.lv1_pkg_split==0:
                                data['e'] = _('此' + package_units[0] + '所在箱没有入库记录')
                                data['err_code'] = 10002
                                return JsonResponse(data)
                else:
                    if cfg.outbound_cretiria_lv2==0:
                        if not r:
                            #if cfg.lv1_pkg_split==0:
                                data['e'] = _('此'+package_units[0]+'所在箱没有入库记录')
                                data['err_code']=10002
                                return JsonResponse(data)
                #所在箱或者盒是否出过库
                # cur.execute("select label_code,tm from "+tb_stk+" where vtype_id=2 and label_pkg=3 and label_pk_id="+lbl_pk_id+" and company_id="+c_id)
                if company.ancestor_id == 19318:
                    #诗仙太白退库后重新发  如果当前公司最后一条记录为退库
                    s = "select * from (select label_code,tm,(select vtype_id from " + tb_stk + " where   ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") " +\
                       "or label_code = '" + c + "' " + abWhere + " or ( label_pkg = 2 AND label_id = " + str(parent_id) + " ) )order by tm DESC limit 1),(select tm from " + tb_stk + " where   ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") " +\
                       "or label_code = '" + c + "' " + abWhere + " or ( label_pkg = 2 AND label_id = " + str(parent_id) + " ) )order by tm DESC limit 1) from " + tb_stk + " where vtype_id=2 and ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '" + c + "' or ( label_pkg = 2 AND label_id = " + str(
                        parent_id) + " ) ) and company_id=" + c_id+" )a"
                    cur.execute(s)
                    r = cur.fetchone()
                    if r :
                        if (r[2] !=4 or r[2] !=40) and r[3] < r[1]:
                            data['e'] = _(
                                '此标签或包含此' + package_units[0] + '的' + package_units[2] + '标/' + package_units[
                                    1] + '标已出库') + '(' + r[0] + ":" + r[1].strftime('%Y-%m-%d %H:%M:%S') + ')'
                            data['err_code'] = 10001
                            return JsonResponse(data)
                else:
                    cur.execute(
                            "select label_code,tm from "+tb_stk+" where vtype_id=2 and ((label_pkg=3 and label_pk_id=" + lbl_pk_id + ") or label_code = '"+ c +"' or ( label_pkg = 2 AND label_id = "+str(parent_id)+" ) ) and company_id=" + c_id)
                    
                    r=cur.fetchone()
                    if r:
                        data['e'] = _('此标签或包含此'+package_units[0]+'的'+package_units[2]+'标/'+package_units[1]+'标已出库') + '(' + r[0] + ":" + r[1].strftime('%Y-%m-%d %H:%M:%S') + ')'
                        data['err_code']=10001
                        return JsonResponse(data)

        # 2022-09-13 盒标
        elif data['package_id']==2:
            # 所在箱标是否已有相同操作
            cur.execute("select label_code,tm,(select remark from inventory_voucher where id=vtype_id) "+\
                "from "+tb_stk+" where vtype_id="+vtype_id+" and ((label_pkg=3 and label_pk_id="+lbl_pk_id+") or label_code ='"+ c +"') and company_id="+c_id)
            r=cur.fetchone()
            if r:
                data['e'] = '此标签或包含此'+package_units[1]+'的'+package_units[2]+'标已' + r[2] + '(' + 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 "+tb_stk+" where company_id="+c_id+" and label_pk_id="+lbl_pk_id+" and (label_pkg =3 or label_pkg=4) order by id desc limit 1) "+\
                " from "+tb_stk+" where vtype_id="+vtype_id+" and label_pk_id="+lbl_pk_id+" and company_id="+c_id
            s = "select label_pkg,tm," + \
                "(select vtype_id from " + tb_stk + " where company_id=" + c_id + " and label_pk_id=" + lbl_pk_id + " and (label_pkg =3 or label_pkg=4) order by id desc limit 1) " + \
                " from " + tb_stk + " where (select vtype_id from " + tb_stk + " where company_id=" + c_id + " and label_pk_id=" + lbl_pk_id + " and (label_pkg =3 or label_pkg=4) order by id desc limit 1) =" + vtype_id + " and label_pk_id=" + lbl_pk_id + " and company_id=" + c_id
            
            #print(s)
            cur.execute(s)
            r=cur.fetchone()
            if r:
                #最后一次不是盒标、瓶标、销售退库,也不是标签退库
                if r[0] in [3,4] and 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" where company_id="+c_id+" and label_pk_id="+lbl_pk_id+" order by id desc limit 1) "+\
                #    "from "+tb_stk+" 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 "+tb_stk+" 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
        
        #print(parent_id)
        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]
        #首先判断是否已有退货记录 
        swhere = ''
        if data['package_id'] == 1:
            swhere = f"company_id={c_id} and vtype_id=4 and (label_code='{data['code']}' or (label_pk_id={lbl_pk_id} and label_pkg = 3) or (label_id = {parent_id})) "
        else:
            swhere = f"company_id={c_id} and vtype_id=4 and label_pk_id = {lbl_pk_id} and is_delete=false "
        s="select a.id,a.label_code,a.label_pkg,to_char(a.tm,'yyyy-mm-dd HH24:MI:SS'),"+\
            "(select max(id) from "+tb_stk+" 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 "+tb_stk+" where "+swhere+\
                " order by id desc limit 1"+\
            ") a"                
        cur.execute(s)
        #print(s)
        r=cur.fetchone()        
        if r:
            #有退货
            #Jonathan调整与2022-09-13
            if r[0]>r[4]:
                #如果是瓶标
                if data['package_id']==1:
                    if r[1]==c:
                        data['e']=f'此{package_units[0]}已于{r[3]}退货'
                    elif r[2]==2:
                        data['e']=f'此{package_units[0]}所在{package_units[1]}已于'+r[3]+"退货"
                    elif r[2]==3:
                        data['e']=f'此{package_units[0]}所在{package_units[2]}已于'+r[3]+"退货"
                #如果是盒标
                elif data['package_id']==2:
                    if r[1]==c:
                        data['e']=f'此{package_units[1]}已于'+r[3]+"退货"
                    elif r[2]==3:
                        data['e']=f'此{package_units[1]}所在{package_units[2]}已于'+r[3]+"退货"
                #箱标，单枚标 
                elif data['package_id'] in (3,4): 
                    if r[2] in (3,4):
                        data['e']=f'此{package_units[2]}已于'+r[3]+"退货"
                    #elif r[2]==1:
                        #data['e']='此箱已有瓶标于'+r[3]+"退货"
                if data['e'] !='': 
                    data['err_code']=10004    
                    return JsonResponse(data)   
        #(0, _('严格(必须是发给当前终端的产品)')),
        #(1, _('中等(经销商有发货记录)')), 
        #(2, _('不限制')),),default=2) 
        err=''
        if data['package_id']==1:
            p=package_units[0]
        elif data['package_id']==2:
            p=package_units[1]
        else:
            p=package_units[2]
        if cfg.terminal_return==0: 
            err='此'+p+'没有给'+agent_name+'的发货记录'
            if data['package_id']==3:
                s="select tm from "+tb_stk+" where company_id="+c_id+" and vtype_id=2 and label_code='"+data['code']+"' and company_to_id="+str(agent_id)
            elif data['package_id']==2:
                s="select tm from "+tb_stk+" where company_id="+c_id+" and vtype_id=2 "+\
                    "and (label_code='"+data['code']+"' or (label_pk_id="+lbl_pk_id+" and label_pkg = 3)) and company_to_id="+str(agent_id)
            else:
                #检查箱标 或 盒标 或 当前标签
                s="select tm from "+tb_stk+" where company_id="+c_id+" and vtype_id=2 "+\
                    "and (label_code = '"+data['code']+"' or (label_pk_id="+lbl_pk_id+" and label_pkg = 3) "+\
                    "   or (label_pkg = 2 and label_id = "+str(parent_id)+") )"+\
                    "and company_to_id="+str(agent_id)
                #print(s)
        elif cfg.terminal_return==1:
            err='没有此'+p+'的发货记录'
            s="select tm from "+tb_stk+" where company_id="+c_id+" and vtype_id=2 "+\
                "and label_pk_id="+lbl_pk_id
        else:
            s="select 1"
        #print(s)
        cur.execute(s)
        r=cur.fetchone()
        if not r:
            data['err_code']=10005    
            data['e']=err
            return JsonResponse(data) 
        #2021-12-24 取最后一次发货经销
        s="select company_to_id from "+tb_stk+" 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 "+tb_stk+" 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:
        # 2022-11-07 stkdetails分表
        cur.execute("select ancestor_id from company_company where id="+str(company_id))
        rr=cur.fetchone()
        tb_stk='stkdetails.c'+str(rr[0]) 
        

        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 "+tb_stk+""+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 "+tb_stk+" "+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)+")"

        # 2022-10-29 stkdetail分表
        aid=str(c.ancestor_id)
        tb_stk="stkdetails.c"+aid

    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 "+tb_stk+" "+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 "+tb_stk+" "+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

        # 2022-10-29 stkdetail分表
        aid=str(c.ancestor_id)
        tb_stk="stkdetails.c"+aid


    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 "+tb_stk+" "+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 stkdetails.c1 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 stkdetails.c1 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 }}
    cur=connection.cursor()
    
    # 2022-10-29 stkdetails分表
    cur.execute("select ancestor_id from company_company where id="+str(company_id))
    r=cur.fetchone()
    aid=str(r[0])
    tb_stk="stkdetails.c"+aid

    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 "+tb_stk+" 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 "+tb_stk+" where   batch_id=a.id)"+\
            ") b order by b.tm"            
    
    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':[]}

    # 2022-10-29 stkdetails分表
    cur.execute("select ancestor_id from company_company where id="+str(company_id))
    r=cur.fetchone()
    aid=str(r[0])
    tb_stk="stkdetails.c"+aid

    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 "+tb_stk+" 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 "+tb_stk+" 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()

    # 2022-10-29 stkdetails分表
    #cur.execute("select ancestor_id from company_company where id="+str(company_id))
    #r=cur.fetchone()
    aid=str(request.user.company.ancestor_id)
    tb_stk="stkdetails.c"+aid

    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 "+tb_stk+" where  batch_id=e.batch_id) cnt,"+\
        "(select count(*) from "+tb_stk+" z where  batch_id=e.batch_id and product_id<>"+\
            "(select product_id from "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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()

    # 2022-10-29 stkdetails分表
    #cur.execute("select ancestor_id from company_company where id="+str(company_id))
    #r=cur.fetchone()
    aid=str(request.user.company.ancestor_id)
    tb_stk="stkdetails.c"+aid

    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 "+tb_stk+" 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 "+tb_stk+" a where batch_id="+id+" and "+\
                "product_id<>(select product_id from "+tb_stk+" 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})


    if company_id == 132080:
        return render(request, 'inventory/upload_inv_txt_jcs.html', data)
    else:
        return render(request, 'inventory/upload_inv_txt.html', data)    



#2020-04-22
#@login_required
@tj_login_required
def upload_inv_txt_old(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)
    

# 2023-03-01
# @login_required
@tj_login_required
def upload_inv_txt(request, is_app=False):
    data = {'files': [], 'e': ''}
    u = request.user
    c = u.company
    u_id = u.id
    c_id = u.company_id
    code = request.POST.get('code', '')
    dt = datetime.datetime.now()
    v_id = request.POST.get('voucher_id', '2')

    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')

    t = dt.strftime('%Y-%m-%d %H:%M:%S')
    m2 = hashlib.md5((sK + t).encode('utf8'))

    if c_id == 132080:
        err_file = []
        ok_file = []
        cnt = 0        
        url = 'https://davis.china315net.com/inventory/fg/update/'
        for f in files:
            fn = f.name
            type = fn.split('.')[-1]
            if type == 'txt' or type == 'TXT':
                with open(p + '/' + fn, 'wb+') as destination:
                    for chunk in f.chunks():
                        destination.write(chunk)
                f.seek(0)
                label = []
                code = ''
                agent_id = ''
                store_id = ''
                product_id = ''
                # 批次，经销商，产品，标签，仓库
                # 230131141854,12289,8034,502670699387,240
                with open(p + '/' + fn, 'r') as f:
                    line = f.readline()
                    if line:
                        text = line.split(',')
                        code = text[0]
                        agent_id = text[1]
                        store_id = text[4].strip('\n')
                        product_id = text[2]
                        label.append(text[3])
                    for l in f:
                        l = l.strip()
                        if l:
                            aa = l.split(',')
                            label.append(aa[3])
                if code and agent_id and store_id and product_id and label:
                    d = {
                        "bill_number": code,
                        "company_id": 132080,
                        "to_company_id": int(agent_id),
                        "user_id": u_id,
                        "product_id": int(product_id),
                        "voucher_id": int(v_id),
                        "voucher_time": t,
                        "codes": label,
                        "time": t,
                        "key": m2.hexdigest(),
                    }
                r = requests.post(url, json=d)
                if r.status_code == 200:
                    res = r.json()
                    ok_file.append(fn)
                    cnt += res['cnt']
            else:
                err_file.append(fn)
            # if err_file:
            #     data['e'] = ','.join(err_file) + ' 文件格式错误！'

            data['ok'] = ','.join(ok_file) + ' 已成功上传,共处理 '+str(cnt)+' 件 '
        return JsonResponse(data)
    else:
        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')
        p_id = request.POST.get('plant_id', '0')
        clmn = request.POST.get('column', '5')

        # 2021-05-06
        force = request.POST.get('force', '1')
        remark=''
        a = []
        if files:
            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)

        else:
            # 2023-07-15
            page_fr = request.POST.get('page_fr', 0)
            page_to = request.POST.get('page_to', 0)
            sWhere = " label_wrapper  between'" + page_fr + "' and '" + page_to + "'"
            remark="按标签页码出入库是从'" + page_fr + "' 到 '" + page_to + "'"
            cur = connection.cursor()
            s = f""" 
                select label_code from  label.lbl_overwrap where {sWhere}
                """
            cur.execute(s)
            for l in cur.fetchall():
                a.append(l[0])

        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 强制发货（不检查标签是否已有发货记录）
            "remark":remark,
        }
        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':_('')})
    # 2022-10-29 stkdetails分表
    # cur.execute("select ancestor_id from company_company where id="+str(company_id))
    # r=cur.fetchone()
    aid = str(request.user.company.ancestor_id)
    tb_stk = "stkdetails.c" + aid
    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'))  
        product_id=str(request.POST.get('product_id'))
        order_number=str(request.POST.get('order_number'))
        dt_fr=str(request.POST.get('dt_fr'))
        dt_to=str(request.POST.get('dt_to'))

        sAnd= ""
        a_s = []
        
        if   product_id != '0' :
            sAnd =sAnd+" and product_id = "+product_id
        if order_number:
            sAnd = sAnd+" and code = '" + order_number+"'"
        if dt_fr and dt_to:
            sAnd =sAnd+ " and (dt between '"+dt_fr+"' and '"+dt_to+"')"
        if order_number:
            cnt = 0
            s = "select id from logistics.inventory_batch where company_id="+id_o + sAnd
            cur.execute(s)
            rs = cur.fetchall()
            for r in rs:
                a_s = [
                    "update logistics.inventory_batchdetails set company_id=" + id_n + " where batch_id="+str(r[0]) ,
                    "update " + tb_stk + " set company_to_id=" + id_n + " where batch_id="+str(r[0]),
                    "update " + tb_stk + " set company_id=" + id_n + " where batch_id="+str(r[0]),
                    "update logistics.inventory_batch set company_to_id=" + id_n + " where id="+str(r[0]),
                    "update logistics.inventory_batch set company_fr_id=" + id_n + " where  id="+str(r[0]),
                    "update logistics.inventory_batch set company_id=" + id_n + " where id="+str(r[0])
                ]
                cnt = cnt +1
                for s in a_s:
                    cur.execute(s) 
                
        else:
            a_s = [
                "update logistics.inventory_batchdetails set company_id=" + id_n + " where company_id=" + id_o + sAnd,
                "update " + tb_stk + " set company_to_id=" + id_n + " where company_to_id=" + id_o + sAnd,
                "update " + tb_stk + " set company_id=" + id_n + " where company_id=" + id_o + sAnd,
                "update logistics.inventory_batch set company_to_id=" + id_n + " where company_to_id=" + id_o + sAnd,
                "update logistics.inventory_batch set company_fr_id=" + id_n + " where  company_fr_id=" + id_o + sAnd,
                "update logistics.inventory_batch set company_id=" + id_n + " where company_id=" + id_o + sAnd
            ]
            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}) 







#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:
        cid = str(request.user.company.id)
        #print(cid)
        d = {'labels': [], 'e': ''}
        f = request.FILES.get('file')
        l = f.read().decode().splitlines()
        for n in l:
            if (len(n)>0):
                d['labels'].append(n)
        for i in d['labels']:
            url = 'https://davis.china315net.com/label/app/'+cid+'/' + 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  经销商出入库查询
# 2022/9/28 Jonathan 重写查询逻辑
@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)

    # 2022-10-29 stkdetails分表
    #cur.execute("select ancestor_id from company_company where id="+str(company_id))
    #r=cur.fetchone()
    aid=str(request.user.company.ancestor_id)
    tb_stk="stkdetails.c"+aid
    
    if agent_id=="":
        sWhere="ancestor_id="+str(cid)+" and company_id != "+str(cid)+" and (dt between '"+dt_fr+"' and '"+dt_to+"')"
    else:
        sWhere="(company_id = "+agent_id+" or company_to_id = "+agent_id+") and (dt between '"+dt_fr+"' and '"+dt_to+"')"
            
    s = f"""
        SELECT 
            A.batch_id,
            to_char(b.tm,'yyyy-mm-dd HH24:MI:SS'),
            (select name from inventory_voucher where id = a.vtype_id),
            b.code,
            (select name from product_product where id = A.product_id),
            (select name from company_company where id = b.company_id),
            (select name from company_company where id = b.company_to_id),
            (select username from company_user where id = b.user_id),
            x,
            h,
            P,
            b.remark
        FROM
            (
            SELECT
                batch_id,
                product_id,
                vtype_id,
                SUM ( x ) x,
                SUM ( h ) h,
                SUM ( P ) P 
            FROM
                (
                SELECT
                    batch_id,
                    product_id,
                    vtype_id,
                    label_pkg,
                    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
                    {tb_stk} 
                WHERE {sWhere}) d 
        GROUP BY
            batch_id,
            product_id,
            vtype_id
            ) A 
        LEFT JOIN logistics.inventory_batch b ON A.batch_id = b.id
        order by batch_id
    """
        
    cur.execute(s)
    data=[]
    for r in cur.fetchall():
        data.append([
            "<a href='inventory/agent/details/" + str(r[0]) + "/'>" + r[1] + "</a>", # 日期
            r[2],  # 单据类别
            r[3],  # 单据编号
            r[4],  # 产品名称
            r[5],  # 操作方
            r[6],  # 客户名称
            r[7],  # 操作人
            r[8],  # 箱
            r[9],  # 盒
            r[10], # 瓶
            r[11], # 备注
        ])

    if agent_id=="":
        cur.close()
        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:
        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':[
            '箱','瓶',#入库
            '箱','瓶',#出库
            '箱','瓶',#退库
        ]
    }  

    # 2022-10-29 stkdetails分表
    #cur.execute("select ancestor_id from company_company where id="+str(company_id))
    #r=cur.fetchone()
    aid=str(request.user.company.ancestor_id)
    tb_stk="stkdetails.c"+aid


    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 "+tb_stk+" "+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 "+tb_stk+" "+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 "+tb_stk+" "+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 "+tb_stk+" "+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()
    
    # 2022-10-29 stkdetails分表
    #cur.execute("select ancestor_id from company_company where id="+str(company_id))
    #r=cur.fetchone()
    aid=str(request.user.company.ancestor_id)
    tb_stk="stkdetails.c"+aid

    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 "+tb_stk+" 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','')
        id_address= request.GET.get('id_address','')
       
        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:
                if r[0] and r[1]:
                    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]
                    })
            if id_address:
                david_ak = "TzSrPO5pkx7tt36nIfZwtUzRMgomAor6"
                jz_ak = "xAzoE0s7AzzGI27OLo49w9LIzavAqT2s"
                davis_ak = "QSVVHpVmZM381bd5nXDCfyevn63acGq4"
                aks = [
                    david_ak,
                    jz_ak,
                    davis_ak,
                ]
                ak = random.choice(aks)
                # 服务地址
                host = "https://api.map.baidu.com"

                # 接口地址
                uri = "/geocoding/v3"

                params = {
                    "address": id_address,
                    "output": "json",
                    "ak": ak,
                }


                response = requests.get(url=host + uri, params=params)
                if response:
                    r = response.json()
                    if r['status'] == 0:
                        center = {'lng': r['result']['location']['lng'], 'lat': r['result']['location']['lat']}
        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()    


    # 2022-10-29 stkdetails分表    
    aid=str(batch.company.ancestor_id)
    tb_stk="stkdetails.c"+aid

    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 "+tb_stk+" 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)

    # 2022-10-29 stkdetails分表    
    aid=str(c.ancestor_id)
    tb_stk="stkdetails.c"+aid



    
    # 2023-06-02 优先检查奖池布奖(箱标号码，1箱1个箱标),如果有，计算、生成返利后直接返回
    # 目前奖池返利只做一次返利操作
    try:
        #s="select s.promotion_id,s.label_code,s.label_pkg,s.label_id,s.label_pk_id,"+\
        #    "coalesce(case when r.amt_current_award=1 then s.terminal_rebate else r.amt_current_val end,0),"+\
        #    "coalesce(case when r.amt_parent_award=1  then s.agent_rebate  else   r.amt_parent_val  end,0),"+\
        #    "(select product_id from "+tb_stk+" where batch_id="+bid+" and label_code=s.label_code limit 1) "+\
        #    "from "+\
        #    "(SELECT promotion_id,terminal_rebate,agent_rebate,label_code,label_pkg,label_id,label_pk_id "+\
        #        "FROM sales_promotionseeds s where company_id="+aid+" and "+\
        #        "not exists (select id from sales_channelrebatedetails where label_code=s.label_code) and "+\
        #        "exists (select id from "+tb_stk+" where batch_id="+bid+" and label_code=s.label_code) and "+\
        #        "promotion_id in (select id from sales_channelpromotions where company_id="+aid+" and "+\
        #            "status=1 and ('"+t+"' between tm_start and tm_end) )"+\
        #    ") s "+\
        #    "left outer join "+\
        #    "(SELECT promotion_id,label_pkg,amt_current_award,amt_current_val,amt_parent_award,amt_parent_val "+\
        #        "FROM sales_customizerebate where trigger_lv="+str(c.level_id)+" and scan_type="+vid+" and "+\
        #        "(select company_id from logistics.sales_channelpromotions  where id=promotion_id)="+aid+\
        #    ") r "+\
        #    "on s.promotion_id=r.promotion_id"    

        # 2023-06-09 奖池布奖统一用B标布奖
        s="select s.promotion_id,s.label_code,s.label_pkg,s.label_id,s.label_pk_id,"+\
            "coalesce(case when r.amt_current_award=1 then s.terminal_rebate else r.amt_current_val end,0),"+\
            "coalesce(case when r.amt_parent_award=1  then s.agent_rebate  else   r.amt_parent_val  end,0),"+\
            "d.product_id "+\
            "from "+\
            "(select coalesce((select code_b FROM label.lbl_abcode where code_a=label_code),label_code) label_code,"+\
                "label_pkg,label_id,label_pk_id,product_id from "+tb_stk+" where batch_id="+bid+\
            ") d "+\
            "left outer join "+\
            "(SELECT promotion_id,terminal_rebate,agent_rebate,label_code,label_pkg,label_id,label_pk_id "+\
                "FROM sales_promotionseeds s where company_id="+aid+" and "+\
                "not exists (select id from sales_channelrebatedetails where label_code=s.label_code)  and "+\
                "promotion_id in (select id from sales_channelpromotions where company_id="+aid+" and "+\
                    "status=1 and ('"+t+"' between tm_start and tm_end) )"+\
            ") s "+\
            "on d.label_code=s.label_code "+\
            "left outer join "+\
            "(SELECT promotion_id,label_pkg,amt_current_award,amt_current_val,amt_parent_award,amt_parent_val "+\
                "FROM sales_customizerebate where trigger_lv="+str(c.level_id)+" and scan_type="+vid+" and "+\
                "(select company_id from logistics.sales_channelpromotions  where id=promotion_id)="+aid+\
            ") r "+\
            "on s.promotion_id=r.promotion_id "+\
            "where s.promotion_id is not null"

        cur.execute(s)
        rs=cur.fetchall()
        #print(rs)
        amt=0
        a=[]
        if rs:
            tb_temp="tmp"
            s="create temp table "+tb_temp+"("+\
                "promotion_id integer,"+\
                "label_code character varying(20),"+\
                "label_pkg smallint,"+\
                "label_id bigint,"+\
                "label_pk_id bigint,"+\
                "amt_terminal numeric(12,2),"+\
                "amt_agent numeric(12,2),"+\
                "product_id integer"+\
            ")"            
            cur.execute(s)
            for r in rs:
                a.append("("+str(r[0])+",'"+r[1]+"',"+str(r[2])+","+str(r[3])+","+str(r[4])+","+str(r[5])+","+str(r[6])+","+str(r[7])+")")
            s="insert into "+tb_temp+"(promotion_id,label_code,label_pkg,label_id,label_pk_id,amt_terminal,amt_agent,product_id) values "+",".join(a)                
            cur.execute(s)    
            #终端返利
            s="select promotion_id,sum(x),sum(p),sum(amt_terminal),sum(amt_agent) from "+\
                "(select promotion_id,case when label_pkg=3 then 1 else 0 end x,case when label_pkg=1 then 1 else 0 end p,"+\
                    "coalesce(amt_terminal,0) amt_terminal,coalesce(amt_agent,0) amt_agent from "+tb_temp+\
                ") d group by promotion_id"                    
            cur.execute(s)
            rr=cur.fetchone()
            #print(rr)
            if rr[3]>0:            
                #终端返利 batch
                s="insert into sales_channelrebatebatch(ancestor_id,company_id,company_src_id,promotion_id,batch_id,val,vtype_id,boxes,bottles,confirmed) values "+\
                    "("+aid+","+cid+","+cid+","+str(rr[0])+","+bid+","+str(rr[3])+","+vid+","+str(rr[1])+","+str(rr[2])+",false) returning id"                
                cur.execute(s)
                rrr=cur.fetchone()
                id=str(rrr[0])
                #print(id)
                s="INSERT INTO sales_channelrebatedetails("+\
                    "label_id,label_pk_id,label_code,label_pkg,val,product_id,rebate_batch_id,stk_batch_id,company_id,vtype_id) select "+\
                    "label_id,label_pk_id,label_code,label_pkg,amt_terminal,product_id,"+id+","+bid+","+cid+","+vid+" from "+tb_temp
                cur.execute(s)            
                data['amount']=rr[3]
                data['promotion_id']=rr[0]
            if rr[4]>0:
                #经销商返利 batch
                s="insert into sales_channelrebatebatch(ancestor_id,company_id,company_src_id,promotion_id,batch_id,val,vtype_id,boxes,bottles,confirmed) values "+\
                    "("+aid+","+str(c.parent_id)+","+str(c.parent_id)+","+str(rr[0])+","+bid+","+str(rr[4])+","+vid+","+str(rr[1])+","+str(rr[2])+",false) returning id"                
                cur.execute(s)
                rrr=cur.fetchone()
                id=str(rrr[0])
                s="INSERT INTO sales_channelrebatedetails("+\
                    "label_id,label_pk_id,label_code,label_pkg,val,product_id,rebate_batch_id,stk_batch_id,company_id,vtype_id) select "+\
                    "label_id,label_pk_id,label_code,label_pkg,amt_agent,product_id,"+id+","+bid+","+str(c.parent_id)+","+vid+" from "+tb_temp
                cur.execute(s)
            return data
    except Exception:
        # 渠道扫码奖池布奖相关计算出错，先不做处理
        pass



    

    # 2021-02-12 # 同一笔BATCH可能有多个PRODUCT_ID,即一个BATCH可能有多个promotion_id
    
    cur.execute("SELECT product_id from "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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"    
    
    # 2022-10-29 stkdetails分表    
    aid=str(batch.company.ancestor_id)
    tb_stk="stkdetails.c"+aid


    #2020-11-19
    sProductdA="ARRAY(SELECT product_id from "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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()  

    # 2022-10-29 stkdetails分表
    tb="stkdetails.c"+str(aid)
    
    #主箱标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)   
    

   


    #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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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]
    #有瓶盖数据的标签，目前只考虑箱瓶二级套标关系

    # 2022-10-29 stkdetails分表
    cur.execute("select ancestor_id from company_company where id="+str(company_id))
    r=cur.fetchone()
    aid=str(r[0])
    tb_stk="stkdetails.c"+aid

    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 "+tb_stk+" 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] 

    # 2022-10-29 stkdetails分表
    cur.execute("select ancestor_id from company_company where id="+str(company_id))
    r=cur.fetchone()
    aid=str(r[0])
    tb_stk="stkdetails.c"+aid

    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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" "+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)
    
    # 2022-10-29 stkdetails分表
    tb_stk="stkdetails.c"+str(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 "+tb_stk+" " + \
                "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 "+tb_stk+" " + \
                "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 "+tb_stk+" "+\
               "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 "+tb_stk+" " + \
            "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)

    # 2022-10-29 stkdetails分表
    tb_stk="stkdetails.c"+str(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 " + \
                tb_stk+" 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 " +\
                tb_stk+" 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 " + \
                tb_stk+" 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 " +\
            tb_stk+" 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)

    # 2022-10-29 stkdetails分表
    tb_stk="stkdetails.c"+str(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 "+ \
                tb_stk+" 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 " +\
                tb_stk+" 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 " + \
                tb_stk+" 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 " +  \
            tb_stk+" 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,"+\
       "coalesce(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

    # 2022-10-29 stkdetails分表
    aid=str(c.ancestor_id)
    tb_stk="stkdetails.c"+aid

    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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+"(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-08-25 含跨段在线绑定（再绑定）标签查询
class LabelQuery():
    def __init__(self,company_id,code,conn=None,agent_id=None):
        if not conn:
            conn=connection
        self.code=code    
        self.tb_cross=''    #卷标跨段表名
        self.company_id=int(company_id)
        self.connection=conn 
        self.package={}
        if agent_id:
            self.agent_id = int(agent_id)        
        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':{'details':[]},

            # 2023-03-22 carton schema 新增字段，用以保存同一箱的跨段箱标
            'carton_codes':[]
        } 
        #取主箱标ID，包装，是否已激活          
        self.infor['label_pk_id']=self.get_label_pk()
    
    # 2023 07-14 经销商查询标签信息
    #判断是否是该经销商标签
    def get_agent_label(self):
        flag = False
        agent_id = self.agent_id
        label_pk_id = self.infor['label_pk_id']
        tb = "stkdetails.c"+str(self.company_id)
        cur = self.connection.cursor()
        s = "SELECT * from " +tb+ " WHERE company_to_id = "+str(agent_id)+" and vtype_id = 2 and label_pk_id = "+str(label_pk_id)+" ;"
        cur.execute(s)
        r = cur.fetchone()
        if r:
            flag = True
        return flag

            
    def get_batch_number(self):
        batch_number = '未知'
        label_pk_id = self.infor['label_pk_id']
        cur = self.connection.cursor()
        if  label_pk_id != 0:
            s="select batch_no,label_code,label_pk_id,remark,tm,vtype_id,label_pkg from batchlot.batchlot where label_pk_id = "+ str(label_pk_id) +" limit 1"
            cur.execute(s)
            r = cur.fetchone()
            if r :
                batch_number = r[0]
        return batch_number
        
        
    def get_parent_id(self):
        parent_id = 0
        code = self.code
        cur = self.connection.cursor()
        s = "select parent_id from label.t"+ code[0:4] + " where code = '"+ code +"' union  all ( select parent_id from label.lbl_binding_jg where code ='"+ code +"' ORDER BY id  desc limit 1)"        
        cur.execute(s)
        r = cur.fetchone()
        if r:
            parent_id = r[0]
        return parent_id
        
    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()

        # 2022-10-29 stkdetails分表
        tb_stk='stkdetails.c'+str(aid)

        sPkg='package_id'   #一般情况下，标签类别取标签基础表的 package_id 字段
        #2021-05-06 瓶盖码
        #if not code.isdigit():  
        # 2022-12-14
        if code[0] 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 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,label_pk_id,box_code from label.bottlecap where  label='"+code+"' "+\
                #    " union all "+\
                #    "select bottle,label_pk_id,box_code from z_bottlecap_binding where  label='"+code+"' "
                #)

                # 2022-12-16
                # 酒鬼今后会有直接扫临时标代替瓶盖码 (盖内码解密=瓶盖上贴的44开头临时标) 
                # 目前瓶盖码加密方式只能从加密码得到明码,不能从明码得到加密码(盖内码)  
                baid=aid
                if int(company_id)==1644:
                    baid=1
                s="select a.bottle,a.id from "+\
                    "(select   bottle,label_pk_id,box_code,id from label.bottlecap       where company_id="+str(baid)+" and label='"+code+"'"+\
                        " union all "+\
                        "select bottle,label_pk_id,box_code,id from z_bottlecap_binding  where company_id="+str(baid)+" and label='"+code+"'"+\
                        " union all "+\
                        "select  bottle,label_pk_id,box_code,id from label.bottlecap     where company_id="+str(baid)+" and code='"+d_code+"'"+\
                        " union all "+\
                        "select bottle,label_pk_id,box_code,id from z_bottlecap_binding  where company_id="+str(baid)+" and code='"+d_code+"'"+\
                    ") a order by id desc"
                cur.execute(s)
                
                r=cur.fetchone()
                #if r:
                #    code=r[0]     
                if r:
                    # 2022-11-18  
                    if r[0]:
                        code=r[0]
                    else:
                        # 2019年酒鬼酒第一批瓶盖，只绑定到箱标，没有具体到瓶
                        if r[1]:               
                            self.infor['label_company_id']=1
                            self.infor['label_pk_code']=r[2]
                            self.package={'id':100,'name':'活动码'}
                            return r[1]
                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


        # 2023-04-17 早期要求独立箱标要先导入基础表，酒鬼车间绑定写入酒鬼跨段表;导致一枚箱标可能会有2个ID
        # 优先查询酒鬼跨段表 fg_update 也优先查询 label.lbl_binding_jg
        if company.ancestor_id in (1,1644):
            s="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),"+\
                "id from label.lbl_binding_jg j where code='"+code+"'"    
            cur.execute(s)
            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]}
                # 2023-07-13
                self.infor['label_id']=rrr[4]
                return rrr[0]


        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]                            
                    # 主箱标
                    else:                        
                        self.infor['label_pk_id']=rrr[0]
                        self.infor['label_pk_code']=rrr[5]   
                    # 套标是否为标准跨段模式
                    cur.execute("select count(*) from information_schema.tables where table_schema = 'carton' "+
                        "and table_type='BASE TABLE' and table_name = 't"+self.infor['label_pk_code'][:4]+"'")
                    r0=cur.fetchone()                    
                    if r0[0]:
                        #s="select id from carton.t"+self.infor['label_pk_code'][:4]+" where code='"+self.infor['label_pk_code']+"'"
                        # 2023-03-22
                        s="select id,codes::json from carton.t"+self.infor['label_pk_code'][:4]+" where code='"+self.infor['label_pk_code']+"'"
                        cur.execute(s)
                        r4=cur.fetchone()
                        if r4:
                            self.infor['carton']=self.infor['label_pk_code'][:4]  
                            # 2023-03-22
                            if r4[1]:                               
                                self.infor['carton_codes']=r4[1]
                    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]
                            elif r4[2]:
                                # 箱盒瓶三级绑定
                                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']

        
        """
        # 以下代码以移到10316行，优先判断标签是否在酒鬼跨段表label.lbl_binding_jg
        #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]
            cur.execute( "select code,code_is_permanent from inventory_stack where id=" + str(label_pk_id) + " or parent_id = " + str(label_pk_id))
            rs = cur.fetchall()
            for i in rs:
                self.infor['stack']['details'].append(i[0])

            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()
                    # 2022-11-12 r10可能为空
                    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 "+tb_stk+" 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 
        company_id = self.company_id
        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=[]
            if  company_id == 16687:
                for r1 in cur.fetchall():
                    cartons.append({'label': r1[6], '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]})
            else:
                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]})
            #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}) 
            
            
            # 2023-03-22 如果两枚箱标跨段 先只添加箱号，目前跨段箱标没有                      
            for c in self.infor['carton_codes']:                
                #print('compare:',c, self.infor['label_pk_code'])
                if c!=self.infor['label_pk_code']:
                    ctb="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 "+ctb+" a where code='"+c+"') l "+\
                        "left outer join "+\
                        "(SELECT id,code0,code,dt FROM label.lbl_replace_details) r "+\
                        "on l.rid=r.id" 
                    cur.execute(s)
                    for r1 in cur.fetchall():
                        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[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="+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-10-29 stkdetails分表
        tb_stk='stkdetails.c'+aid

        
        # 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,components 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,components 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,components from "+\
                "(select coalesce("+\
                        "(select product_id from "+tb_stk+" 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 "+tb_stk+" 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,components 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-12-14
                pid=str(r[0])                  
                
                # 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]
                # 2022-12-14 组合包装产品，且查询的是瓶标，要显示实际单品名称
                cmpnts=r[8]
                if isinstance(r[8],str):  
                    cmpnts=json.loads(cmpnts)
                if cmpnts and self.package['id']==1:
                    # 查询mes在线绑定 ph绑定表，取瓶标产品信息
                    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,components "+\
                        "from "+\
                        "(select product_id from mes_labelbindph where company_id="+aid+" "+\
                            "and is_delete=false and bottle_code='"+self.code+"' order by id desc limit 1"+\
                        ") s "+\
                        "left outer join "+\
                        "(select id,name,price,coalesce(contents,'') contents,external_code,photo,shelf_life,barcode,components from product_product where company_id="+aid+") p "+\
                        "on s.product_id=p.id  where s.product_id>0"  
                    cur.execute(s)
                    rr=cur.fetchone()
                    if rr:
                        if rr[0]:                            
                            data['name']=rr[1]
                            data['price']=rr[2].strip()
                            data['id']=rr[0]
                            data['external_code']=rr[4]   
                            if rr[5]:
                                data['photo']='/media/'+rr[5]
                            if rr[6]:
                                data['shelf_life']=rr[6]
                            if rr[7]:
                                data['barcode']=rr[7]
                            pid=str(rr[0])

                s="select coalesce(c.value,'') val,g.name,g.desc_cn,coalesce(g.unit,'') from "+\
                    "(SELECT * FROM product_prdprops where product_id="+pid+") 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 "+tb_stk+" 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 "+tb_stk+" 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]  
        # 2022-09-27 没有物流信息
        else:
            if aid=="1":
                s="select coalesce((select name from jiugui_local.product where id=product_id),'') "+\
                    "from jiugui_local.stk_details s where label_pk_id="+str(pk)+" order by id desc limit 1"
                cur.execute(s)
                r=cur.fetchone()
                if r:
                    data['name']=r[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':          #包装
            }

            try:
                # 设置2秒钟连接超时
                r=requests.get(url,param,timeout=2) 
                
                #{
                # "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}
            except Exception:
                pass
            
        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,show_related=True):
        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-10-29 stkdetails分表
        tb_stk='stkdetails.c'+aid
        
        # 2022-07-19 同一族系，母公司可以查子公司物流 hierarchy_id
        #100424;"成义烧坊酒业股份有限公司" 111006;"成都成义烧坊电子有限公司"
        #1;"酒鬼酒股份有限公司" 1644;"湖南内参酒销售有限责任公司"        
        hierarchies={
            '1':['1','1644'],                   #酒鬼可查内参
            '100424':['100424','111006'],       #烧坊可查电子
        }

        replaced_labels=self.get_replaced_labels()
        sRep=''
        if replaced_labels:
            sRep=" or label_code in ('"+"','".join(replaced_labels)+"')"
        
        # 2022-11-24 易臻（特别是 灸贴、眼贴、艾饼）是否显示关联标物流信息
        if show_related:
            sWlbl="label_pk_id="+pk+sRep+" or label_code='"+code+"'"
        else:
            sWlbl="label_code='"+code+"'"


        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)])+")"

            # 2022-12-08 stkdetails分表后，查询修改
            sDtls="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 "+tb_stk+" "+\
                "where ("+sWlbl+")"+sAid            
            if str(self.company_id) in hierarchies:
                aDtls=[]
                for cc in hierarchies[str(self.company_id)]:
                    aDtls.append("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 stkdetails.c"+cc+" "+\
                        "where ("+sWlbl+")"+sAid) 
                sDtls=" union all ".join(aDtls)    

        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)+")" 
            
            # 2022-12-08
            sDtls="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 "+tb_stk+" "+\
                "where ("+sWlbl+")"+sAid
        
        
        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),"+\
            "coalesce(b.dn_number,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,''),"+\
            "coalesce(remark,''),"+\
            "(select json_build_object('x',sum(a.x),'h',sum(a.h),'p',sum(a.p)) from "+\
                "(select 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 stkdetails.c"+aid+" where batch_id=b.id) a) "+\
            "from "+\
            "("+sDtls+") s "+\
            "left outer join "+\
            "(select id,code,dn_number,user_id,rmk_name,remark 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)
        package_units = get_package_name(aid,'标')
        bOut=False #是否需要查询酒鬼酒本地数据库
        for r in cur.fetchall():
            rmk=''
            label_pkg = ''
            qty=''
            if r[10] == '瓶标':
                label_pkg = package_units[0]
            elif r[10] == '盒标':
                label_pkg = package_units[1]
            elif r[10] == '箱标':
                label_pkg = package_units[2]
            else:
                label_pkg = r[10]
            if r[20]:
                rmk=' '+r[20]
            if r[12]==2:
                bOut=True

            # 2023-01-11
            if r[22]['x']:
                qty=str(r[22]['x'])+'箱'
            if r[22]['h']:
                qty=qty+str(r[22]['h'])+"盒"
            if r[22]['p']:
                qty=qty+str(r[22]['p'])+"瓶"  

            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':label_pkg,"code_b":r[11],'is_delete':r[13],
                'customer_external_code':r[14],'batch_id':r[15],'label_pkg_id':r[19],'remark':r[21],'qty':qty,
                '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)
    package_units = get_package_name(u.ancestor_id,"码")
    data['infor']=q.infor
    if cid == 19267 or cid =='19267':
        data['batch_no'] = q.get_batch_number()
    if q.package['id'] == 1:
        q.package['name'] = package_units[0]
    elif q.package['id'] == 2:
        q.package['name'] = package_units[1]
    elif q.package['id'] == 3:
        q.package['name'] = package_units[2]
    data['package']=q.package    
    what=request.GET.get('content','all') 

    # 2022-11-24 是否显示关联标物流信息
    if request.GET.get('show_related','1')=='1':
        show_related=True
    else:
        show_related=False

    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(show_related)
    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(show_related)   
        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']+'与盖码绑定过,现绑定为新盖码'       
            # 2022-12-16 酒鬼今后会有直接扫临时标代替瓶盖码 (盖内码解密=瓶盖上贴的444开头临时标)
            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},
                # 2022-12-16 
                # 酒鬼今后会有直接扫临时标代替瓶盖码 (盖内码解密=瓶盖上贴的44开头临时标) 
                # 目前瓶盖码加密方式只能从加密码得到明码,不能从明码得到加密码(盖内码)

                b_label=b['bottlecap']

                # 瓶盖加密码 2022-12-16                 
                if b_label.isdigit():   # '44'<=b_label[:2] and b_label[:2]<='49'
                    
                    # 传过来瓶盖码是明码，拿不到加密码，只能保存明码，加密码置空
                    b_code="'"+b_label+"'"
                    # b_label='null'       

                    # 2023-01-07 酒鬼酒除第一批中试产品外，瓶盖开始使用V2版加密
                    b_label="'" + CodeEncryptV2(b_label,header='h') + "'"


                else:       
                    b_code="'"+decrypt_11h(b_label)+"'"     # 瓶盖解密码  
                    b_label="'"+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)")  
                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=[]
        
        # 2023-01-13
        nfc_ids=[]
        
        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+"')")
            
            # 2023-01-13
            nfc_ids.append(nfc)

        #防止传数据量过大，每次插入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}    

        # 2023-01-13 nfc标签激活
        if company_id=='16716':     # 湖北裕贡酒业销售有限公司 16716  
            #裕贡，异步任务服务器发送 东海平台 激活nfc标签   
            result=tasks.nfc_activate.delay({ "uidList":nfc_ids })    

    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])

    # 2022-10-29 stkdetails分表
    tb_stk="stkdetails.c"+aid


    #当前会计期是否已做期结
    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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" "+\
            "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'  
    # 2022-10-29 stkdetails分表
    sTbStk='stkdetails.c'+cid
    
    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()   

    # 2022-10-29 stkdetails分表
    aid=str(c.ancestor_id)
    tb_stk="stkdetails.c"+aid
    
    #本期及上期期结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=tb_stk
                # 2022-10-29 stkdetails分表
                tb='stkdetails.c'+cid

                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()   

    # 2022-10-29 stkdetial分表
    cur.execute("select ancestor_id from company_company where id="+str(company_id))
    r=cur.fetchone()
    aid=str(r[0])
    tb_stk="stkdetails.c"+aid

    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), "+\
            "label_pkg from "+t+sW+" order by label_pkg desc"

        
        

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

        # 是否已出库
        s="select to_char(tm,'yyyy-mm-dd hh24:mi:ss'),(select name from company_company where id=company_to_id) "+\
            "from "+tb_stk+" "+sW+" and vtype_id=2  "+\
            "and (select vtype_id from "+tb_stk+" "+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-09-14
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)  

    # 2022-11-24
    # 易臻，灸贴、眼贴、艾饼，2022年9月27号前，套标工厂在随意贴标不，套标关系混乱，先设置force=True，否则仓库发不了货
    force=False
    if int(company_id) in [19267]:
        force=True
    
    q=LabelQuery(company_id,label)         
    pk_id=0
    pkg_id=0
    lb_id=0
    if q.infor['label_pk_id']:   
        pk_id=q.infor['label_pk_id'] 
    if  q.infor['label_id']:     
        lb_id=q.infor['label_id']
    if q.package:
        pkg_id=q.package['id']   
        
    d=custom_label_infor(company_id,lb_id,pk_id,pkg_id,label,vtype_id=2)   
   
    if d['product']:
        #data['product_id']
        cid=str(company_id)
        if pkg_id:
            data['package_id']=pkg_id
        else:
            data['package_id']=d['package_id']        
        # 2022-09-19 如易臻转念 艾艾饼，1*24 二级包装，如果标签是瓶标，需要返给扫码枪盒标       
        if d['product'] and cid=='19267' and data['package_id']==1:
            cur=connection.cursor()
            s="SELECT value FROM product_productprop p	where company_id="+cid+" and categoryprop_id=(SELECT id FROM company_categoryprop where name='package' "+\
                "and  category_id=(select category_id from logistics.company_company where id="+cid+")) "+\
	        "and id in (select prd_property_id from product_prdprops where product_id="+str(d['product']['id'])+")"   
            cur.execute(s)
            r=cur.fetchone()
            a=r[0].split('*')
            if len(a)==2:
                data['package_id']=2  
            cur.close()

        if d['product']['id']!=int(product_id):
            data['suggestion']=d['product']

        if d['outbound'] and force==False :
            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() 

    # 2022-10-29
    tb_stk='stkdetails.c'+company_id

    #先只查询箱标记录 有些公司用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 "+tb_stk+" 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 "+tb_stk+" "+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 "+tb_stk+" "+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 "+tb_stk+" 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 "+tb_stk+" 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])

    # 2022-10-29 stkdetails分表
    tb_stk='stkdetails.c'+aid

    #当前会计期是否已做期结
    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 "+tb_stk+" "+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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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)
        
    #2023 03-07 诗仙太白要求自己公司能够重复出库，不做标签出库检查
    #if company_id ==19318 or company_id =='19318':
    #    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']


        # 2022-10-29 stkdetails分表
        cur.execute("select ancestor_id from company_company where id="+str(company_id))
        r=cur.fetchone()
        aid=str(r[0])
        tb_stk="stkdetails.c"+aid

        # 若为箱标，则以主箱标为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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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()

        # 2022-10-29 stkdetails分表
        cur.execute("select ancestor_id from company_company where id="+str(company_id))
        rr=cur.fetchone()
        aid=str(rr[0])
        tb_stk='stkdetails.c'+aid

        
        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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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 "+tb_stk+" 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)








# 库存保质期
@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]

    aid='stkdetails.c'+str(c.ancestor_id)

    package_units = get_package_name(c.ancestor_id)
    # 找到最近一次盘库记录的时间，小于该时间的出入库记录不在此展示，于期结中单独展示
    tmc = query_json(
        f"SELECT tm FROM logistics.inventory_stkclosingbatch WHERE company_id = '{company_id}' ORDER BY tm DESC LIMIT 1")
    tm = tmc[0]["tm"] if len(tmc) > 0 else "2018-02-01 13:15:00+08"  # stkdetails中最早数据时间
    # 进销商层级，工厂
    if c.level.sn == 0:
        sWhere = "WHERE d.ancestor_id=" + str(
            c.ancestor_id) + " AND d.company_id<>" + str(c.id) + f" AND d.tm > COALESCE((SELECT tm FROM logistics.inventory_stkclosingbatch WHERE company_id = d.company_id ORDER BY tm DESC LIMIT 1),'2022-01-01')"
    else:
        sWhere = "WHERE d.ancestor_id=" + str(
            c.ancestor_id) + " AND d.tm > COALESCE((SELECT tm FROM logistics.inventory_stkclosingbatch WHERE company_id = d.company_id ORDER BY tm DESC LIMIT 1),'2022-01-01')" +\
                 " AND d.company_id IN (SELECT id FROM company_company WHERE id=" + str(
            c.id) + " OR parent_id=" + str(c.id) + ")"
    s = f"""
        SELECT
            tbt.company, tbt.product, SUM(tbt.p)::text||'{package_units[0]}' p, tbt.company_id, tbt.product_id, tbt.name, days_to_expire, tbt."type", tbt.color
        FROM
        (
        SELECT
            tbl.company, tbl.product, tbl.P "p", tbl.company_id, tbl.product_id, tbl.NAME,
            COALESCE(tbl.days::TEXT,'') days_to_expire,
            COALESCE(tbl.warn_type, '') "type",
            COALESCE(tbl.warn_color, '') 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.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 * qty_h * qty_p + A.h * qty_p + A.p) P, A.days,A.dt
                    FROM
                        (SELECT d.ID, d.dt, d.product_id, d.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,
                        tbp.qty_x, tbp.qty_h, tbp.qty_p
                FROM
                {aid} d
                LEFT JOIN product_product tbp ON d.product_id = tbp.ID 
                {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
        UNION
        SELECT tbb.company, tbb.product, tbb.p "p", tbb.company_id, tbb.product_id, tbb.NAME,
            COALESCE(tbb.days::TEXT,'') days_to_expire,
            COALESCE(texp.warn_type, '') "type",
            COALESCE(texp.warn_color, '') color
        FROM
        (
        SELECT
            tba.company, tba.product,
            SUM(tba.x * qty_h * qty_p + tba.h * qty_p + tba.p) p,
            tba.company_id, tba.product_id, tba.name,
            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
        (SELECT
            company_id,
            (SELECT name FROM company_company WHERE id = company_id) company,
            (SELECT NAME FROM company_level WHERE ID = (SELECT level_id FROM company_company WHERE ID = company_id)),
            product_id,
            (SELECT name FROM product_product WHERE id = product_id) product,
            sum(CASE WHEN label_pkg IN (3, 4) THEN 1 ELSE 0 END) x,
            sum(CASE WHEN label_pkg = 2 THEN 1 ELSE 0 END) h,
            sum(CASE WHEN label_pkg = 1 THEN 1 ELSE 0 END) p,
            (SELECT dt FROM {aid} WHERE label_code = label_code AND vtype_id = 1 AND is_delete = false ORDER BY dt DESC LIMIT 1) dt
        FROM
            inventory_stkclosingbatchdetails
        WHERE
            company_id IN (SELECT id FROM company_company WHERE id={company_id} OR parent_id={company_id}) 
            AND tm >= COALESCE((SELECT tm FROM logistics.inventory_stkclosingbatch WHERE company_id = inventory_stkclosingbatchdetails.company_id ORDER BY tm DESC LIMIT 1),'2022-01-01')
        GROUP BY
            company_id, company, product_id, dt
        ) tba
        LEFT JOIN
        product_product tbp
        ON tbp.id = tba.product_id
        GROUP BY tba.company_id, tba.company, tba.name, tba.product_id, tba.product, tba.x, tba.h, tba.p, tba.dt, tbp.qty_x, tbp.qty_h, tbp.qty_p
        ) tbb
        LEFT JOIN inventory_stkexp texp
        ON tbb.days > texp.warn_min_day AND tbb.days <= texp.warn_max_day
        ) tbt
        GROUP BY
            tbt.company, tbt.product, tbt.company_id, tbt.product_id, tbt.name, days_to_expire, tbt."type", tbt.color
        """
    

    if c.level.sn == 0:
        data = {'data': [], 'clmns': [], 'e': [], 'subtt': ['', ''], 'murl': '', 'dt': False, 'add': True}
        data['subtt'] = ['进销存报表', '过期预警']
        data['clmns'] = ['经销商', '层级', '产品', '数量', '剩余保质期天数']
        cur = connection.cursor()
        cur.execute(s)
        for r in cur.fetchall():
            a = []
            warn = r[7]
            days = f'<span class=" ant-tag ant-tag-{warn}">{r[6]}</span>'

            data['data'].append([
                r[0],  # agent
                r[5],  # level
                r[1],  # product
                r[2],  # qty
                days  # 剩余保质期天数
            ])
        return render(request, 'obj/list_obj.html', data)
    else:
        jsonData = query_json(s)
        return JsonResponse({'data': jsonData})


# 订单(发货单)发货状态查询
def delivery_status(request):
    data={'data':[],'clmns':["发货单号","创建时间","发货单状态","出库单号","出库单状态","产品编码","产品名称", "应发数量", "单位",
                     "实发数量"]}
    company_id = request.user.company.id

    # 2022-10-29 stkdetails分表
    aid=str(request.user.company.ancestor_id)
    tb_stk='stkdetails.c'+aid

    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
                {tb_stk}
            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]

    # 2022-10-29 stkdetails分表
    aid=str(c.ancestor_id)
    tb_stk="stkdetails.c"+aid

    package_units = get_package_name(c.ancestor_id)
    # 找到最近一次盘库记录的时间，小于该时间的出入库记录不在此展示，于期结中单独展示
    tmc = query_json(f"SELECT tm FROM logistics.inventory_stkclosingdetails WHERE company_id = '{company_id}' ORDER BY tm DESC LIMIT 1")
    tm = tmc[0]["tm"] if len(tmc) > 0 else "2018-02-01 13:15:00+08" # stkdetails中最早数据时间
    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,
        (select remark from inventory_voucher where id = vtype_id) vtype,
        (select direction from inventory_voucher where id = vtype_id) direction,
        (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
        {tb_stk}
    WHERE
        product_id = '{str(product_id)}'
        AND company_id = '{str(company_id)}'
        AND dt > ( now() - '""" + period + f"""' :: INTERVAL )
        AND tm > '{tm}'
    GROUP BY product_id, batch_number, product_name, unit, vtype, direction, dt
    LIMIT """ + str(limit) + """
    OFFSET """ + str(int(limit) * int(offset))
    data = query_json(sql)
    return JsonResponse(
        {
            "code": 200,
            "info": "success",
            "data": data
        }
    )


def stack_log(batch_id,company_id):
    data= {'e':''}
    cur = connection.cursor()
    
    # 2022-10-29 stkdetails分表
    cur.execute("select ancestor_id from company_company where id="+str(company_id))
    rr=cur.fetchone()
    aid=str(rr[0])
    tb_stk='stkdetails.c'+aid

    s = "select b.batch_id,a.stack_id,a.label_code,a.label_pk_id,a.label_id,a.label_pkg from "+\
        " (SELECT stack_id,label_code,label_id,label_pk_id,label_pkg from logistics.inventory_stackdetails where company_id = "+str(company_id)+")a "+\
        " left outer join "+\
        " (SELECT label_pk_id,label_code,batch_id FROM "+tb_stk+"  where batch_id = "+ str(batch_id)+")b "+\
        " on a.label_code =b.label_code "+\
        " WHERE b.label_pk_id is not  NULL  "
    cur.execute(s)
    res = cur.fetchall()
    values = []
    label_pk_id = []
    in_sert  = "insert into inventory_stacklog (batch_id,stack_id,label_code,label_pk_id,label_id,package_id,company_id,dt,tm) values "
    if res:
        for r in res :
            label_pk_id.append(str(r[3]))
            values.append("("+str(r[0])+","+str(r[1])+",'"+r[2]+"',"+str(r[3])+","+str(r[4])+","+str(r[5])+","+str(company_id)+",now(),now())")
        try :
            del_s = "delete from logistics.inventory_stackdetails where label_pk_id in ("+(",").join(label_pk_id)+")"
            cur.execute(del_s)
            in_s = in_sert + (",").join(values)
            cur.execute(in_s)
        except :
            data['e'] = '处理错误'
        if cur.rowcount > 0:
            data['e'] = '部分产品移除垛盘'

    return data

# 业务员到店库存盘点
@csrf_exempt
def to_store_inventory(request):
    data = {
        'e': '',
        'data': ''
    }
    try:
        body = json.loads(request.body)
        '''
        body = {
            "batch_id": "",
            "ancestor_id": 1,
            "company_id": 1,
            "store_id": 1,
            "user_id": 1,
            "remark": 1,
            "labels": [
                {
                    "product_id": "",
                    "code": "",
                    "label_id": "",
                    "label_pk_id": "",
                    "package_id": ""
                }
            ]
        }
        '''
    except json.decoder.JSONDecodeError as e:
        data['e'] = e.msg
        return JsonResponse(data)
    if 'user_id' not in body:
        data['e'] = 'user_id is required!'
        return JsonResponse(data)
    if 'company_id' not in body and ('user_id' not in body or 'label' not in body):
        data['e'] = 'Body should contain company_id and either user_id or label!'
        return JsonResponse(data)
    if not body['batch_id']:
        batch = StkClosingBatch(
            ancestor_id=body['ancestor_id'] if body['ancestor_id'] is not None else 0,
            company_id=body['company_id'],
            store_id=body['store_id'] if body['store_id'] is not None else 0,
            user_id=body['user_id'],
            remark=body['remark'] if body['remark'] is not None else None,
            stkclosing_id=0
        )
        batch.save()
    else:
        batch = StkClosingBatch.objects.get(id=body['batch_id'])

    for label in body['labels']:
        detail = StkClosingBatchDetails(
            closingbatch_id=batch.id,
            ancestor_id=batch.ancestor_id,
            company_id=batch.company_id,
            stkclosing_id=0,
            product_id=label['product_id'],
            label_code=label['code'],
            label_id=label['label_id'],
            label_pk_id=label['label_pk_id'],
            label_pkg=label['package_id'],
            store_id=batch.store_id
        )
        detail.save()
    data['data'] = 'Success!'
    return JsonResponse(data)


# 获取上次到店盘点
@csrf_exempt
def last_to_store(request):
    data = {
        'e': '',
        'msg': '',
        'data': ''
    }
    try:
        r = json.loads(request.body)
    except json.decoder.JSONDecodeError as e:
        data['e'] = 'JSONDecodeError: ' + e.msg
        return JsonResponse(data)
    if 'company_id' not in r:
        data['e'] = 'missing data'
        return JsonResponse(data)
    else:
        sql = f"SELECT * FROM inventory_stkclosingbatch WHERE company_id = {r['company_id']} ORDER BY id DESC LIMIT 1"
    data['data'] = query_json(sql)
    return JsonResponse(data)


@csrf_exempt
def check_to_store_existence(request):
    if request.method != 'POST':
        return HttpResponse("Only POST request is supported.")
    try:
        body = json.loads(request.body)
    except json.JSONDecodeError as e:
        return JsonResponse({"error": e})
    if 'labelCode' not in body:
        return JsonResponse({"error": "labelCode is required!"})
    # 在则不入，子在父不入，父在子不入
    ext = StkClosingBatchDetails.objects.filter(label_code=body['labelCode']).count()
    if get_label_pk_id(body['labelCode']):
        par = StkClosingBatchDetails.objects.filter(label_id=get_label_pk_id(body['labelCode'])).count()
    else: par = 0
    sub = StkClosingBatchDetails.objects.filter(label_pk_id=int(body['labelCode'])).count()
    data = {"capable": "False"}
    if ext > 0:
        data['msg'] = "该标签已存在"
        return JsonResponse(data)
    elif par > 0:
        data['msg'] = "该标签绑定的父标签已存在"
        return JsonResponse(data)
    elif sub > 0:
        data['msg'] = "该标签绑定的子标签已存在"
        return JsonResponse(data)
    data['capable'] = "True"
    stkdetails = StkDetails.objects.filter(label_code=body['labelCode']).order_by('-dt').last()
    data['msg'] = {"productId": stkdetails.product.id, "productName": stkdetails.product.name} if stkdetails is not None else None
    return JsonResponse(data)


@login_required
def stack_list(request):
    u = request.user
    cid = str(u.company.id)
    
    aid=str(u.company.ancestor_id)
    # 2022-10-29 stkdetails分表
    tb_stk='stkdetails.c'+aid

    dt = datetime.datetime.now()
    dt_fr = request.GET.get('date_from',(dt-datetime.timedelta(days=7)).strftime("%Y-%m-%d"))
    dt_to = request.GET.get('date_to',dt.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
    cur = connection.cursor()
    package_units = get_package_name(u.ancestor_id)
    data = {'clmns':["垛标号码","操作时间","单据编号","单据类型","客户名称","产品名称","仓库名称","操作人",package_units[2],package_units[1],package_units[0]],
            'data':[],'date_from':dt_fr,'date_to':dt_to}

    s = " select a.id,a.tm,a.batch_no,coalesce(d.name,''),coalesce(b.name,''),c.name," +\
        "COALESCE ( e.s,(SELECT COUNT(*) from inventory_stacklog where batch_id = z.batch_id and  stack_id = z.stack_id), 0 )," +\
        " coalesce(f.s,0),coalesce(g.s,0),n.name,m.last_name, y.code,z.stack_id  from  "+\
        "(SELECT batch_id,stack_id from "+tb_stk+" WHERE stack_id IS NOT NULL AND "+\
        " company_id = "+cid+" AND ( dt BETWEEN '"+dt_fr+"' AND '"+dt_to+"' ) GROUP BY batch_id,stack_id "+\
        " union SELECT batch_id,stack_id from inventory_stacklog WHERE   company_id = "+cid+" AND "+\
        "( dt BETWEEN '"+dt_fr+"' AND '"+dt_to+"' ) GROUP BY batch_id,stack_id )z "+\
        " left outer join  (SELECT id,batch_no,TO_CHAR(tm, 'yyyy-mm-dd HH24:MI:SS')tm,vtype_id ," +\
        "company_to_id,product_id,stacks,user_id,store_fr_id from inventory_batch where id in " +\
        "( SELECT batch_id FROM "+tb_stk+" WHERE stack_id IS NOT NULL AND company_id = "+cid+" and " +\
        "( dt BETWEEN '"+dt_fr+"' AND '"+dt_to+"' ) GROUP BY batch_id ) " +\
        "or id in (select batch_id from inventory_stacklog where company_id = "+cid+" and " +\
        "( dt BETWEEN '"+dt_fr+"' AND '"+dt_to+"' ) GROUP BY batch_id ) ) A on a.id = z.batch_id "+\
        " left outer join  (select id ,name  from logistics.product_product)B on a.product_id = b.id  "+\
        " left outer join (select id ,name from logistics.inventory_voucher)c on c.id = a.vtype_id " +\
        " left outer join (select id,name from logistics.company_company)d on d.id =a.company_to_id " +\
        " left outer join (select id,last_name from logistics.company_user)m on m.id = a.user_id " +\
        " left outer join (select id,name from logistics.inventory_storehouse)n on a.store_fr_id = n.id " +\
        " left outer join (select id,code from inventory_stack )y on z.stack_id = y.id"+\
        " left outer join (SELECT count(*)s,batch_id,stack_id from "+tb_stk+" " +\
        "where company_id = "+cid+" and label_pkg = 3 GROUP BY batch_id,stack_id ) e " +\
        "on e.stack_id = z.stack_id and  e.batch_id = a.id " +\
        " left outer join (SELECT count(*)s,batch_id,stack_id from "+tb_stk+" " +\
        "where company_id = "+cid+"  and label_pkg = 2 GROUP BY batch_id,stack_id ) f " +\
        "on f.stack_id = z.stack_id and f.batch_id = a.id "+\
        " left outer join (SELECT count(*)s,batch_id,stack_id from "+tb_stk+" " +\
        "where  company_id = "+cid+"  and label_pkg = 1 GROUP BY batch_id,stack_id ) g " +\
        "on g.stack_id = z.stack_id and g.batch_id = a.id "
    #print(s)
    cur.execute(s)
    r = cur.fetchall()
    for i in r :
        tm = "<a href='/inventory/stack/details/" + str(i[0]) + "/"+str(i[12])+"/' target='_blank'>" + \
             i[11] + "</a>"
        data['data'].append([tm,i[1],i[2],i[5],i[3],i[4],i[9],i[10],i[6],i[7],i[8]])
    return render(request, 'inventory/stack/stack_list.html', data)

@login_required
def stack_details(request,batch_id,stack_id):
    data={'e':'','batch':{},'dataset':[],'del_perm':False}
    u=request.user

    cur=connection.cursor()
    qty='0'
    # 2022-10-29 stkdetails分表
    aid=str(u.company.ancestor_id)
    tb_stk='stkdetails.c'+aid

    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 "+tb_stk+" where batch_id=b.id and stack_id = "+str(stack_id)+")," + \
        "(select count(*) from inventory_batchdetails where batch_id=b.id and stack_id = "+str(stack_id)+") " + \
        "from inventory_batch b where id=" + batch_id
    cur.execute(s)
    r = cur.fetchone()
    if r:
        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
                         }
        clmns = ['扫码标签', '写入标签', '标签类型', '产品名称']
        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 stack_id = "+str(stack_id)+" and batch_id=" + batch_id + ") a " + \
            "left outer join " + \
            "(select label_code,label_pkg,product_id from "+tb_stk+" where stack_id = "+str(stack_id)+" and batch_id=" + batch_id + ") b " + \
            "on a.label_code=b.label_code"

        cur.execute(s)
        rs = cur.fetchall()
        if rs:
            for r in rs:
                data['dataset'].append([r[0], r[1], r[2], r[3]])
        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=" + batch_id + ") a " + \
                "left outer join " + \
                "(select label_code,label_pkg,product_id,label_pk_id from "+tb_stk+" where batch_id=" + batch_id + ") b  on a.label_code=b.label_code "+\
                " left outer join (select batch_id,stack_id ,label_code ,label_pk_id from inventory_stacklog " +\
                "where stack_id = "+str(stack_id)+" and batch_id="+str(batch_id)+")c on c.label_pk_id = b.label_pk_id where c.label_code is not null "
            cur.execute(s)
            rs = cur.fetchall()
            for r in rs:
                data['dataset'].append([r[0], r[1], r[2], r[3]]) 
            data['batch']['qty'] = len(rs)
        cur.close()
    data['dataset'] = SafeString(data['dataset'])
    data['clmns'] = clmns

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

@csrf_exempt
def binding_of_stacks(request):
    data={'e':'','message':''}
    r = json.loads(request.body)
    e = time_key_check(request, sK)
    if e:
        data['e'] = e
        return JsonResponse(data)
    if 'stack' not in r or 'product_id' not in r or 'company_id' not in r or 'is_physical' not in r :
        data['e'] = 'missing data'
        return JsonResponse(data)
    stack = r['stack']
    pid = str(r['product_id'])
    cid = str(r['company_id'])
    physical = 'true'
    if  not r['is_physical']:
        physical = 'false'
    details = r['details']
    cur = connection.cursor()
    company = Company.objects.get(id=cid)
    a=[]
    labels = []
    message = []
    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,"+\
        "company_id integer,binded bool default false ,binded_tm timestamptz(6),stack character varying(30),err character varying(100))")
    for i in details:
        labels.append("("+i+",'t"+i[:4]+"',"+pid+","+cid+")")
    cur.execute("insert into codes (label_code,tb,product_id,company_id) values"+",".join(labels))

    #处理标签替换
    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)


    # 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(company.ancestor_id) + ") b " + \
        "on a.code=b.code " + \
        "where codes.code=a.code and label_id is null"
    cur.execute(s)
    cur.execute("update codes set tb='t'||left(code,4) where length(tb)=4")



    # 标记重复入库
    # cur.execute("update codes a  set binded = 'true' where  exists ( select label_pk_id from inventory_stackdetails  where company_id = a.company_id and label_pk_id =  a.label_pk_id )  ")
    cur.execute("update codes a set binded = 'true', binded_tm = b.tm, stack = (select code from inventory_stack where id = b.stack_id)  from inventory_stackdetails b  where a.company_id = b.company_id and a.label_pk_id =  b.label_pk_id ")


    cur.execute("select label_code,binded_tm,stack from codes where binded = true")
    binded = cur.fetchall()
    if binded:
        for i in binded:
            message.append(i[0]+"已于"+i[1].strftime('%Y-%m-%d %H:%M:%S')+"与垛标"+i[2]+"绑定")
    data['message'] = (",").join(message)
    cur.execute("select count(*) from (select label_pk_id from codes where binded = false and label_pk_id is not null group by  label_pk_id)z")
    r = cur.fetchone()
    if r[0] == 0 :
        data['e']='当前扫描暂无箱标可绑定！'
        return JsonResponse(data)
    s = "INSERT INTO logistics.inventory_stack ( code, location, qty_lmt, is_fixed, company_id, store_id, product_id, remark, parent_id, dt, tm, is_physical) " +\
        " VALUES ('"+stack+"', NULL, "+str(r[0])+", 'f', "+cid+", null, "+pid+", NULL, NULL, now(), now(), '"+physical+"') on conflict (company_id,code) do nothing returning id"
    cur.execute(s)
    r = cur.fetchone()
    if not r :
        data['e']='该垛标已存在!'
        return  JsonResponse(data)
    cls_id = str(r[0])

    s = "INSERT INTO inventory_stackdetails(company_id,product_id,label_pk_id,label_id,label_pkg,label_code,tm,stack_id)  " +\
        "select company_id,product_id,label_pk_id,label_id,label_pkg,code,now(),"+str(cls_id)+ \
        " from codes where binded = false and label_pk_id is not null on CONFLICT(stack_id,label_pk_id) do nothing "
    cur.execute(s)
    return JsonResponse(data)
    
    

@csrf_exempt
def returning_of_stacks(request,cid):
    data = {'e': '', 'stack': '', 'details': [], 'qty_lmt': 0}
    e = time_key_check(request,sK)
    if e:
        data['e'] = e
        return JsonResponse(data)
    code = request.GET.get('code', '')
    q = LabelQuery(cid, code)
    label_pk_id = q.get_label_pk()
    if not label_pk_id:
        data['e'] = '标签数据异常'
        return JsonResponse(data)
    stack = StackDetails.objects.filter(company_id=cid, label_pk_id=label_pk_id)
    if stack:
        stack_id=stack[0].stack.id
        stackD = StackDetails.objects.filter(company_id=cid, stack=stack_id)
        for i in stackD:
            data['details'].append(i.label_code)
        stack = Stack.objects.get(id=stack_id)
        data['stack'] = stack.code
        data['qty_lmt'] = stack.qty_lmt
    else:
        data['e'] = '该标签暂未找到归属垛标'
    return JsonResponse(data)


@login_required
def cat_batchno_details(request,batch_id):
    data = {'e': '未知','details':[]}
    c = request.user.company
    cur = connection.cursor()
    package = get_package_name(c.ancestor_id)
    s = "select count(*),c.name,(SELECT dt_inbound FROM batchlot.c19267  where label_pk_id = a.label_pk_id order by id desc limit 1) dt_inbound, "+\
	    " (SELECT batch_no FROM batchlot.c19267  where label_pk_id = a.label_pk_id order by id desc limit 1) batch_no,d.shelf_life  from ( " +\
        "SELECT label_pk_id,label_pkg,product_id FROM stkdetails.c"+str(c.ancestor_id)+\
        " WHERE batch_id = "+str(batch_id)+" AND company_id = "+str(c.ancestor_id)+")A "+\
        " left outer join (select id ,name from label.lbl_package )c on c.id = a.label_pkg " +\
        " left outer join (select shelf_life,id from logistics.product_product)d on d.id = a.product_id " +\
        "  GROUP BY dt_inbound, batch_no, c.name,d.shelf_life"
    cur.execute(s)
    r = cur.fetchall()
    if r :
        data['e'] = ''
        for i in r : 
            life = json.loads(i[4])
            shelf_life = ''
            shelf_day = ''
            qty = i[1][:-1]
            if i[1] == "瓶":
                qty = package[0]
            elif i[1] == "盒":
                qty = package[1]
            elif i[1] == "箱":
                qty = package[2]
            if i[3]:
                if i[4]:
                    if life['period'] == 'year':
                        shelf_life = i[2]+relativedelta(years=life['value'])
                    elif life['period'] == 'month':
                        shelf_life = i[2]+relativedelta(months=life['value'])
                    else:
                        shelf_life = i[2]+relativedelta(days=life['value'])
                if shelf_life:
                    shelf_day =shelf_life - datetime.datetime.now().date()
                
                data['details'].append([i[3],i[2],shelf_day.days,shelf_life,str(i[0])+qty])
            else:
                data['details'].append(['未知', '未知', '未知', '未知', str(i[0]) + qty])
    return JsonResponse(data)



# 2022-11-02 标签替换
@login_required
def label_replace(request,what,id=None):
    cur = connection.cursor()    
    u=request.user
    cid=str(u.company_id)

    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
    
    actions=['list','view','check','update','delete']
    if what not in actions:
        return JsonResponse({'e':'action error'})  
    if what=='list':
        clmns=[ 
            {"title":"时间",  "data":"tm"},
            {"title":"数据源",  "data":"src"},
            {"title":"备注说明",  "data":"remark"}, #2023-07-18
            {"title":"操作人",    "data":"usr"},
            {"title":"记录数",    "data":"cnt"},
            {"title":"审核人",    "data":"checker"},
            {"title":"审核时间",    "data":"tm_checked"},
        ]
        data=[]
        s="select to_char(tm,'yyyy-mm-dd hh24:mi:ss') tm,coalesce(txt_file,'') src,"+\
            "(select coalesce(last_name,username) from company_user where id=user_id) usr,"+\
            "(select count(id) from label.lbl_replace_details where   batch_id=b.id) cnt,"+\
            "coalesce((select coalesce(last_name,username) from company_user where id=b.checked_by),'') checker,"+\
            "coalesce(to_char(tm_checked,'yyyy-mm-dd hh24:mi:ss'),'') tm_checked,"+\
            "id,coalesce(remark,'') from label.lbl_replace_batch b "+\
            "where company_id="+cid+" and (dt between '"+dt_fr+"' and '"+dt_to+"') "+\
                "and (select count(1) from label.lbl_replace_details where batch_id=b.id)>0"
        cur.execute(s)
        for r in cur.fetchall():
            a='<a href="/inventory/label/replace/view/'+str(r[6])+'/" class="btn-view">'+r[0]+'</a>'            
            data.append({"tm":a,"src":r[1],"usr":r[2],"cnt":r[3],"checker":r[4],"tm_checked":r[5],"DT_RowId":r[6],'remark':r[7]})
        cur.close()        
        return render(request,'inventory/label/replace/list.html',{
            'data':data,'clmns':clmns,'params':{'dt_fr':dt_fr,'dt_to':dt_to}            
        })

    elif what=='view':
        # 2022-11-07  审核按键权限
        #2;"罗秋吉";"";"罗秋吉"   73712;"tyf";"";"腾雨峰"
        can_edit=False
        if cid=='1' and  u.id in [2,73712]:
            can_edit=True        
        cur.execute("select coalesce(txt_file,'未知'),"+\
            "(select coalesce(last_name,username) from company_user where id=checked_by),"+\
            "tm_checked from label.lbl_replace_batch where id="+id)
        r=cur.fetchone()
        src=r[0]
        if r[1]:            
            checked_by=r[1]
            checked_tm=r[2].strftime('%Y-%m-%d %H:%M:%S')            
        else:
            checked_by=''
            checked_tm=''  
        
        clmns=[ 
            {"title":"旧标签",  "data":"code0"},
            {"title":"标签类型",  "data":"code0_pkg"},
            {"title":"新标签",  "data":"code"},
            {"title":"标签类型",  "data":"code_pkg"},
            {"title":"时间",    "data":"tm"},
            {"title":"备注",    "data":"remark"},
        ]
        data=[]
        cnt=0
        s="select id,code0,code,to_char(tm,'yyyy-mm-dd hh24:mi:ss'),"+\
            "case when code0_pkg>0 and code_pkg>0 and code0_pkg<>code_pkg then '标签类型不匹配' else '' end,"+\
            "coalesce((SELECT name from label.lbl_package where id=code0_pkg),'未知'),"+\
            "coalesce((SELECT name from label.lbl_package where id=code_pkg), '未知') "+\
            "from label.lbl_replace_details where batch_id="+id
        cur.execute(s)

        #"DT_RowId": "row_5",
        for r in cur.fetchall():
            data.append({
                "DT_RowId":r[0],
                "code0":r[1],
                "code":r[2],
                "tm":r[3],
                "remark":r[4],
                "code0_pkg":r[5],
                "code_pkg":r[6]
            })
            cnt=cnt+1      
        
        cur.close()
        return render(request,'inventory/label/replace/details.html',{
            'clmns':clmns,'data':data,'batch':{'src':src,'qty':cnt,'id':id,'checked_by':checked_by,'checked_tm':checked_tm,'can_edit':can_edit}
        })
    
    elif what=='check':
        s='update label.lbl_replace_batch set '+\
            "tm_checked=now(),checked_by="+str(u.id)+" "+\
            "where id="+id
        cur.execute(s)
        s='update label.lbl_replace_details set checked=true '+\
            "where batch_id="+id        
        cur.execute(s)
        cur.close()        
        return JsonResponse({'e':''})
    elif what=='update':
        data={'e':'','cnt':0}
        obj=request.GET.get('obj','')
        cnt=0
        if not obj or not id:
            data['e']='parameter missing'
        else: 
            # 标签替换的修改操作，只会针对明细记录            
            code0=request.GET.get('code0','')
            code=request.GET.get('code','')
            remark=request.GET.get('remark','')
            if not code0 or not code:
                data['e']='fields missing'                   
            else:
                # 取出原始值
                cur.execute("select code0,code,remark from label.lbl_replace_details where id="+id)
                r=cur.fetchone()
                if r:
                    d={
                        'code0':    {'old':r[0],'new':code0},
                        'code':     {'old':r[1],'new':code},
                        'remark':   {'old':r[2],'new':remark}
                    }
                    s="update label.lbl_replace_details set "+\
                        "code0='"+code0+"',code='"+code+"',remark='"+remark+"' where id="+id
                    cur.execute(s)
                    cnt=cur.rowcount 
                    
                    # 写入操作日志 action=models.SmallIntegerField(_('操作类型'),choices=( (1,_('修改')),  (2,_('删除')) ))
                    s="INSERT INTO company_operationlog(company_id,user_id,tb_name,object_id,action,changes) values ("+\
                        cid+","+str(u.id)+",'label.lbl_replace_details',"+id+",1,'"+json.dumps(d)+"'"+\
                    ")"
                    cur.execute(s)
                else:
                    data['e']='details id not exists'
        cur.close()
        return JsonResponse(data)
    elif what=='delete':
        data={'e':'','cnt':0}
        obj=request.GET.get('obj','')        
        if not obj or not id:
            data['e']='parameter missing'
        else:  
            if obj=='details':
                # 取出原始值
                cur.execute("select id,code0,code,remark from label.lbl_replace_details where id="+id)
                r=cur.fetchone()
                if r:
                    d={'id':r[0], 'code0':r[1], 'code':r[2], 'remark':r[3]},
                    # 标签替换明细不做物理删除，只打删除标记
                    cur.execute("update label.lbl_replace_details set is_delete=true where id="+id)
                    data['cnt']=cur.rowcount
                    s="INSERT INTO company_operationlog(company_id,user_id,tb_name,object_id,action,changes) values ("+\
                        cid+","+str(u.id)+",'label.lbl_replace_details',"+id+",2,'"+json.dumps(d)+"'"+\
                    ")"
                    cur.execute(s)
                else:
                    data['e']='details id not exists'
            elif obj=='batch':     
                d={'details':[]}
                # 删除前将要删除的明细写入日志
                s="select id,code0,code,coalesce(remark,''),to_char(tm,'yyyy-mm-dd hh24:hi:ss') from label.lbl_replace_details where batch_id="+id
                cur.execute(s)
                for r in cur.fetchall():
                    d['details'].append({"id":r[0],"code0":r[1],"code":r[2],"remark":r[3],"tm":r[4]})
                s="INSERT INTO company_operationlog(company_id,user_id,tb_name,object_id,action,changes) values ("+\
                    cid+","+str(u.id)+",'label.lbl_replace_batch',"+id+",2,'"+json.dumps(d)+"'"+\
                ")"
                cur.execute(s)    
                # 整批删除为物理删除，包括batch和对应details明细
                cur.execute("delete from label.lbl_replace_details where  batch_id="+id)
                cur.execute("delete from label.lbl_replace_batch where id="+id)
                data['cnt']=cur.rowcount  
            else:
                data['e']='obj name error'
        cur.close()
        return JsonResponse(data)


def jcs_virtual_stack_binding(batch,stack_binding,company_id):
    data = {'e': '' }
    # 2022-07-20 数据写入日志
    cs = Company.objects.filter(id=int(company_id))
    c = cs[0]
    cur= connection.cursor()
    cur.execute("create temp table temps(" + \
                "id serial," + \
                "label_code character varying(32) ," + \
                "tb character varying(20)," + \
                "product_id integer," + \
                "stack_id integer," + \
                "wrapper_id integer," + \
                "code character varying(32)," + \
                "label_id bigint," + \
                "label_pk_id bigint," + \
                "label_pkg smallint," + \
                "err character varying(100)," + \
                "label_code0 character varying(32)," + \
                "from_agent_id integer)"
                )

    insert_sql = []
    codes=[]
    for i in stack_binding:
        is_physical = True
        code = i['stack']
        if code[:4] == 'xndb':
            is_physical = False
        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
        stack.is_physical = is_physical
        if 'location' in i:
            stack.location = i['location']
        if 'qty_lmt' in i:
            stack.qty_lmt = i['qty_lmt']
        if 'is_fixed' in i:
            stack.is_fixed = i['is_fixed']
        stack.qty_lmt = 0
        stack.save()
        if batch.product_id:
            product_id = str(batch.product_id)
        else:
            product_id = 'null'
        for l in i['codes']:
            insert_sql.append("('" + l + "','" + l[:4] + "'," + product_id + "," + str(stack.id) + ")")
            codes.append(l)
        # s = "INSERT INTO inventory_stackdetails(company_id,product_id,label_pk_id,label_id,label_pkg,label_code,tm,stack_id) " + \
        #     "select company_id,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"
    sSql = "insert into temps(label_code,tb,product_id,stack_id) " \
           "values " + ",".join(insert_sql)
    cur.execute(sSql)

    stacks = []
    stack_binding = ''
    # 2022-05-10 保存原始标签号码
    cur.execute("update temps set label_code0=label_code")


    s = "update temps 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 temps set tb=b.tbname from " + \
        "(SELECT tb,label_code from temps) a " + \
        "left outer join " + \
        "(SELECT segment, tbname FROM label.lbl_tbcross) b " + \
        "on a.tb=b.segment " + \
        "where  temps.label_code=a.label_code and b.tbname is not null"
    cur.execute(s)


    # 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 temps " + \
        "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 temps 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 temps set tb='t'||left(code,4) where length(tb)=4")

    cur.execute("select tb from temps 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 temps 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 temps 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 temps.code=a.code"
            cur.execute(s)


    # 没有标签id的，看是不是企业第三方标签
    s = "update temps 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 temps.code=a.code and label_id is null"
    cur.execute(s)


    s = "INSERT INTO inventory_stackdetails(company_id,product_id,label_pk_id,label_id,label_pkg,label_code,tm,stack_id) " + \
        "select "+str(company_id)+",product_id,label_pk_id,label_id,label_pkg,label_code,now(),stack_id " + \
        "from  temps where  label_pk_id is not null and stack_id>0 " + \
        "on CONFLICT(stack_id,label_pk_id) do nothing"
    cur.execute(s)
    return data




# 2022-11-24 破损标号码重新生成二维码
@login_required
def tj_qrcode(request):
    codes=request.GET.get('codes','')
    if codes:    
        images=[]
        cs=codes.replace('，',',').split(',')   
        n=0
        msg=''
        company_id=request.user.company_id
        errors=[]
        for c in cs:
            c=c.strip()
            # 一次最多允许补9个二维码,瓶盖码、小圆标活动码不能补码
            if n<10:
                if len(c)==12:
                    if c.isdigit():                    
                        q=LabelQuery(company_id,c)
                        if q.get_label_pk():
                            data='http://tj1.me/?t='+c 
                            img=qrcode.make(data) 
                            buf = io.BytesIO()
                            img.save(buf, format="PNG")   
                            i=b64encode(buf.getvalue()).decode('utf-8')  
                            images.append({'code':c,'image':i})
                            n=n+1
                        else:
                            errors.append(c)
                    else:
                        errors.append(c)
                else:
                    errors.append(c)
            else:
                msg='一次最多允许补10个物流码'
        e=''
        if errors:
            msg='不正确的物流码：'+','.join(errors)
        return JsonResponse({'msg':msg, 'e':e, 'images':images})
    else:
        return render(request,'inventory/label/qrcodes.html')


# 2022-11-29 定义积分发生变化信号
import django.dispatch

points_changed = django.dispatch.Signal()


# 如在model类定义内调用：   points_changed.send(sender=self)
# 如在views(obj)内调用：    points_changed.send(sender=obj)

def process_points_changed(sender, **kwargs):
    # 参数：sender 发送信号的model类实例

    # 返加值
    data = {
        'e': '',  # 报错信息
        'channelpromotion_id': 0,  # 渠道促销方案id
        'company_id': 0,  # 经销商id
        'user_id': 0,  # 用户id
        'points': 0  # 当前积分变化值
    }

    # 信号发送者sales_channelpromotiontrigger
    # id 3;ContentType 293;"inventory";"receipt" 收货确认   id 2;ContentType 320;"banquet";"apply" 宴会申请
    ctt = ContentType.objects.get_for_model(sender)
    tb = ctt.app_label + '_' + ctt.model  # 也可以tb=sender._meta.app_label+'_'+sender._meta.model_name

    # 信号发送者一定有company字段
    c = Company.objects.get(id = sender.company_id)
    # 信号发送者一定有company字段
    # u=sender.user
    data['company_id'] = c.id
    # data['user_id']=u.id


    # 先判断当前是否有符合条件的渠道营销方案正在进行 表名：sales_channelpromotions
    sPrd = ''
    sSaldiv = ''
    sSubdiv = ''
    # 是否传参product_id
    if 'product_id' in kwargs:
        sPrd = " and case when array_length(products,1) is null then true else ARRAY[" + str(
            kwargs['product_id']) + "] <@ products end "
    # 经销商是否含销售战区信息
    if c.division:
        sSaldiv = " and case when array_length(div_ids,1) is null then true else ARRAY[" + str(
            c.division_id) + "] <@ div_ids end "
    # 经销商是否含销售分区信息
    if c.sub_division:
        sSubdiv = " and case when array_length(div_ids,1) is null then true else ARRAY[" + str(
            c.sub_division_id) + "] <@ div_ids end "
    # 当前经销商是否符合渠道营销方案

    t = datetime.datetime.now().strftime('%Y-%m-%d %H:%M')
    aid = str(c.ancestor_id)
    s = "select id,name,awardcategory_id,triggers,point_ratio from sales_channelpromotions " + \
        "where company_id=" + aid + " and ('" + t + "' between tm_start and tm_end) and status=1 " + \
        sPrd + sSaldiv + sSubdiv
    sTrigger = ''
    cur = connection.cursor()
    if tb == 'banquet_apply':
        # print('宴会申请')
        sTrigger = " and triggers @> '[{\"id\":\"2\"}]'::jsonb "
        s = s + sTrigger + " order by priority"
        cur.execute(s)
        r = cur.fetchone()
        if r:
            # 渠道促销活动id
            channelpromotions_id = r[0]

            # 奖励类型id
            # sales_awardcategory 1;"实物"2;"积分 "3;"优惠券 "4;"微信红包"5;"记账现金"6;"代金券"7;"卡券"8;"福袋"
            awd_id = r[2]

            # 宴会申请 返利详情
            # {"package":"1", "value":"1"}
            details = {}
            for d in json.loads(r[3]):
                if d['id'] == '2':
                    details = d['details']
            # 有宴会申请设置信息
            if details:
                # 业务逻辑处理
                self_p_ratio = 1
                if details['package'] == 1 or details['package'] == '1' or details['package'] == 2 or details['package'] == '2':
                    self_p_ratio = details['value']
                request_rebate_points(sender, channelpromotions_id, self_p_ratio)

    elif tb == 'inventory_batch':
        # print('收货确认')
        sTrigger = " and triggers @> '[{\"id\":\"3\"}]'::jsonb "
        s = s + sTrigger + " order by priority"
        cur.execute(s)
        r = cur.fetchone()
        if r:
            # 渠道促销活动id
            channelpromotions_id = r[0]

            # 奖励类型id
            # sales_awardcategory 1;"实物"2;"积分 "3;"优惠券 "4;"微信红包"5;"记账现金"6;"代金券"7;"卡券"8;"福袋"
            awd_id = r[2]

            # 收货确认 返利详情
            # {"package":"1", "value_level1":"1", "value_level2":"2","value_terminal":"3"}
            details = {}
            for d in json.loads(r[3]):
                if d['id'] == '3':
                    details = d['details']
            # 有收货确认设置信息
            if details:
                # 业务逻辑处理
                if details['package'] == 1 or details['package'] == '1' or details['package'] == 2 or details['package'] == '2':
                    self_p_ratio = details['value_terminal']
                    parent_p_ratio = details['value_level1']
                    request_rebate_points(sender,channelpromotions_id,self_p_ratio,parent_p_ratio)

    else:
        # 当前系统 只有宴会申请和收货确认 会产生积分变化
        data['e'] = 'sender not surported'
    if not data['e']:
        pass

    cur.close()
    return data
    
points_changed.connect(process_points_changed)


#检查标签是否入库
def label_infor_check(request,user_id):
    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)
    u = User.objects.get(id=int(user_id))
    c = u.company
    cs = Company.objects.get(id=int(c.id))
    aid = cs.ancestor_id
    tb_stk = "stkdetails.c" + str(aid)
    l = request.GET.get('label', '')
    if not l:
        data['e']='label_code missing'
        return JsonResponse(data)
    data['label_code'] = l
    cur = connection.cursor()
    s=f"""
    select label_code,label_pk_id from {tb_stk} where label_code='{l}' and vtype_id=1
    """
    cur.execute(s)
    r=cur.fetchone()
    if r:
        data['label_pk_id']=r[1]
    else :
        s=f"""
        select id,code,parent_id from label.t{l[0:4]} where code='{l}'
        """
        try:
            cur.execute(s)
            rr=cur.fetchone()
            if rr:
                s=f"""
                select label_code,label_pk_id from {tb_stk} where label_pk_id='{rr[2]}' and vtype_id=1
                """
                cur.execute(s)
                rrr=cur.fetchone()
                if not rrr:
                    data['e']=_('标签号码未入库')
            else:
                data['e']=_('标签号码错误')
        except Exception:
            data['e']=_('标签号码不存在')
    cur.close
    return JsonResponse(data)


# confirm goods receipt Jun. 1 2023
def format_str_date(date: str):
    return datetime.datetime.strptime(date, '%Y-%m-%d').date()


def get_not_received_batch_ids(company_from_id: int, company_to_id: int, period: list):
    start = format_str_date(period[0])
    end = format_str_date(period[1])
    batch_ids = Batch.objects.filter(
        **{
            'company_fr_id': company_from_id,
            'company_to_id': company_to_id,
            'vtype_id': 2,  # 只用查出库
            'dt__range': (start, end)
        }
    ).exclude(
        pk__in=Receipt.objects.values('batch_id')
    ).values_list('pk', flat=True)
    return batch_ids


def get_stkdetail_amount_by_batch(batch_id, company_id):
    sql = f"""SELECT SUM(CASE WHEN label_pkg = 3 THEN 1 ELSE 0 END) carton,
    SUM(CASE WHEN label_pkg = 2 THEN 1 ELSE 0 END) box,
    SUM(CASE WHEN label_pkg = 1 THEN 1 ELSE 0 END) bottle
FROM stkdetails.c{company_id} WHERE batch_id = {batch_id} AND NOT is_delete AND company_id = {company_id}"""
    return query_json(sql)[0]


def get_not_received_batch_amount(request):
    try:
        company_from_id = request.GET.get('companyFromId', '')
        company_to_id = request.GET.get('companyToId', '')
        start = request.GET.get('start', '')
        end = request.GET.get('end', '')
        res = get_not_received_batch_ids(company_from_id, company_to_id, [start, end]).__len__()
        return JsonResponse({"data": res}, status=200)
    except Exception as e:
        return JsonResponse({"e": e.args}, status=500)


def get_not_received_batch_details(request):
    try:
        company_from_id = request.GET.get('companyFromId', '')
        company_to_id = request.GET.get('companyToId', '')
        start = request.GET.get('start', '').replace('/', '-')
        end = request.GET.get('end', '').replace('/', '-')
        page_size = int(request.GET.get('pageSize', 10))
        current = int(request.GET.get('current', 1))

        batch_ids = get_not_received_batch_ids(company_from_id, company_to_id, [start, end])
        data = []
        batchs = Batch.objects.filter(pk__in=batch_ids).values_list(
            'id', 'code', 'product_id').order_by(
            'id')[(current - 1) * page_size:(current - 1) * page_size + page_size]
        for batch in batchs.values('id', 'code', 'product_id'):
            product = Product.objects.get(pk=batch['product_id'], is_delete=False)
            quantity = get_stkdetail_amount_by_batch(batch['id'], company_from_id)
            data.append({
                'id': batch['id'],
                'productName': product.name,
                'code': batch['code'],
                'carton': quantity['carton'],
                'box': quantity['box'],
                'bottle': quantity['bottle']
            })
        res = {
            'total': batch_ids.__len__(),
            'current': current,
            'pageSize': page_size,
            'data': data
        }
        return JsonResponse({"data": res}, status=200)
    except Exception as e:
        return JsonResponse({"e": e.args}, status=500)


@csrf_exempt
def confirm_receipt(request):
    try:
        body = json.loads(request.body)
        batch = Batch.objects.get(pk=body['batchId'])
        user = User.objects.get(pk=body['userId'])
        company = Company.objects.get(pk=body['companyId'])
        if batch.company_to_id != body['companyId']:
            raise Exception("收货公司不符")
        if user.company_id != body['companyId']:
            raise Exception("用户数据异常")
        receipt = Receipt(
            ancestor_id=company.ancestor_id,
            company=company,
            batch=batch,
            user=user
        )
        receipt.save()
        return JsonResponse({"data": {"id": receipt.id}}, status=200)
    except django.core.exceptions.ObjectDoesNotExist as e:
        e = str(e).split(' ')[0]
        return JsonResponse({"e": e + '不存在'}, status=404)
    except Exception as e:
        return JsonResponse({"e": e.args}, status=500)









# 2023-06-09 
def product_borrowing(ancestor_id=None,agent_id=None,borrowing=[]):
    '''
    如茗酒荟业务员代分销，借货业务   
    ancestor_id:企业id,    
    agent_id:发生借货业务的经销商id,
    borrowing:[{
        'agent_id':借货涉及到的第三方id,
        'product_id':产品id, 
        'codes':[{'label_code':箱标号码,'label_id':标签ID,'label_pk_id':主箱标id}]
    }]
    42;"GBI";"借货入库"; 1;"从别的公司借入"
    43;"GBO";"借货出库";-1;"把库存产品借给其它公司"   
    '''
    data={'e':''}
    if not ancestor_id or not agent_id or not borrowing:
        data['e']="ancestor_id,agent_id,borrowing missing or not assigned"
        return data
    if not isinstance(borrowing,list):
        data['e']='borrowing should be a list'
        return data

    cur=connection.cursor()
    aid=str(ancestor_id)
    tb="stkdetails.c"+aid
    uid=14499 # 14499;"system" "系统管理员"
    
    dt=datetime.datetime.now().strftime('%Y%m%d')
    n=1
    agent_id=str(agent_id)
    for br in borrowing:       
        cd=dt+"-"+str(n).zfill(2)        
        pid=str(br['product_id'])        
        a_in=[]
        a_out=[]
        
        # inventory.Batch                
        # 借货出库
        b=Batch(
            code=cd,
            ancestor_id=int(ancestor_id),
            company_id=int(br['agent_id']),
            vtype_id=43,
            product_id=int(pid),
            company_to_id=int(agent_id),
            user_id=uid
        )    
        b.save()
        id_out=b.id     

        # 借货入库
        b=Batch(
            code=cd,
            ancestor_id=int(aid),
            company_id=int(agent_id),
            vtype_id=42,
            product_id=int(pid),
            company_fr_id=int(br['agent_id']),
            user_id=uid
        )
        b.save()
        id_in=b.id      

        # inventory.Details
        sIns="insert into inventory_batchdetails(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id,ancestor_id,product_id)" 
        for c in br['codes']:
            a_in.append("("+str(id_in)+",'"+c['label_code']+"',"+str(c['label_id'])+","+str(c['label_pkg'])+","+str(c['label_pk_id'])+","+str(agent_id)+","+aid+","+pid+")")
            a_out.append("("+str(id_out)+",'"+c['label_code']+"',"+str(c['label_id'])+","+str(c['label_pkg'])+","+str(c['label_pk_id'])+","+str(br['agent_id'])+","+aid+","+pid+")")
                
        # 借货出库明细
        cur.execute(sIns+" values "+",".join(a_out))         
        s="insert into "+tb+"(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id,ancestor_id,product_id,vtype_id,company_to_id) select "+\
            "batch_id,label_code,label_id,label_pkg,label_pk_id,company_id,ancestor_id,product_id,43,"+str(agent_id)+" "+\
            "from inventory_batchdetails where batch_id="+str(id_out)
        cur.execute(s)
        # 借货入库明细
        cur.execute(sIns+" values "+",".join(a_in))  
        s="insert into "+tb+"(batch_id,label_code,label_id,label_pkg,label_pk_id,company_id,ancestor_id,product_id,vtype_id,from_agent_id) select "+\
            "batch_id,label_code,label_id,label_pkg,label_pk_id,company_id,ancestor_id,product_id,42,"+str(br['agent_id'])+" "+\
            "from inventory_batchdetails where batch_id="+str(id_in)
        cur.execute(s)  
        n=n+1
    cur.close()
    return data

#2023-06-14,在出库时检查叶嘉岩产品绑定规格是否一致
def product_specification(request,product_id):
    data = {'e': '', 'label_pk_id': 0, 'label_id': 0, 'label_package': 0, 'label_code': ''}
    e = time_key_check(request, sK)
    p=Product.objects.get(id=int(product_id))
    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()
    s=f"""select value   from product_productprop where 
        id=(SELECT prd_property_id  FROM product_prdprops where product_id={p.id} 
        and (SELECT categoryprop_id FROM product_productprop where id=prd_property_id)=10)
    """
    cur.execute(s)
    index=cur.fetchone()
    s=f"""
    select package_id from label.t{l[0:4]} where code='{l}' and package_id=3
    """
    cur.execute(s)
    label_pkg=cur.fetchone()
    if label_pkg:
        if index:
            if p.company_id==32597:
                s=f"""
                select bottle_tb,box_tb from carton.t{l[0:4]} where code='{l}'
                """
                try:
                    cur.execute(s)
                    r=cur.fetchone()
                    if r :
                        s=f"""
                            select round(cast(sum(package_id) as numeric)/cast(package_id as numeric),0) from label.t{r[0][0:4]}  
                            where parent_id=(select id from label.t{l[0:4]} where code='{l}')  group by package_id   
                        """
                        cur.execute(s)
                        rr=cur.fetchone()
                        if rr:
                            if str(rr[0]) != str(index[0][2:4]):
                                data['e']=_('数据未绑全')
                        else:
                            data['e'] = _('未绑定数据')
                    else:
                        s=f"""
                            select round(cast(sum(package_id) as numeric)/cast(package_id as numeric),0) from label.t{l[0:4]} 
                            where parent_id=(select id from label.t{l[0:4]} where code='{l}')  group by package_id
                        """
                        cur.execute(s)
                        rr=cur.fetchone()
                        if rr:
                            if str(rr[0]) != str(index[0][2:4]):
                                data['e'] = _('数据未绑全')
                        else:
                            data['e'] = _('未绑定数据')
                except Exception:
                    try:
                        s = f"""
                            select round(cast(sum(package_id) as numeric)/cast(package_id as numeric),0) from label.t{l[0:4]} 
                            where parent_id=(select id from label.t{l[0:4]} where code='{l}')  group by package_id
                        """
                        cur.execute(s)
                        rr = cur.fetchone()
                        if rr:
                            if str(rr[0]) != str(index[0][2:4]):
                                data['e'] = _('数据未绑全')
                        else:
                            data['e'] = _('未绑定数据')

                    except Exception:
                        data['e'] = _('标签号码不存在')
        else:
            s = f"""
                select bottle_tb,box_tb from carton.t{l[0:4]} where code='{l}'
                """
            try:
                cur.execute(s)
                r = cur.fetchone()
                if r:
                    s = f"""
                        select round(cast(sum(package_id) as numeric)/cast(package_id as numeric),0) from label.t{l[0:4]} 
                        where parent_id=(select id from label.t{l[0:4]} where code='{l}')  group by package_id    
                    """
                    cur.execute(s)
                    rr = cur.fetchone()
                    if not rr:
                        data['e'] = _('未绑定数据')
                else:
                    s = f"""
                        select round(cast(sum(package_id) as numeric)/cast(package_id as numeric),0) from label.t{l[0:4]} 
                            where parent_id=(select id from label.t{l[0:4]} where code='{l}') group by package_id 
                    """
                    cur.execute(s)
                    rr = cur.fetchone()
                    if not rr:
                        data['e'] = _('未绑定数据')
            except Exception:
                try:
                    s = f"""
                            select round(cast(sum(package_id) as numeric)/cast(package_id as numeric),0) from label.t{l[0:4]} 
                                where parent_id=(select id from label.t{l[0:4]} where code='{l}') group by package_id 
                        """
                    cur.execute(s)
                    rr = cur.fetchone()
                    if not rr:
                        data['e'] = _('未绑定数据')
                except Exception:
                    data['e'] = _('标签号码不存在')

    cur.close
    return JsonResponse(data)
    
 
@login_required
def stkdetails_not_in_stock(request,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)

    data = []
    clmns = ['经销商', '产品', '未入库量' ]
    cur = connection.cursor()
    s = f'''
        SELECT * from (SELECT a.company_to_id,d.name,a.product_id,COALESCE(c.name,''),sum(a.cnt)as out_cnt,sum(COALESCE(b.cnt,0)) as in_cnt from 
        ( SELECT count(*)cnt,company_to_id,product_id from stkdetails.c19257 WHERE vtype_id = 2  GROUP BY company_to_id,product_id)A
        left outer JOIN (SELECT count(*)cnt,company_id,product_id from stkdetails.c19257 WHERE vtype_id = 1 and  company_id != {company_id} GROUP BY company_id,product_id)b on b.company_id = a.company_to_id and a.product_id = b.product_id
        LEFT outer join (SELECT id,name from logistics.product_product)c on c.id = a.product_id
        LEFT outer join (SELECT id,name from logistics.company_company WHERE	 ancestor_id = {company_id}  or id in(11013,11014)  )d on d.id = a.company_to_id
        GROUP BY a.company_to_id,d.name,a.product_id,c.name  )a 
        ;
        '''

    cur.execute(s)
    rs = cur.fetchall()
    for r in rs :
        qty = int(r[4] -r[5])
        data.append([r[1],r[3],qty])
    return render(request, 'inventory/stock/not_in_stock.html', {
        'data': SafeString(data),
        'clmns':clmns
    })

@csrf_exempt
def agent_label_query(request,ancestor_id):
    data={"e":"","data":None,"dn_number":None,"product":None}
    r = json.loads(request.body)
    
    data['e'] = '尚未开通访问权限'
    return JsonResponse(data)
    
    sK = '3t$#&@jtrfdvgu'
    k = sK
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    if 'label' not in r or 'agent_id' not in r:
        data['e'] = '标签参数不能为空'
        return JsonResponse(data)

    label = r["label"]
    if not label.isnumeric() or len(label) != 12:
        data['e'] = '请输入正确标签号码'
        return JsonResponse(data)
    c = Company.objects.get(id=r['agent_id'])
    if c:
        c_name = c.name
    else:
        data['e'] = 'agent_id错误'
        return JsonResponse(data)
    q = LabelQuery(company_id=ancestor_id,code=label,agent_id=r['agent_id']) 
    if not q.infor['label_pk_id']:
        data['e'] = '标签号码错误'
        return JsonResponse(data)
    else:
        if q.get_agent_label():
            relations = q.get_relations()
            data['data'] = relations
            product = q.get_product()
            if product:
                data['product'] = {'name':product['name'],'property':product['property']}
            stk = q.get_stk_dev()
            for i in stk:
                #江苏名品叁陆伍电子科技有限公司 144322
                if i['vtype_id'] == 2 and i['customer'] == c_name :
                    data['dn_number']=i['bill_no']
        else:
            data['e'] = '暂无权限查询'
    return  JsonResponse(data)

#2023-07-18按标签起止页出入库
@tj_login_required
@csrf_exempt
def upload_inv_code(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_code.html', data)
