from django.shortcuts import render

# Create your views here.
from inventory.views import LabelQuery
import redis
from django.http import JsonResponse
import datetime
from utils.views import time_key_check
from django.conf import settings
from django.db import connection
from django.utils.translation import gettext_lazy as _


from inventory.views import sK
#sK = 'fgfdvgu$#&3t@j'
# 2024-07-02
from utils.hand import label_status



rd = redis.StrictRedis(connection_pool=settings.LABEL_CHECK_POOL)   # redis 连接池
ex=8*3600                                                           # 默认过期时间8小时

def bottlecap_check(enterprise_id, product_id, label_pk_id, bottle=None):
    # 瓶盖绑定是完整 
    """
    瓶盖绑定是完整    
    :param enterprise_id:企业id
    :param product_id: 产品id
    :param label_pk_id: 主箱标id
    :param : bottle 瓶标号码
    """
    cid=str(enterprise_id)
    pk=str(label_pk_id)
    e=''   
    if cid=='1':
        # 酒鬼酒  
        s="select bottle_cnt from z_bottle_cap_product where product_id="+str(product_id)
        if bottle:
            # 检查当前瓶
            sb="select (select count(*) from z_bottlecap_binding where bottle='"+bottle+"')"+\
                " + (select count(*) from label.bottlecap where bottle='"+bottle+"')"
        else:
            # 检查箱标
            sb="select (select count(*) from z_bottlecap_binding where label_pk_id="+pk+")"+\
                " + (select count(*) from label.bottlecap where label_pk_id="+pk+")"
    else:                
        s="select cap_cnt from mes_bottlecapproduct where product_id="+str(product_id)
        if bottle:
            sb="select count(*) from mes_bottlcap where company_id="+cid+" and label_pk_id="+pk+" and is delete=false"
        else:
            sb="select count(*) from mes_bottlcap where company_id="+cid+" and label_code='"+bottle+"' and is_delete=false"
    cur=connection.cursor()    
    cur.execute(s)
    
    r=cur.fetchone()
    if r:
        # 当前产品需要检查瓶盖绑定
        cnt=r[0]
        cur.execute(sb)
        rr=cur.fetchone()   
        if bottle:
            if not rr[0]:
                e=_('当前瓶标未绑定瓶盖')
        else:
            if rr[0]!=cnt:        
                e=_("瓶盖绑定数据不正确 "+str(rr[0])+"/"+str(cnt))
    cur.close()
    return e


def labelbinding_chek(enterprise_id,product_id,label_pk_id,h_tbs=None,p_tbs=None):
    """
    套标绑定是否完整    
    :param enterprise_id:企业id
    :param product_id: 产品id
    :param label_pk_id: 主箱标id
    :param tbs: 瓶标所在号段数组
    """
    e=''
    cur=connection.cursor()
    cur.execute("select qty_x,qty_h,qty_p from product_product where id="+str(product_id))
    r=cur.fetchone()

    if r[1]:
        # 盒数不为0， 云平台后绑定标签目前除上海易臻外，产品规格没盒瓶三级关系
        pass
    elif r[2]:
        # 2024-06-19 2177;"52度500mL小酒鬼酒（蓝盒）品鉴酒（促销）" 瓶身瓶盖都没有贴瓶标的位置，只贴箱标
        #if str(product_id)  in ['2177']:
        #    pass
        # 2024-06-24
        s="select products @> '[{\"id\":"+str(product_id)+"}]' FROM product_excemptions "+\
            "where company_id="+str(enterprise_id)+" and category_id=1"
        # 2024-07-26
        s="select products @> '[{\"id\":\""+str(product_id)+"\"}]' FROM product_excemptions "+\
            "where company_id="+str(enterprise_id)+" and category_id=1"


        cur.execute(s)
        rr=cur.fetchone()
        if rr[0]:
            pass
        else:
            a=[]
            # 为客户生产的套标有箱盒瓶三级标签，有客户如川酒只重新绑定箱盒关系，瓶盒关系不变，瓶盖码也是跟盒标绑定 
            for tb in h_tbs:
                a.append("(select count(*) cnt from "+tb+" where parent_id="+str(label_pk_id)+"  and package_id<>3)")
            s="select sum(cnt) from ("+ " union all ".join(a)+ ") u"
            cur.execute(s)
            rr=cur.fetchone()
            if rr[0]<r[2]:
                e="套标绑定不完整 "+str(rr[0])+"/"+str(r[2]) 
    cur.close()
    return e


