/// 
///LOGIC CLASS FOR TABLE t_WmsPlate
///By wm with codesmith. 
///on 04/06/2020
/// 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DeiNiu.wms.Data.Model;
using System.Data;
using System.Transactions;
using DeiNiu.Utils;
using System.Threading;
namespace DeiNiu.wms.Logical
{
    [Serializable]
    public class lWmsPlate : lbase
    {
        WmsPlate _obj;
        public lWmsPlate()
        {
            initialize();
        }
        public WmsPlate getWmsPlate
        {
            get
            {
                if (_obj == null)
                {
                    _obj = new WmsPlate();
                }
                _obj.operater = operId;
                return _obj;
            }
        }
        WmsPlateStock_tmp _plateStk;
        public WmsPlateStock_tmp plateStk
        {
            get
            {
                if (_plateStk == null)
                {
                    _plateStk = new WmsPlateStock_tmp();
                }
                _plateStk.operater = operId;
                return _plateStk;
            }
        }
        lWmsOutPickRequest _lop;
        public lWmsOutPickRequest lop
        {
            get
            {
                if (_lop == null || _lop.operId != operId)
                {
                    //   log.Debug(string.Format("_lop is null? {0},lop.operId {1}, operId {2}", _lop == null, lop.operId, operId));
                    _lop = new lWmsOutPickRequest(operId);
                }
                return _lop;
            }
        }
        public lWmsPlate(int operId)
            : base(operId)
        {
            initialize();
        }
        /// 
        /// get all data
        /// 
        public DataSet getAllData()
        {
            return _obj.Query();
        }
        /// 
        /// get all data
        /// 
        public DataSet getAllActiveData()
        {
            return _obj.QueryActived();
        }
        /// 
        /// get a record by id
        /// 
        public void initialize(int id)
        {
            _obj = id != 0 ? new WmsPlate(id) : new WmsPlate();
        }
        /// 
		/// get a record by id 0
		/// 
        public void initialize()
        {
            initialize(0);
        }
        /// 
        /// get a record by id
        /// 
        public void initialize(DataRow dr)
        {
            _obj = new WmsPlate(dr);
        }
        protected override DeiNiu.Data.BaseObject.BaseModel getModel()
        {
            return _obj;
        }
        //begin cust db operation, query, excute sql etc.
        internal int add(WmsPlate obj, int count)
        {
            for (int i = 0; i < count; i++)
            {
                obj.inPlate = "";
                obj.Add();
                obj.plateId = Util.getBoxId((enumPlateLevel)obj.type, obj.color, plateStk.getNextSeq("seqplate" + obj.type + obj.color));
                obj.Update();
            }
            return 1;
        }
        /// 
        /// put goods into a plate
        /// 
        public enumRegPlateResult inPlate(string plateId, enumPlateStatus type, string goodsId, string barcode, int skuId, decimal count, string orderNo)
        {
            /*if (valid(  plateId,  type,   goodsId,  skuId) == enumRegPlateResult.成功)
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    WmsPlate plate = new WmsPlate(plateId);
                    plate.type =(int)type;
                    WmsPlateStock_tmp pst = new WmsPlateStock_tmp(plateId,skuId);
                    if (pst.ID == 0)
                    {
                        pst.plateId = plateId;
                        pst.goodsId = goodsId;
                        pst.skuId = skuId;
                        pst.count = count;
                        pst.operater = operId;
                        pst.barcode = barcode;
                        pst.Add();
                    }
                    else
                    {
                        pst.count += count;
                        pst.operater = operId;
                        pst.Update();
                    }
                   
                    switch (type)
                    {
                      //  case enumPlateStatus.播种周转:
                      //      plate.customerId = orderNo;
                      //      break;
                        case enumPlateStatus.存储架上:
                            plate.locationId = orderNo;
                            break;
                        case enumPlateStatus.临时堆放: 
                            break; 
                        case enumPlateStatus.入库待上架:
                            plate.preInOrderNo = orderNo;
                            break;  
                        case enumPlateStatus.摘果周转:
                            plate.pickOrderNo = orderNo;
                            break;
                        case enumPlateStatus.运输周转:
                            plate.transNo = orderNo;
                            break;
                             
                    }
                    plate.operater = operId;
                    plate.Update(); 
                    scope.Complete();
                }
            }*/
            return enumRegPlateResult.成功;
        }
        private enumRegPlateResult valid(string plateId, enumPlateStatus type, string goodsId, int skuId)
        {
            if (enumPlateStatus.入库待上架 == type)
            {
                WmsPlateStock_tmp pst = new WmsPlateStock_tmp();
                DataTable dt = pst.getPlateStockDetail(plateId);
                if (dt.Rows.Count == 0)
                {
                    return enumRegPlateResult.成功;
                }
                foreach (DataRow dr in dt.Rows)
                {
                    if (dr["goodsId"].ToString() == goodsId)//存在goodsid
                    {
                        return enumRegPlateResult.成功;
                    }
                }
                WmsGoods wg = new WmsGoods(goodsId);
                foreach (DataRow dr in dt.Rows)
                {
                    if (Convert.ToInt32(dr["goodsType"].ToString()) == wg.goodsType)//存在goods type
                    {
                        return enumRegPlateResult.成功;
                    }
                }
                return enumRegPlateResult.容器已被不同库区或类型物品使用;
            }
            return enumRegPlateResult.成功;
        }
        /// 
        /// 下级容器可并入上级容器
        /// 客户笼车、线路码头 集货验证
        /// 
        /// 
        /// 
        /// 
        public enumRegPlateResult putPlateIntoPlate(string fromPlate, string toPlate)
        {
            //
            WmsPlate toP = new WmsPlate(toPlate);
            WmsPlate fromP = new WmsPlate(fromPlate);
            if (toP.type <= fromP.type)
            {
                return enumRegPlateResult.只允许下级容器放入上级容器;
            }
            else if (fromP.getParentPlate(fromPlate).ID > 0)
            {
                return enumRegPlateResult.容器已完成合流集货;
            }
            List requests = getWmsPlate.getPlateRequests(fromPlate, true);
            if (requests.Count == 0)
            {
                return enumRegPlateResult.容器空闲无任务;
            }
            WmsPlatePack wpp = new WmsPlatePack();
            //  wpp.getUpPlateId(fromPlate);
            wpp.plateId = toPlate;
            wpp.subPlateId = fromPlate;
            string custId = "";
            int lineId = 0;
            toP.volume += fromP.volume;
            toP.load += fromP.load;
            if (toP.type == (int)enumPlateLevel.客户集货)
            {
                WmsPlateStock_tmp ptmp = new WmsPlateStock_tmp();
                if (new WmsPlatePack(toPlate, fromPlate).ID > 0)
                {
                    return enumRegPlateResult.容器已完成客户集货;
                }
                custId = requests[0].customerId;
                List jflows = new List();
                foreach (WmsOutPickRequest wop in requests)
                {
                    jflows.Add(new WmsFlow(wop.pickOrderNo + fromPlate));
                }
                if (string.IsNullOrEmpty(toP.customerId) || toP.customerId == custId)
                {
                    DataTable dt = ptmp.getStockLst(fromPlate);
                    using (TransactionScope scope = new TransactionScope())
                    {
                        foreach (DataRow dr in dt.Rows)
                        {
                            ptmp = new WmsPlateStock_tmp(dr);
                            if (toP.partion == 0)
                            {
                                if (fromP.partion == 0)
                                {
                                    WmsGoods goods = new WmsGoods(ptmp.goodsId);
                                    fromP.partion = goods.part;
                                    fromP.Update();
                                }
                                toP.partion = fromP.partion;
                                toP.Update();
                            }
                            DataTable dt1 = ptmp.getOutPort(ptmp.outPortId);
                            foreach (DataRow dr1 in dt1.Rows)
                            {
                                custId = dr1["customerId"].ToString();
                                lineId = Convert.ToInt32(dr1["lineId"].ToString());
                                toP.volume += Convert.ToDecimal(dr1["volCm"].ToString());
                                toP.load += Convert.ToDecimal(dr1["weight"].ToString());
                                break;
                            }
                            /*
                            if(flow.orderNo.Equals(ptmp.orderNo) || flow.flowNo.Equals(fromPlate))
                            {
                                flow = new WmsFlow(ptmp.orderNo + ptmp.plateId);
                            }
                            */
                            foreach (WmsFlow flow in jflows)
                            {
                                flow.finishedTasksPlus(operId, 1);
                            }
                            ptmp.inPlate = toPlate;
                            ptmp.Update();
                        }
                        //客户容器不进行线路集货, 直接装车,则生成装车任务
                        if (!WmsConstants.IS_PLATE_IN_LINE && string.IsNullOrEmpty(toP.customerId))
                        {
                            string ldTask = toP.jobNo;
                            if (string.IsNullOrEmpty(ldTask)) //
                            {
                                foreach (WmsOutPickRequest req in requests)
                                {
                                    if (string.IsNullOrEmpty(req.loadTruckJob))
                                    {
                                        ldTask = requests[0].createLoadTruckJob(operId);
                                    }
                                    else
                                    {
                                        ldTask = req.loadTruckJob; //每个订单一个装车任务,在开始分拣时生成
                                    }
                                    break;
                                }
                            }
                            WmsFlow wmsflow = new WmsFlow(ldTask);
                            wmsflow.taskCnt++;// 每个订单的装车任务的 客户集货容器数量
                            wmsflow.Update();
                            toP.jobNo = wmsflow.task;
                        }
                        toP.customerId = custId;
                        toP.lineId = lineId;
                        wpp.removeUp();
                        wpp.operater = operId;
                        wpp.Add();
                        fromP.inPlate = toP.plateId;
                        fromP.Update();
                        toP.Update();
                        foreach (WmsOutPickRequest req in requests)
                        {
                            if (string.IsNullOrEmpty(req.loadTruckJob) && string.IsNullOrEmpty(toP.jobNo))
                            {
                                req.loadTruckJob = toP.jobNo;
                                req.Update();
                            }
                            if (req.state == (int)enumOutStockRequestStatus.分拣完成)
                            {
                                foreach (WmsFlow flow in jflows)
                                {
                                    if (flow.orderNo == req.pickOrderNo)
                                    {
                                        if (flow.getUnFinishedByOrderNo(req.pickOrderNo, EnumFlowTaskType.客户集货).Rows.Count == 0)
                                        {
                                            req.state = (int)enumOutStockRequestStatus.集货完成;
                                            req.Update();
                                        }
                                    }
                                }
                            }
                        }
                        scope.Complete();
                    }
                    return enumRegPlateResult.成功;
                }
                else if (toP.customerId != custId)
                {
                    return enumRegPlateResult.客户容器已被其他客户占用;
                }
            }
            else
            if (toP.type == (int)enumPlateLevel.线路集货)
            {
                //   log.Debug(string.Format("线路集货  from plate {0}, to plate {1}, to plate line id {2},from plate line id {3}",fromPlate,toPlate,toP.lineId,lineId));
                if (!String.IsNullOrEmpty(fromP.inPlate))
                {
                    // return enumRegPlateResult.容器已完成码头集货;
                }
                if (fromP.type != (int)enumPlateLevel.客户集货)
                {
                    // return enumRegPlateResult.码头集货需要客户类型的容器;
                }
                if (!String.IsNullOrEmpty(toP.inPlate))
                {
                    return enumRegPlateResult.码头已装车集货;
                }
                if (WmsConstants.JIHUO_CHECK_PRE_STATE)
                {
                    if (fromP.type == (int)enumPlateLevel.客户集货)
                    {
                        WmsFlow flow = new WmsFlow();
                        foreach (WmsOutPickRequest req in requests)
                        {
                            /* if (req.state != (int)enumOutStockRequestStatus.集货完成 && req.state == (int)enumOutStockRequestStatus.分拣完成)
                             {
                                 if (flow.getUnFinishedByOrderNo(req.pickOrderNo, EnumFlowTaskType.客户集货 ).Rows.Count == 0)
                                 {
                                     req.state = (int)enumOutStockRequestStatus.集货完成;
                                     req.Update();
                                 }
                             }
                             if (req.state != (int)enumOutStockRequestStatus.集货完成)
                             {
                                 return enumRegPlateResult.前置集货未完成;
                             }*/
                            if (flow.getUnFinishedByOrderNo(req.pickOrderNo, EnumFlowTaskType.客户集货).Rows.Count > 0)
                            {
                                return enumRegPlateResult.前置集货未完成;
                            }
                        }
                    }
                }
                //  检测客户是否已经在其它码头集货
                DataTable dt2 = getWmsPlate.getLineId(fromP.customerId);
                foreach (DataRow dr in dt2.Rows)
                {
                    WmsPlate wp = new WmsPlate(dr);
                    if (!String.IsNullOrEmpty(wp.inPlate) && wp.inPlate != toP.plateId)
                    {
                        return enumRegPlateResult.客户已经在其他码头集货;
                    }
                }
                if (toP.lineId == 0)
                {
                    toP.lineId = fromP.lineId;
                }
                else if (WmsConstants.IS_PLATE_IN_LINE && toP.lineId != (fromP.lineId) && fromP.lineId > 0)
                {
                    return enumRegPlateResult.集货线路不同;
                }
                fromP.inPlate = toP.plateId;
                WmsPlateStock_tmp ptmp = new WmsPlateStock_tmp();
                DataTable dt = ptmp.getStockLst(fromPlate);
                using (TransactionScope scope = new TransactionScope())
                {
                    foreach (DataRow dr in dt.Rows)
                    {
                        ptmp = new WmsPlateStock_tmp(dr);
                        ptmp.inPlate = toPlate;
                        ptmp.Update();
                    }
                    toP.volume += fromP.volume;
                    toP.load += fromP.load;
                    wpp.removeUp();
                    wpp.operater = operId;
                    wpp.Add();
                    toP.Update();
                    WmsFlow wmsflow = new WmsFlow();
                    wmsflow.operater = operId;
                    wmsflow.orderNo = toP.plateId;
                    wmsflow.flowNo = fromP.plateId;
                    wmsflow.type = (int)EnumFlowTaskType.装车运输;
                    wmsflow.typeName = EnumFlowTaskType.装车运输.ToString();
                    wmsflow.task = Util.getOrderNo(enumCreateOrderType.pickJobNo, _obj.getNextSeq(enumCreateOrderType.pickJobNo));
                    wmsflow.taskCnt = fromP.getSubPlateIds(fromP.plateId).Count;
                    wmsflow.Add();
                    foreach (WmsOutPickRequest req in requests)
                    {
                        req.loadTruckJob = wmsflow.task;
                        req.Update();
                    }
                    fromP.jobNo = wmsflow.task;
                    fromP.Update();
                    scope.Complete();
                }
            }
            else if (toP.type == (int)enumPlateLevel.运输车)
            {
                //容器临时库存转移到车辆,结束拣货单据,更新拣货状态,通知erp
                //update the pickrequest directly to validation status.
                if (fromP.type != (int)enumPlateLevel.线路集货)
                {
                    //  return enumRegPlateResult.装车集货需要码头类型的容器;
                }
                if (!String.IsNullOrEmpty(fromP.inPlate))
                {
                    // return enumRegPlateResult.容器已完成装车集货;
                }
                fromP.inPlate = toP.plateId;
                List custPlates = fromP.getSubPlates(fromP.plateId);
                log.Debug(string.Format(" 装车 {0} ,码头拣货单数量 {1}", fromPlate, requests.Count));
                using (TransactionScope scope = new TransactionScope())
                {
                    toP.volume += fromP.volume;
                    toP.load += fromP.load;
                    if (string.IsNullOrEmpty(toP.transNo))
                    {
                        toP.transNo = Util.getOrderNo(enumCreateOrderType.transOrder, _obj.getNextSeq(enumCreateOrderType.transOrder));
                        toP.Update();
                        logPlate.Debug(string.Format("1 plate {0} start new trans {1}", toPlate, toP.transNo));
                        new lTmsTranRequest(operId).createSimpleTran(requests, toP);// req.transNo = toP.transNo;
                    }
                    //  toP.Update();
                    wpp.removeUp();
                    wpp.operater = operId;
                    wpp.Add();
                    fromP.Update();
                    log.Debug(string.Format(" 集货,自动复核 {0} ,客户拣货单数量 {1}", fromPlate, requests.Count));
                    foreach (WmsOutPickRequest req in requests)
                    {
                        // log.Debug(string.Format(" 集货,开始复核客户拣货单  {0}", req.pickOrderNo));
                        //TODO: check 订单没有集货的容器,没有完成拣货的订单
                        /*
                        if (req.state >= (int)enumOutStockRequestStatus.分拣完成
                            //|| req.state == (int)enumOutStockRequestStatus.复核异常)
                            )
                        { 
                            // check all flowno  
                            WmsPlateStock_tmp wst = new WmsPlateStock_tmp();
                            DataTable dt = wst.getByOrder(req.pickOrderNo); 
                        
                            DataView dv = dt.DefaultView;
                            dv.RowFilter = "isnull(inPlate,'') = ''";
                            if (dv.Count == 0)
                            {
                                req.state = (int)enumOutStockRequestStatus.集货完成;
                            }
                                
                        }
                        */
                    }
                    foreach (WmsPlate plate in custPlates)
                    {
                        plate.transNo = toPlate;
                        plate.Update();
                    }
                    scope.Complete();
                }
            }
            //  log.Debug(string.Format("to plate custid  {0}, to plate lineid {1} ", toP.customerId,  toP.lineId ));
            return enumRegPlateResult.成功;
        }
        /// 
        /// 按客户装车
        /// 
        /// 客户集货的容器号码
        /// 
        public enumRegPlateResult loadTruck(string fromPlate, string toPlate)
        {
            logPlate.Debug("start load truck, fromPlate " + fromPlate + ", toPlate " + toPlate);
            WmsPlate fromP = new WmsPlate(fromPlate);
            if (fromP.getParentPlate(fromPlate).ID > 0)
            {
                return enumRegPlateResult.容器已完成合流集货;
            }
            /*
            if (fromP.type != (int)enumPlateLevel.客户集货)
            {
                return enumRegPlateResult.装车需要客户类型的容器;
            }
                if (String.IsNullOrEmpty(fromP.inPlate))
                {
                    return enumRegPlateResult.完成码头集货后才能装车;
                }
                if (String.IsNullOrEmpty(fromP.transNo))
                {
                    return enumRegPlateResult.完成装车集货后才能装车;
                }
                if (!fromP.transNo.Trim().ToUpper() .Equals(toPlate.Trim().ToUpper()))
                {
                    return enumRegPlateResult.客户货物不属于此车;
                }
              */
            List requests = getWmsPlate.getPlateRequests(fromPlate, true);
            if (requests.Count == 0)
            {
                return enumRegPlateResult.容器空闲无任务;
            }
            if (string.IsNullOrEmpty(requests[0].customerId))
            {
                return enumRegPlateResult.容器所属客户不明确;
            }
            WmsPlateStock_tmp ptmp = new WmsPlateStock_tmp();
            WmsFlow jflow = new WmsFlow();
            //  List jflows = new List();
            WmsPlate toP = new WmsPlate(toPlate);
            int lineId = fromP.lineId;
            if (fromP.ID == 0 || fromP.volume == 0) //临时容器
            {
                DataTable dt2 = ptmp.getStockLst(fromPlate);
                foreach (DataRow dr in dt2.Rows)
                {
                    ptmp = new WmsPlateStock_tmp(dr);
                    if (jflow.ID == 0)
                    {
                        jflow = new WmsFlow(ptmp.jobNo); //? 拣货任务??
                    }
                    DataTable dt1 = ptmp.getOutPort(ptmp.outPortId);
                    foreach (DataRow dr1 in dt1.Rows)
                    {
                        lineId = Convert.ToInt32(dr1["lineId"].ToString());
                        fromP.volume += Convert.ToDecimal(dr1["volCm"].ToString());
                        fromP.load += Convert.ToDecimal(dr1["weight"].ToString());
                        break;
                    }
                    /*
                    if(string.IsNullOrEmpty(ptmp.inPlate))
                    {
                        ptmp.inPlate = toPlate;
                        ptmp.Update();
                    }*/
                }
            }
            toP.load += fromP.load;
            toP.volume += fromP.volume;
            if (toP.ID == 0) //非注册车辆,可能为第三方运单等
            {
                toP.plateId = toPlate;
                toP.type = (int)enumPlateLevel.临时容器;
                toP.plateLevel = toP.type;
                toP.lineId = lineId;
            }
            if (WmsConstants.IS_PLATE_IN_LINE && lineId > 0 && lineId != toP.lineId)
            {
                return enumRegPlateResult.集货线路不同;
            }
            WmsPlatePack wpp = new WmsPlatePack();
            wpp.plateId = toPlate;
            wpp.subPlateId = fromPlate;
            DataTable dt = getPateJobsDt(fromPlate);
            DataView dv = dt.DefaultView;
            dv.RowFilter = String.Format("orderNo='{0}'", requests[0].pickOrderNo);
            using (TransactionScope scope = new TransactionScope())
            {
                if (jflow.ID > 0)
                {
                    jflow.finishedTasksPlus(operId, 1, false, true);
                }
                wpp.removeUp();
                int id = wpp.Add();
                log.Debug("load truck add plate pack id " + id);
                //支持跳过线路集货,直接装车
                if (string.IsNullOrEmpty(toP.transNo))
                {
                    toP.transNo = Util.getOrderNo(enumCreateOrderType.transOrder, _obj.getNextSeq(enumCreateOrderType.transOrder));
                    logPlate.Debug(string.Format("2 plate {0} start new trans {1}, top.ID {2}", toPlate, toP.transNo, toP.ID));
                    new lTmsTranRequest(operId).createSimpleTran(requests, toP);// req.transNo = toP.transNo;
                    //  return enumRegPlateResult.完成装车集货后才能装车;
                }
                else
                {
                    foreach (WmsOutPickRequest op in requests)
                    {
                        if (string.IsNullOrEmpty(op.transNo))
                        {
                            op.operater = operId;
                            op.transNo = toP.transNo;
                            op.Update();
                            TmsTranRequestDetail td = new TmsTranRequestDetail();
                            td.pickOrderNo = op.pickOrderNo;
                            td.transNo = toP.transNo;
                            td.operater = operId;
                            td.Add();
                        }
                    }
                }
                foreach (DataRowView drv in dv)
                {
                    WmsPlateStock_tmp wst = new WmsPlateStock_tmp(drv.Row);
                    wst.transNo = toP.transNo;
                    wst.inPlate = toPlate;
                    wst.Update();
                }
                TmsTranRequest tmsTranRequest = new TmsTranRequest(toP.transNo);
                tmsTranRequest.sumVol += toP.volume;
                tmsTranRequest.sumWeight += toP.load;
                tmsTranRequest.Update();
                if (toP.ID == 0)
                {
                    toP.Add();
                }
                else
                {
                    toP.Update();
                }
                logPlate.Debug(string.Format("3  plate {0} start new trans {1}, top.ID {2}", toPlate, toP.transNo, toP.ID));
                foreach (WmsOutPickRequest req in requests)
                {
                    if (req.state == (int)enumOutStockRequestStatus.集货完成)
                    {
                        req.state = (int)enumOutStockRequestStatus.已装车;
                        req.Update();
                    }
                }
                 //非自动装车时,释放已装车容器,自动装车时不能释放,会导致客户集货位释放从而失去客户和容器的对应关系限制
                if (WmsConstants.IS_PLATE_IN_LINE && !WmsConstants.AUTO_LOAD_TRUCK)
                {
                    if (fromP.ID > 0)
                    {
                        //to release plates of customer type
                        List lst = getWmsPlate.getSubPlates(fromPlate);
                        foreach (WmsPlate s in lst)
                        {
                            s.releaseSubPlate(s.plateId);  //to release customer and its subs
                                                           // log.Debug(string.Format("on truck load, released plate {0}, type{1}", s.plateId, (enumPlateLevel)s.type));
                        }
                        getWmsPlate.releaseSubPlate(fromPlate);  //to release custType type and its subs
                        log.Debug(string.Format("on truck load, released plate {0} ", fromPlate));
                    }
                    //to release plate of Line
                    // 线路码头容器里面的客户容器是否已经全部装车了,如果都已装车(释放),则释放线路容器
                    if (fromP.plateLevel == (int)enumPlateLevel.客户集货)
                    {
                        WmsPlate linePlate = new WmsPlate(fromP.inPlate);
                        if (linePlate.lineId > 0)
                        {
                            int cnt = getWmsPlate.getSubPlates(linePlate.plateId).Count;
                            logOut.Debug(string.Format(" line plate {0} sub plates cnt {1}", linePlate.plateId, cnt));
                            if (cnt == 0)
                            {
                                linePlate.releaseSubPlate(linePlate.plateId);
                            }
                        }
                    }
                }
                string ldTask = fromP.jobNo;
                // if (string.IsNullOrEmpty(ldTask))  // 非固定容器、非客户集货类型的容器,容器没有装车任务信息
                {
                    foreach (WmsOutPickRequest req in requests) //容器里可能有多个分拣单,多个装车任务
                    {
                        ldTask = req.loadTruckJob;
                        WmsFlow flow = new WmsFlow(ldTask); // ref: fromP.pickOrderNo = wmsflow.task;
                        flow.finishedTasksPlus(operId, 1, true);
                        logPlate.Debug("updated loadtruck task " + ldTask);
                    }
                }
                //客户容器的装车任务
                scope.Complete();
            }
            return enumRegPlateResult.成功;
        }
        internal enumRegPlateResult startTran(string plateId)
        {
            WmsPlate plate = new WmsPlate(plateId);
            if (plate.ID > 0 && plate.type != (int)enumPlateLevel.运输车)
            {
                //  return enumRegPlateResult.发车需要运输类型的容器;
            }
            if (string.IsNullOrEmpty(plate.transNo))
            {
                return enumRegPlateResult.容器空闲无任务;
            }
            TmsTranRequest tmsTranRequest = new TmsTranRequest(plate.transNo);
            if (tmsTranRequest.state == (int)enumTranStatus.配送途中)
            {
                return enumRegPlateResult.已发车;
            }
           
            if (WmsConstants.IS_PLATE_IN_LINE)
            {
                List lst = getWmsPlate.getSubPlates(plateId);
                foreach (WmsPlate s in lst)//to release line and its subs
                {
                    s.releaseSubPlate(s.plateId);
                    // log.Debug(string.Format("on start tran load, released plate {0}, type{1}", s.plateId, (enumPlateLevel)s.type));
                }
            }
            plate.partion = 0;
            //TODO: 按车发货,订单满足关单条件(全部发出) 再关单
            Thread threadPreProcess = new Thread(new ParameterizedThreadStart(porcessStock4TransStart));
            threadPreProcess.IsBackground = true;
            threadPreProcess.Start(plate);
            return enumRegPlateResult.成功;
        }
        void porcessStock4TransStart(object plate)
        {
            try
            {
                WmsPlate tranP = (WmsPlate)plate;
                List requests = new lWmsOutPickRequest(operId).getRequestsByTransNo(tranP.transNo);
                logPlate.Debug("装车后续处理。。。。开始, plateId " + tranP.plateId);
                WmsPlateStock_tmp wpt = new WmsPlateStock_tmp();
               // new lWmsInRequest(operId).retryNoticeErpValidIn(true);
                using (TransactionScope scope = new TransactionScope())
                {
                    foreach (WmsOutPickRequest req in requests)
                    {
                        //  req.state = (int)enumOutStockRequestStatus.已出库;
                        //  req.Update();
                        logPlate.Debug(" 开始处理 " + req.pickOrderNo);
                        req.finishAllFlowTasks(req.pickOrderNo);//完成所有未完成的任务
                        logPlate.Debug(" force finished all tasks of " + req.pickOrderNo);
                        DataTable dt = wpt.getByOrder(req.pickOrderNo);
                        foreach (DataRow dr in dt.Rows)
                        {
                            wpt = new WmsPlateStock_tmp(dr);
                            WmsStock stk = new WmsStock(wpt.locationid, wpt.skuId, wpt.goodsId);
                            if (stk.ID > 0)
                            {
                                stk.plateCount -= wpt.count;
                                stk.updateCountOut();
                            }
                        }
                        //to finish all pick tasks 
                        WmsOutPickPort wop = new WmsOutPickPort();
                        DataTable dt2 = wop.getPickDetails(req.pickOrderNo, (int)enumPickState.未拣);
                        foreach (DataRow dr in dt2.Rows)
                        {
                            wop = new WmsOutPickPort(dr);
                            WmsStock st = new WmsStock(wop.locationId, Convert.ToInt32(dr["skuId"].ToString()), dr["goodsId"].ToString());
                            log.Debug(string.Format(" get 未拣货记录 {0}", wop.ToString()));
                            if (wop.virtialCnt > 0) //还回未出库虚拟库存
                            {
                                st.virtialCount -= wop.virtialCnt;
                                st.virtialCount = st.virtialCount > 0 ? st.virtialCount : 0;
                                WmsStock virSt = st.getVirStock(st.goodsId);
                                log.Debug(string.Format(" 借入的虚拟库存: {0}", virSt.ToString()));
                                virSt.countOuting -= wop.virtialCnt;
                               // virSt.updateCountOut();
                                virSt.Update();
                            }
                            log.Debug(string.Format(" 实际库存: {0}", st.ToString()));
                            st.countOuting -= wop.count;
                            st.countOuting = st.countOuting > 0 ? st.countOuting : 0; ;
                        
                            st.updateCountOut();
                        }
                        wop.closePickPorts(req.pickOrderNo);
                        logPlate.Debug(" 关闭所有的拣货任务, 释放锁定库存 " + req.pickOrderNo);
                        //to realse plate tmp stock.
                        int cnt = wpt.releasePlateByOrder(req.pickOrderNo);
                        logPlate.Debug(req.pickOrderNo + " released tmp stock item cnt " + cnt);
                        lop.finishRequest(req); //更新订单状态,通知ERP
                    }
                    getWmsPlate.releaseSubPlate(tranP.plateId);  //to release truck type and its subs 
                    logPlate.Debug(" 释放此次运输相关临时容器 " + tranP.plateId);
                    log.Debug("装车后续处理。。。。结束");
                    TmsTranRequest tmsTranRequest = new TmsTranRequest(tranP.transNo);
                    tmsTranRequest.state = (int)enumTranStatus.配送途中;
                    tmsTranRequest.Update();
                    if (tranP.plateLevel == (int)enumPlateLevel.临时容器)
                    {
                        tranP.Delete();
                    }
                    scope.Complete();
                }
            }
            catch (Exception er)
            {
                logPlate.Error(er);
            }
        }
        public enumRegPlateResult mergePlate(string fromPlate, string toPlate)
        {
            // stock out port plate merge
            List requests = getWmsPlate.getPlateRequests(fromPlate, true);
            WmsPlate fromP = new WmsPlate(fromPlate);
            WmsPlate toP = new WmsPlate(toPlate);
            if (fromP.plateLevel != toP.plateLevel)
            {
                return enumRegPlateResult.等级别的容器才可以合并;
            }
            if (fromP.getParentPlate(fromPlate).ID > 0
                  && fromP.getParentPlate(fromPlate).ID != toP.getParentPlate(toPlate).ID)
            {
                return enumRegPlateResult.相同上级容器的子容器才可以相互合并;
            }
            using (TransactionScope scope = new TransactionScope())
            {
                foreach (WmsOutPickRequest wop in requests)
                {
                    plateStk.merge(fromPlate, toPlate, wop.pickOrderNo);
                }
                scope.Complete();
            }
            return 0;
        }
        public void releasePlateStock(string plateId, decimal count, int inPortId = 0, int outPortId = 0)
        {
            logPlate.Debug(string.Format("plateId {0},count {1},inPortId {2},outPortId {3}", plateId, count, inPortId, outPortId));
            WmsPlateStock_tmp plateStock = new WmsPlateStock_tmp();
            if (count == 0 && inPortId == 0 && outPortId == 0)
            {
                int cnt = plateStock.releasePlate(plateId);
                logPlate.Debug(string.Format("release plate {0} ", plateId));
                return;
            }
            DataTable dt;
            if (inPortId > 0)
            {
                dt = plateStock.getPlateIn(plateId, inPortId);
            }
            else
                dt = plateStock.getPlateOut(plateId, outPortId);
            logPlate.Debug(string.Format(" stk items count {0} ", dt.Rows.Count));
            foreach (DataRow dr in dt.Rows)
            {
                WmsPlateStock_tmp tmp = new WmsPlateStock_tmp(dr);
                tmp.count -= count;
                if (tmp.count <= 0)
                {
                    tmp.Delete();
                    logPlate.Debug(string.Format("release stk {0} ", tmp.ID));
                }
                else
                {
                    tmp.Update();
                }
            }
        }
        public DataTable getPateJobsDt(string plateId, bool showSub = false)
        {
            DataTable dt = getWmsPlate.getPateJobsDt(plateId, showSub);
            logTest.Debug(string.Format("plate {0} ,showSub {1}, all contents size {2}", plateId, showSub, dt.Rows.Count));
            return dt;
        }
        internal DataTable queryRegistedPlate(string flowNo)
        {
            return getWmsPlate.queryRegistedPlate(flowNo);
        }
        internal DataTable getFromPlate(string flowNo)
        {
            return getWmsPlate.queryFromPlate(flowNo);
        }
        internal enumRegPlateResult takeOutPlate(string fromPlate, string plate)
        {
            WmsPlatePack wpp = new WmsPlatePack(fromPlate, plate);
            log.Debug(string.Format("fromPlate {0}, plate {1}", fromPlate, plate));
            if (wpp.ID == 0)
            {
                return enumRegPlateResult.容器非直接包含关系;
            }
            using (TransactionScope scope = new TransactionScope())
            {
                wpp.Delete();
                if (wpp.getSubPlates(fromPlate).Rows.Count == 0)
                {
                    WmsPlate wmsPlate = new WmsPlate(fromPlate);
                    wmsPlate.customerId = "";
                    wmsPlate.lineId = 0;
                    wmsPlate.Update();
                }
                scope.Complete();
            }
            return enumRegPlateResult.成功;
        }
        /// 
        /// 容器复核  
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 是否只纠正账目,品相正确只是数量差异,则按实际拿的发
        /// 
        internal enumOutValidResult plateValidation(string plateId, int portId, int skuId, string productDate, string validDate, string batch, decimal validationCnt, string validReason, bool finialValidation = true)
        {
            log.Debug(string.Format("容器复核。。。。plateId {8},   portId {0},  skuId {1},  productDate {2},  validDate {3},  batch {4},   validationCnt {5},   validReason {6},  finialValidation {7}",
                portId, skuId, productDate, validDate, batch, validationCnt, validReason, finialValidation,plateId));
            WmsPlateStock_tmp wst = new WmsPlateStock_tmp().getModelByOutPort(plateId, portId);
            WmsOutPickPort wpp = new WmsOutPickPort(portId);
            WmsOutPickDetail wpd = new WmsOutPickDetail(wpp.pickDetailId);
            //  WmsOrderRequest wor = new WmsOrderRequest();
            wpp.validationCnt = validationCnt;
            wpp.checkBy = operId;
            wpp.checkTime = wpp.getDateTime();
            wpp.validationReason = validReason;
            decimal diffCnt = wst.count - validationCnt;
            if (!finialValidation) //
            {
                wpp.description += "; 实物多退少补";
                diffCnt = 0;
            }
            log.Debug(string.Format("容器复核  原数量 {0}, 差异 {1} ", wst.count, diffCnt));
            WmsStock stk = null;
            WmsStockRecord wsr = null;
            if (diffCnt != 0)
            {
                wst.count = validationCnt;
                wsr = new WmsStockRecord(wpp.recordId);
                stk = new WmsStock(wpp.locationId, skuId);
                //  stk.adjustingCnt += diffCnt;
                if(skuId>0) //非借入出库
                {
                    stk.count += diffCnt ;
                }
               
            
               
                log.Debug(string.Format("容器复核  volType  {0}, 差异 {1}, pickdetail id {2} ,pick bulk cnt {3}, seeded cnt {4} pick batch cnt {5} ", wst.count, diffCnt, wpd.ID, wpd.bulkPicked, wpd.seeded, wpd.batchPicked));
                //少拿不补
                //多拿不退 
                if (wpp.volType == 0)
                {
                    wpd.bulkPicked -= diffCnt;
                }
                else
                {
                    wpd.batchPicked -= diffCnt;
                }
            }
            using (TransactionScope scope = new TransactionScope())
            {
                wpp.Update();
                if (diffCnt != 0)
                {
                   
                    string description = string.Format("\n 业务类型:{0} {5},拣货任务{1},计划数量 {2}, 实际数量{3}, 备注:{4}", "容器复核",
                        wpp.ID, wpp.count, validationCnt, validReason, finialValidation ? " 按拣货数量发货" : " 实物多退少补,按需求发");
                    log.Debug(description);
                    int i = wpd.Update();
                    log.Debug(" pick detail count updated rows " + i);
                    wst.Update();
                    if (skuId>0  && stk.Update() == 0)
                    {
                        stk.locationId = new WmsLocation().getLocation(enumWhLocVol.零库, wpd.goods.part, wpd.goods.ABC).locationId;
                        stk.goodsId = wsr.goodsId;
                        stk.skuId = skuId;
                        stk.batch = batch;
                        stk.productDate = productDate;
                        stk.validDate = validDate;
                        stk.Add();
                    }
                    if (string.IsNullOrEmpty(stk.locationId))
                    {
                    }
                    wsr.description = description;
                    wsr.Update(); //更新记录
                    wsr.count = validationCnt;
                    wsr.count1 = diffCnt;
                    wsr.locationId = wpp.locationId;
                    wsr.operater = operId;
                    wsr.rectype = (int)enumStockRecordType.容器复核;
                    wsr.Add();  //新增记录
                }
                scope.Complete();
            }
            //new lWmsOutPickRequest(operId).validationPickrequests();//对于复核完毕的订单进行回传erp操作
            return enumOutValidResult.成功;
        }
        internal string getLatestPlate(string custId, string goodsId)
        {
            return getWmsPlate.getLatestPlate(custId, goodsId).plateId;
        }
        public DataTable getUnLoadTruckStks(string toPlate, int cnt)
        {
            log.Debug(string.Format("...... to getUnLoadTruckStks plateId {0}",toPlate));
            WmsPlate toP = new WmsPlate(toPlate);
            return plateStk.getUnLoadTruckStks(toP.transNo,cnt);
        }
        public DataTable getLoadContent(string toPlate)
        {
            return plateStk.getLoadContent(toPlate);
        }
        internal string getGoodsById(string goodsId)
        {
         //   WmsGoods wg = new WmsGoods(goodsId);
         //
           // logIn.Debug(string.Format("wg name {0}, wg bigcount {1}, wg iszhitong {2}", wg.goodsName, wg.bigCount, wg.isZhitong));
          //  logIn.Debug(wg);
            WmsGoods goods = new WmsGoods(goodsId, 0, "");
            return goods.stockAvCount + "";
        }
    }
}