def redis_check(enterprise_id,label_pk_id,label_pkg,label_code,username,vtype_id,agent_id=None):
    """
    企业(工厂)多用户实时扫码,在redis内存储/检查   目前先不考虑垛标检查
    """        
    prfx='c'+str(enterprise_id)+"_"+str(vtype_id)               # 键值前缀    
    tm=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')    # 当前扫码时间
    key=prfx+'_label_pk_'+str(label_pk_id)                      # 当前号码主箱标ID键名
    e=''    
    d=rd.hgetall(prfx+'_label_code_'+label_code)   
    if d:       
        #print(prfx+'_label_code_'+label_code, d)

        e="此标签 "+label_code+" "+d['time'][-8:]+" 被 "+d['user_name']+" 扫描"
    else:     
        # 遍历主箱标ID键名的列表
        for l in rd.lrange(key, 0, -1):                
            a=l.split(',')      # '209916443259,1,acc,2023-12-14 15:27:30'
            c=a[0]              # 标签号码
            p=a[1]              # 标签类型
            u=a[2]              # 扫码人
            t=a[3]              # 扫码时间
            if str(label_pkg)=='3':
                # 当前标签为箱标，可能会贴两枚标签                  
                if a[1]=='3':                        
                    e="此箱另一枚箱标 "+c+" "+t[-8:]+" 被 "+u+" 扫描"  
                else:
                    e="此箱已拆,箱内的标签 "+c+" "+t[-8:]+" 被 "+u+" 扫描"  
                break
            else:
                # 当前标签为瓶或盒，只贴一个标签                 
                if a[1]=='3':
                    e='不能拆箱,箱标 '+c+" "+t[-8:]+" 被 "+u+" 扫描"                         
                    break                                   
    if not e:      
        # 当前主箱标ID键内列表不存在或者为空，追加到当前主箱标键值列表            
        rd.lpush(key, label_code+","+str(label_pkg)+","+username+","+tm)
        rd.expire(key,ex) 
        # 创建标签号码键值对        
        rd.hmset(prfx+'_label_code_'+label_code,{
            'user_name':username,
            'time':tm,
            'label_pk_id':label_pk_id,
            'label_pkg':label_pkg
        })
        
        # rd.expire(key, ex)
        # 2024-07-04
        rd.expire(prfx+'_label_code_'+label_code, ex)

    return e


def redis_action(action,enterprise_id,vtype_id=None,label_code=None):
    """
    企业对redis实时扫码数据可执行的操作
    """
    data={'e':''}
    prfx='c'+str(enterprise_id)+"_"+str(vtype_id)               # 键值前缀
    if action=='flush':
        # 清空当前企业redis内所有相关数据
        pre=prfx+"_label_*"  
        cnt=0
        for key in rd.keys(pre):
            cnt=cnt+rd.delete(key)
        data['cnt']=cnt
    elif action=='delete':
        # 删除标签号码
        cnt=0
        if label_code:
            key=prfx+'_label_code_'+label_code
            d=rd.hgetall(key)   
            if d:
                label_pk_id=d['label_pk_id']
                label_pkg=d['label_pkg']
                u=d['user_name']
                t=d['time']
                p=d['label_pkg']
                # 删除标签号码键值对
                cnt=cnt + rd.delete(key) 
                # 删除主箱标ID列表内的标签号码 。
                key=prfx+'_label_pk_'+str(label_pk_id)                
                cnt=cnt + rd.lrem(key, 
                    count=0, #count=0 删除所有与 value 相等的值
                    value=label_code+","+str(p)+","+u+","+t
                )    
        else:
            data['e']='label_code missing'            
        data['cnt']=cnt
    return data


# 2023-12-15 考虑云平台今后统一使用这一个实时检查接口
def label_online(request,enterprise_id,action,agent_id=None):     
    '''
    GET 方法 用于企业工厂、经销商出入库时多人实时扫码的标签号码检查  
    检查内容：
    1.重复出入库
    2.数据绑定是否完整：箱盒瓶 盖 nfc
    3.出库产品是否与入库时一致(如果已入库)
    4.现场多人多设备重码扫码检查                  
    '''   
    data={'e':''}
    key=request.GET.get('key','')
    tm=request.GET.get('time','')
    k = sK   # 默认使用inventory.views sK
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    if action=='check':
        vtype_id=request.GET.get('vtype_id','')
        label_code=request.GET.get('label_code','')
        product_id=request.GET.get('product_id','')
        user_name=request.GET.get('user_name','')
        if not vtype_id or not label_code or not product_id or not user_name:
            data['e']='vtype_id,label,product_id,user_name required'
            return JsonResponse(data)

        # 取标签信息,确定label_pk_id
        q=LabelQuery(enterprise_id,label_code)
        pk=q.infor['label_pk_id']
        if not pk:
            data['e']=_('标签错误')
            return JsonResponse(data)

        if agent_id:
            # 经销商扫码在线检查 先占位
            pass

        e=''
        tb_stk='stkdetails.c'+str(enterprise_id)
        pkg=q.package['id']
        cur=connection.cursor()
        # 是否已入库
        s="select product_id,to_char(tm,'yyyy-mm-dd hh24:mi:ss'),(select name from product_product where id=product_id) "+\
            "from "+tb_stk+" where vtype_id=1 and label_pk_id="+str(pk)+" and is_delete=false"
        cur.execute(s)
        r0=cur.fetchone()
        if str(vtype_id)=='1':
            if r0:
                e="已于 "+r0[1]+" 入库 名称:"+r0[2]
            else:
                # 瓶盖码绑定
                bt=None
                if pkg==1:
                    bt=label_code     
                e=bottlecap_check(enterprise_id, product_id, pk,bottle=bt)  
                if not e:
                    # 套标绑定是否完整
                    h_tbs=[]    # 盒标表
                    p_tbs=[]
                    pkc=q.infor['label_pk_code'] # 主箱标号码
                    if q.infor['carton_codes']:
                        # 有跨段
                        for c in q.infor['carton_codes']:
                            cur.execute("select box_tb,bottle_tb from carton.t"+c+" where code='"+pkc+"'")
                            r=cur.fetchone()
                            if r:
                                if r[0]:
                                    h_tbs.append("label.t"+r[0])
                                else:
                                    h_tbs.append("label.t"+pkc[:4])
                                if r[1]:
                                    b_tbs.append("label.t"+r[1])
                                else:
                                    b_tbs.append("label.t"+pkc[:4])
                    else:
                        # 不跨段
                        if str(enterprise_id)=='1':
                            # 历史原因，酒鬼专用一个跨段表
                            h_tbs=['label.t'+pkc[:4], 'label.lbl_binding_jg']
                            p_tbs=['label.t'+pkc[:4], 'label.lbl_binding_jg']
                        else:
                            h_tbs=['label.t'+pkc[:4]]
                            p_tbs=['label.t'+pkc[:4]]                    
                    e=labelbinding_chek(enterprise_id,product_id,pk,h_tbs,p_tbs)                   
        
        elif str(vtype_id)=='2' :
            # 数据库内是否已有相同的操作记录            
            #s="select to_char(tm,'yyyy-mm-dd hh24:mi:ss'),label_pkg,"+\
            #    "(select remark from inventory_voucher where id="+str(vtype_id)+"),label_code "+\
            #    "from "+tb_stk+" where vtype_id="+str(vtype_id)+" and is_delete=false "+\
            #    "and label_pk_id="+str(pk)                        
            #cur.execute(s)            
            #for rr in cur.fetchall():
            #    if pkg==3:
            #        if rr[1]==3:
            #            e=_('此箱 '+rr[0]+" 已"+rr[2])
            #        else:
            #            e=_('此箱 '+rr[0]+" 已拆箱"+rr[2])
            #        break
            #    else:
            #        if rr[1]==3:
            #            e=_('此标签所在箱 '+rr[0]+" 已"+rr[2])
            #            break
            #        else:
            #            if rr[3]==label_code:
            #                e=_('此标签 '+rr[0]+" 已"+rr[2])
            #                break
            

            # 2024-01-24 是否已出库，且最后一条记录不是退库
            s="select to_char(tm,'yyyy-mm-dd hh24:mi:ss'),label_pkg,"+\
                "(select remark from inventory_voucher where id="+str(vtype_id)+"),label_code "+\
                "from "+tb_stk+" s where vtype_id="+str(vtype_id)+" and is_delete=false "+\
                "and label_pk_id="+str(pk)+" "+\
                "and (select vtype_id from "+tb_stk+" where label_pk_id="+str(pk)+" order by id+0 desc limit 1)<>4 "+\
                "order by id+0 desc limit 1"
            # 2025-03-20 是否有出库记录，且不存在大于出库记录id的退库记录存在
            s="select to_char(tm,'yyyy-mm-dd hh24:mi:ss'),label_pkg,"+\
                "(select remark from inventory_voucher where id="+str(vtype_id)+"),label_code "+\
                "from "+tb_stk+" s where vtype_id=2 and is_delete=false and label_pk_id="+str(pk)+" "+\
                    "and not exists(select id from "+tb_stk+" where label_pk_id="+str(pk)+" and vtype_id=4 and id>s.id)" 
            cur.execute(s)            
            rr=cur.fetchone()
            if rr:           
                if pkg==3:
                    if rr[1]==3:
                        e=_('此箱 '+rr[0]+" 已"+rr[2])
                    else:
                        e=_('此箱 '+rr[0]+" 已拆箱"+rr[2])                    
                else:
                    if rr[1]==3:
                        e=_('此标签所在箱 '+rr[0]+" 已"+rr[2])                        
                    else:
                        if rr[3]==label_code:
                            e=_('此标签 '+rr[0]+" 已"+rr[2])

            if e:
                data['e']=e
                return JsonResponse(data)
            else:
                # 只要不是扫码入库，就要检查前端传过来的产品名称是否正确                       
                if r0:
                    if str(r0[0])!=str(product_id):
                        e=_(r0[1]+" 入库产品名为 "+r0[2])
                else:
                    e=_('产品尚未入库')

        elif str(vtype_id)=='4':
            # 销售退库
            # 2025-03-18            
            if r0:
                if str(r0[0])!=str(product_id):
                    e=_(r0[1]+" 入库产品名为 "+r0[2])

            if str(enterprise_id)=='1':
                # 访问汉得接口
                d=label_status(label_code,is_test=False)
                
                #if d['e']:
                #    e=d['e']            
                #elif d['status']['decapCode']=='01' or d['status']['circulateCode']=='01' or d['status']['devanCode']=='01':
                #    e=_('营销平台: %s' % d['msg'])   


                try:
                    if d['status']['decapCode']=='01' or d['status']['circulateCode']=='01' or d['status']['devanCode']=='01':
                        e=_('营销平台: %s' % d['msg'])
                except Exception:
                    pass

                
        if e:
            data['e']=e
            cur.close()
            return JsonResponse(data)
        
        # 现场重复扫码，做redis检查
        # 2024-06-11 酒鬼酒入库，有先扫标后贴标，多余标又做标签退库情况。先不做入库的redis检查
        #if str(enterprise_id)=='1' and str(vtype_id)=='1':
        if False:

            #print('enterprise_id=1 and vtype_id=1')
            
            pass            
        else:
            e=redis_check(enterprise_id,pk,pkg,label_code,user_name,vtype_id,agent_id=None)       
            if e:
                data['e']=e
            

        cur.close()
    elif action=='flush':
        vtype_id=request.GET.get('vtype_id','')
        if vtype_id:
            data=redis_action(action,enterprise_id,vtype_id)
        else:
            data['e']=_('vtype id missing')
            data['cnt']=0
    elif action=='delete':        
        label_code=request.GET.get('label_code','')
        vtype_id=request.GET.get('vtype_id','')
        if label_code and vtype_id:
            d=redis_action(action,enterprise_id,vtype_id,label_code)
            data['cnt']=d['cnt']
        else:
            data['e']='label code and vtype id required'
    
    return JsonResponse(data)

# 2024-09-11
def mes_check(request,enterprise_id):
    data={'e':'','children':0,'bottlecaps':0}
    key=request.GET.get('key','')
    tm=request.GET.get('time','')
    k = sK   # 默认使用inventory.views sK
    e = time_key_check(request, k)
    if e:
        data['e'] = e
        return JsonResponse(data)
    c=request.GET.get('code','')
    p=request.GET.get('package_id','3')
    bc=request.GET.get('bottlecap_cnt','0')
    cc=request.GET.get('children_cnt','0')
    ee=[]
    if p=='3':        
        # 标签绑定检查
        if cc=='0':
            # 1箱多少个子标
            data['e']=_('每箱子标个数必传')
            return JsonResponse(data)
        cur=connection.cursor() 
        s="select sum(cnt) from ("+\
            "SELECT count(bottle_code) cnt FROM mes_labelbindpx where "\
                "company_id="+enterprise_id+" and cargon_code='"+c+"' and is_delete=false"+\
            " union all "+\
            "SELECT count(box_code)    cnt FROM mes_labelbindhx where "\
                "company_id="+enterprise_id+" and cargon_code='"+c+"' and is_delete=false"+\
            ") u"
        cur.execute(s)
        r=cur.fetchone()
        data['children']=r[0]
        if r[0]!=int(cc):
            ee.append('绑定数量不一致，'+str(r[0])+"/"+cc)
        # 瓶盖绑定检查
        if bc!="0":
            pass
    if ee:
        data['e']=",".join(ee)
    return JsonResponse(data)

