/// 
///LOGIC CLASS FOR TABLE t_wmsOutRequest
///By wm with codesmith. 
///on 05/18/2017
/// 
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;
using System.ServiceModel;
namespace DeiNiu.wms.Logical
{
    [Serializable]
    public class lWmsOutRequest : lbase
    {
        WmsOutRequest _obj;
        WmsOutPickRequest _pickRequestObj;
        WmsOutPick _wop;
        WmsOutDetail _wod;
        Erp_sale _esale;
        public lWmsOutRequest(int operId) : base(operId)
        {
            initialize();
        }
        public lWmsOutRequest()
        {
            initialize();
        }
        public Erp_sale esale
        {
            get
            {
                if (_esale == null)
                {
                    _esale = new Erp_sale();
                    _esale.operater = operId;
                }
                return _esale;
            }
        }
        public WmsOutPickRequest pickRequestObj
        {
            get
            {
                if (_pickRequestObj == null)
                {
                    _pickRequestObj = new WmsOutPickRequest();
                    _pickRequestObj.operater = operId;
                }
                return _pickRequestObj;
            }
        }
        public WmsOutRequest outRequest
        {
            get
            {
                if (_obj == null)
                {
                    _obj = new WmsOutRequest();
                    _obj.operater = operId;
                }
                return _obj;
            }
        }
        public WmsOutDetail outDetail
        {
            get
            {
                if (_wod == null)
                {
                    _wod = new WmsOutDetail();
                    _wod.operater = operId;
                }
                return _wod;
            }
        }
        public WmsOutPick wop
        {
            get
            {
                if (_wop == null)
                {
                    _wop = new WmsOutPick();
                    _wop.operater = operId;
                }
                return _wop;
            }
        }
        /// 
        /// get all data
        /// 
        public DataSet getAllData()
        {
            return outRequest.Query();
        }
        /// 
        /// get all data
        /// 
        public DataSet getAllActiveData()
        {
            return outRequest.QueryActived();
        }
        /// 
        /// get a record by id
        /// 
        public void initialize(int id)
        {
            _obj = id != 0 ? new WmsOutRequest(id) : new WmsOutRequest();
        }
        /// 
		/// get a record by id 0
		/// 
        public void initialize()
        {
            initialize(0);
        }
        /// 
        /// get a record by id
        /// 
        public void initialize(DataRow dr)
        {
            _obj = new WmsOutRequest(dr);
        }
        protected override DeiNiu.Data.BaseObject.BaseModel getModel()
        {
            return outRequest;
        }
        internal DataSet getPickOutDetail(string queryStr, int rowStart, int rowEnd)
        {
            return esale.getPickOutDetail(queryStr, rowStart, rowEnd);
        }
       
         
        internal DataSet getPickOutDetailSum(string queryStr, int rowStart, int rowEnd)
        {
            return esale.getPickOutDetailSum(queryStr, rowStart, rowEnd);
        }
        static bool isSyncing = false;
        /// 
        /// get in_stock requests in a transaction scope
        /// 
        internal void syncOrders()
        {
            logSpec.Debug(" start sync request....." + isSyncing);
            if (isSyncing)
            {
                return;
            }
            isSyncing = true;
            // DataTable dt = null ;
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    // dt = getWmsOutRequest.getNewOrders().Tables[0];
                    enumOutStockRequestStatus wmsStatus = enumOutStockRequestStatus.待审核;
                    if (WmsConstants.AUTO_APPROVE_SALE_ORDER)
                    {
                        wmsStatus = enumOutStockRequestStatus.准备分拣;
                    }
                    // esale.prepareSaleInTmpData(); //erp_wms 记录 临时数据 
                    //to get available out orders for wms 
                    outRequest.prepareSaleInTmpData(); // wms 记录 临时数据 
                    //  DataTable dt = outRequest.getNewOrders();
                    //   fixErpSaleDetailSkuId();
                    outRequest.syncOutRequest();
                    DataTable dtLastSync = outRequest.getLastSyncOrders(); //取本次同步的订单数据
                    WmsOutRequest wor;
                    Erp_sale es = new Erp_sale();
                    foreach (DataRow dr in dtLastSync.Rows)
                    {
                        wor = new WmsOutRequest(dr);
                        es = new Erp_sale(wor.orderNo);
                        es.updateWhType(wor.orderNo, (int)getWhType((int)getOutStoreType(wor.orderType)), wmsStatus); //更新接口数据wms_state 
                    }
                    if (dtLastSync.Rows.Count > 0) //记录接口数据同步时间戳 
                    {
                        WmsSyncLog log = new WmsSyncLog();
                        log.lastOrderNo = dtLastSync.Rows[0]["orderNo"].ToString();
                        log.lastSyncTime = dtLastSync.Rows[0]["timeFromErp"].ToString();
                        log.lastSyncTime = Convert.ToDateTime(dtLastSync.Rows[0]["timeFromErp"]).ToString("yyyy-MM-dd HH:mm:ss.fff"); ;
                        //  LogHelper.debug(this.GetType(), "last sync time is 1 " + dtLastSync.Rows[0]["timeFromErp"].ToString());
                        //  LogHelper.debug(this.GetType(), "last sync time is 2 " + log.lastSyncTime);
                        log.type = 1;
                        log.AddLog();
                    }
                    //根据wms 客户订单分拣类别属性,进行分拣通道分类
                    outRequest.autoPickPrepare();
                    //自动核准普通客户订单,常规集单出货的客户(连锁分店)订单(非紧急单)单独控制
                    if (WmsConstants.AUTO_APPROVE_SALE_ORDER)
                    {
                        outRequest.autoApproveOutRequest(wmsStatus);
                        //  outRequest.deleteBadData(); //TODO: check and find out how bad data in
                    }
                    //  esale.syncSaleOrdersAfter(wmsStatus);
                    scope.Complete();
                    //     return dt;
                }
                catch (Exception e)
                {
                    isSyncing = false;
                    scope.Dispose();
                    // return new DataTable() ;
                    logSpec.Error(e);
                    throw new DeiNiu.Utils.DeiNiuException(e.Message);
                }
            }
            //  return dt;
            LogHelper.debug(typeof(lWmsOutRequest), "end sync request.....");
            isSyncing = false;
        }
        internal bool isErpWorking()
        {
            int offset = 0;
            int hour = DateTime.Now.AddMinutes(offset).Hour;
            int minute = DateTime.Now.AddMinutes(offset).Minute-1;
           
            if (hour == WmsConstants.ERP_TRANS_DATA_AT_CLOCK1)
            {
                if (minute < WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES1+ offset)
                {
                    log.Debug(string.Format(" time for erp transfering.... no out process..." +
                        "当前  {0} 点 {1}分   ----静默剩余  {2}分 ",
                         DateTime.Now.Hour, minute- offset, WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES1 +offset - minute));
                    return true;
                }
            }
            if (hour == WmsConstants.ERP_TRANS_DATA_AT_CLOCK2)
            {
                if (minute < WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES2 + offset)
                {
                    log.Debug(string.Format(" time for erp transfering.... no out process..." +
                        "当前  {0} 点 {1}分   ----静默剩余  {2}分 ",
                         DateTime.Now.Hour, minute - offset, WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES2 + offset - minute));
                    return true;
                }
            } 
            
            log.Debug(string.Format("不满足集货静默时间设置, hour {0}, minute {1}," +
                " CLOCK1 {2} , MINUES1+ offset {3}" +
                ",CLOCK2 {4} , MINUES2+ offset {5}",
                hour, minute, WmsConstants.ERP_TRANS_DATA_AT_CLOCK1, WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES1 + offset
                , WmsConstants.ERP_TRANS_DATA_AT_CLOCK2, WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES2 + offset));
                     
            return false;
        }
        /**
         * erp 没有skuid的情况下,根据batch ,expired date,product data 取skuid
         *
         **/
        public void fixErpSaleDetailSkuId()
        {
            lLot llot = new lLot();
            DataTable dt = outRequest.getAvErpDetailNoSkuId();
            Erp_sale_d esd;
            foreach (DataRow dr in dt.Rows)
            {
                esd = new Erp_sale_d(Convert.ToInt32(dr["id"].ToString()));
                String prd = Util.getShortDateString(esd.product_date.Trim());
                String vld = Util.getShortDateString(esd.save_date.Trim());
                Dictionary dicValue = new Dictionary();
                dicValue.Add(WmsConstants.SKU_RESEVRED_PRDDATE_ATTNAME, prd);
                dicValue.Add(WmsConstants.SKU_RESEVRED_EXPIREDATE_ATTNAME, vld);
                dicValue.Add(WmsConstants.SKU_RESEVRED_BATCH_ATTNAME, esd.batch.Trim());
                dicValue.Add(WmsConstants.SKU_RESEVRED_ENTI_ATTNAME, esd.entid);
                Dictionary skuValue = new Dictionary();
                skuValue = llot.getSKU(prd, esd.goods_id, esd.batch.Trim());
                foreach (int i in skuValue.Keys)
                {
                    esd.skuId = i;
                    esd.skuCode = skuValue[i];
                    break;
                }
                if (esd.skuId > 0)
                {
                    esd.Update();
                }
            }
        }
        public delegate void UpdateUI(int step);//声明一个更新主线程的委托
        public UpdateUI UpdateUIDelegate;
        public delegate void AccomplishTask();//声明一个在完成任务时通知主线程的委托
        public AccomplishTask TaskCallBack;
        public static bool isProcessOutOrders = false;
        /// 
        /// 出库单生成拣货单,完成出库定位
        /// 
        /*
        public void preProcessOutOrders()
         {
             if (isProcessOutOrders)
             {
                 LogHelper.debug(typeof(lWmsOutRequest), "isProcessOutOrders is true, job running,return... ");
                 return;
             }
              
             Thread threadPreProcess = new Thread(preProcessOutOrdersImp);
              threadPreProcess.IsBackground = true;
              threadPreProcess.Start();   
         }
        */
        void updateOutRequestState(string pickOrderNo)
        {
            LogHelper.debug(typeof(lWmsOutRequest), " try updateOutRequestState  " + pickOrderNo);
            enumOutStockRequestStatus rstateNew = Utils.enumOutStockRequestStatus.待定位;
            // enumOutStockRequestStatus rstateOld =   enumOutStockRequestStatus.准备分拣;
            //LogHelper.debug(typeof(lWmsOutRequest), String.Format("rstateNew: {0}, rstateOld: {1}",rstateNew,rstateOld));
            DataTable dt = outRequest.getTemp();
            LogHelper.debug(typeof(lWmsOutRequest), String.Format("tmp rows cnt: {0} ", dt.Rows.Count));
            int cnt = outRequest.updateTmpPickState(pickOrderNo, rstateNew);
            LogHelper.debug(typeof(lWmsOutRequest), String.Format("updateTmpPickState rows cnt: {0} ", cnt));
            esale.updatePickStatus(pickOrderNo, rstateNew);
            //----------------------------------------------------------------------------------------------------------
            enumOutStockRequestStatus rstate = Utils.enumOutStockRequestStatus.待定位;
            enumOutStockDetailStatus dstate = enumOutStockDetailStatus.等待分拣;
            outDetail.updatePickState(pickOrderNo, dstate);
            //--------------------------------------------------------------------------------------------------
        }
        /// 
        /// 预处理多个待出库订单
        /// 1.检查库存量是否够,不足则订单不能出库
        /// 2.检查零库库存量是否够,不够及时补货
        /// 
        /// 
        private void preProcessOutOrdersImp(enumOutStockRequestStatus status)
        {
            logSpec.Debug("开始处理销售订单,订单状态参数为: " + status);
            if (isProcessOutOrders)
            {
                LogHelper.debug(typeof(lWmsOutRequest), " 销售订单正在处理中,稍后再试。。。。。。。。。。。。。。");
                return;
            }
            else
            {
                isProcessOutOrders = true;
            }
            try
            {
                processOutOrders(status);
                isProcessOutOrders = false;
                logSpec.Debug("销售订单处理完毕---------------《《");
            }
            catch (Exception er)
            {
                logSpec.Error(er);
            }
            finally
            {
                isProcessOutOrders = false;
            }
        }
        public void processOutOrders(enumOutStockRequestStatus status)
        {
            if (WmsConstants.AUTO_APPROVE_SALE_ORDER)
            {
                //开始同步下一批数据
                syncOrders();
            }
            Dictionary bulkReps = getRepingCnt();//取今日未上架完成的补货商品明细
            Dictionary bulkCountRequest = new Dictionary();
            Dictionary bulkRepRequest = new Dictionary();
            logTest.Debug("start create pick out request------> status :" + status);
            // outRequest.preparePick(); // only impact on out detail with skuId.
            //根据客户合并出库单,生成拣货单,零货合并成整货的情况下,出整
            string lastCust = "";
            string lastCustAddress = "";
            string lastCustId = "";
            string lastSales = "";
            int lastOrderType = -1;
            int lastPriority = -1;
            bool isMerge = WmsConstants.OUT_REQUEST_MERGE;
            bool isProcessStock = WmsConstants.OUT_REQUEST_PROCESS_STOCK;
 
            DataTable dt = outRequest.QueryByStateForPick(status);
            int worCnt = 0;
            // string lastOrder = "";
            int maxOutRequestCnt = isMerge ? WmsConstants.PAGER_SIZE : 1;
            if (dt.Rows.Count > 0)
            {
                logTest.Debug(" request count to pick  " + dt.Rows.Count);
            }
            int i = 0;
            DataView dv = dt.DefaultView;
            dv.Sort = " priority,customerId,orderType";
            outRequest.deleteTmp("");
            int randomMark = new Random().Next(1000000);
            for (int k = 0; k < dv.Count; k++)
            {
                DataRow dr = dv[k].Row;
                WmsOutRequest wor = new WmsOutRequest(dr);
                /*if (!isMerge)
                {
                    lastOrderType = wor.orderType;
                    createPickorder((enumOrderType)lastOrderType, getOutStoreType(lastOrderType), bulkCountRequest, false, randomMark);
                    continue;
                }*/
                
                if (string.IsNullOrEmpty(lastCustId))
                {
                    lastCust = wor.customerName;// pd.customerId;
                    lastCustAddress = wor.custAddress;
                    lastCustId = wor.customerId;
                    lastOrderType = wor.orderType;
                    lastPriority = wor.priority;
                    lastSales = wor.salesperson;
                }
                if (wor.customerId != lastCustId)
                {
                    Customer cust = new Customer(lastCustId);
                    if (cust.pickInterval > 0 &&
                        outRequest.getByCustForPick(status, lastCustId).Rows.Count == 0)
                    {
                        logTest.Debug("cust " + lastCustId + ", no exist out request to pick, to update last outtime. ");
                        cust.lastOutTime = cust.getDateTime();
                        cust.Update(); 
                    }
                }
                //同客户的订单准备合并成分拣单
                if (isMerge &&
                    lastOrderType == wor.orderType && worCnt < maxOutRequestCnt && lastCustId == wor.customerId
                    && lastCust == wor.customerName && lastCustAddress.Equals(wor.custAddress)
                    && lastPriority == wor.priority && lastSales == wor.salesperson)
                {
                    outRequest.insertTmp(wor.orderNo);
                    if (!isStockLack(wor))
                    {
                        worCnt++;
                    }
                }
                else // new pk
                {
                    createPickorder((enumOrderType)lastOrderType, getOutStoreType(lastOrderType), bulkCountRequest, false, randomMark);
                    worCnt = 0;
                    outRequest.insertTmp(wor.orderNo);
                    if (!isStockLack(wor))
                    {
                        lastCust = wor.customerName;// pd.customerId;
                        lastCustAddress = wor.custAddress;
                        lastCustId = wor.customerId;
                        lastOrderType = wor.orderType;
                        lastPriority = wor.priority;
                        lastSales = wor.salesperson;
                    }
                }
            }
            createPickorder((enumOrderType)lastOrderType, getOutStoreType(lastOrderType), bulkCountRequest, false, randomMark);
            if (dv.Count == 0 || !WmsConstants.OUT_STOCK_WHEN_NO_MORE_REQUEST)// || pickRequestObj.getRequest4StockOut(enumOutStockRequestStatus.待定位).Count>WmsConstants.OUT_PROCESS_ORDERS_CNT)
            {
                processOutStock();
            }
            //scope.Complete();
            // }
            if (!isProcessStock)
            {
                isProcessOutOrders = false;
                return;
            }
            isProcessOutOrders = false;
            logTest.Debug("end create pick out request---------------------------------------- <<<<<<<<<<<<<<<<<<<<<<<<<<<<");
        }
        public void processOutStock()
        {
            //取生成的所有拣货单,按pickgroup生成播种单,对摘果的零货生成补货单
            List all = pickRequestObj.getRequest4StockOut(enumOutStockRequestStatus.待定位);
            bool isSeedsCreated = false;
            logTest.Debug(" 取待定位的分拣单, 数量 " + all.Count);
            List seedsLst;
            Dictionary> dicGroup = new Dictionary>();
          //  bool isHour = DateTime.Now.Hour >= WmsConstants.SEEDS_START_HOUR && DateTime.Now.Hour <= WmsConstants.SEEDS_END_HOUR;
          //  bool isMinute = DateTime.Now.Minute >= WmsConstants.SEEDS_START_MINUTES && DateTime.Now.Minute <= WmsConstants.SEEDS_END_MINUTES;
            bool isHour = DateTime.Now.Hour == WmsConstants.ERP_TRANS_DATA_AT_CLOCK1 ;
            bool isMinute = false;// DateTime.Now.Minute >= WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES1 && DateTime.Now.Minute <= WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES1 +30;
           
            logTest.Debug(string.Format("系统总拣任务生成开始时间设定: CLOCK1 {0}  , MINUES1 {1}, CLOCK2 {2}  , MINUES2 {3}, continue minutes {4}  ", WmsConstants.ERP_TRANS_DATA_AT_CLOCK1,
               WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES1, WmsConstants.ERP_TRANS_DATA_AT_CLOCK2,
               WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES2, WmsConstants.SEEDS_CONTINIU_MINUTES));
           // logTest.Debug(string.Format("DateTime.Now.Hour  {0}  ,DateTime.Now.Minute {1}  ", DateTime.Now.Hour, DateTime.Now.Minute));
           // logTest.Debug(string.Format("isHour {0}  ,isminute {1}  ",isHour,isMinute));
          
            
            if (isHour)
            {
                isMinute = DateTime.Now.Minute >= WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES1 
                    && DateTime.Now.Minute <= WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES1 + WmsConstants.SEEDS_CONTINIU_MINUTES;
                logTest.Debug(string.Format("系统总拣任务生成开始时间{0}:{1},系统总拣结束时间{2}:{3}, 可以总拣? {4}",
                WmsConstants.ERP_TRANS_DATA_AT_CLOCK1, WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES1,
                WmsConstants.ERP_TRANS_DATA_AT_CLOCK1, WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES1 + WmsConstants.SEEDS_CONTINIU_MINUTES, isHour && isMinute));
            }
            else
            {
                isHour = DateTime.Now.Hour == WmsConstants.ERP_TRANS_DATA_AT_CLOCK2  ;
                if (isHour)
                {
                    isMinute = DateTime.Now.Minute >= WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES2
                        && DateTime.Now.Minute <= WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES2 + WmsConstants.SEEDS_CONTINIU_MINUTES;
                    logTest.Debug(string.Format("系统总拣任务生成开始时间{0}:{1},系统总拣结束时间{2}:{3}, 可以总拣? {4}",
                   WmsConstants.ERP_TRANS_DATA_AT_CLOCK2, WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES2,
                   WmsConstants.ERP_TRANS_DATA_AT_CLOCK2, WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES2 + WmsConstants.SEEDS_CONTINIU_MINUTES, isHour && isMinute));
                }
            }
            // logTest.Debug(string.Format("系统总拣开始时间{0}:{1},系统总拣结束时间{2}:{3}, 可以总拣? {4}", 
            //     WmsConstants.SEEDS_START_HOUR, WmsConstants.SEEDS_START_MINUTES,
            //     WmsConstants.SEEDS_END_HOUR, WmsConstants.SEEDS_END_MINUTES, isHour && isMinute));
            if (isHour && isMinute)
            {
                //根据系统的集货设置参数,判断当前时间是否可以进行总拣
                foreach (WmsOutPickRequest opr in all)
                {
                    if (opr.pickGroup == 0 || !string.IsNullOrEmpty(opr.seedsPickNo))
                    {
                        continue;
                    }
                    /*Customer cust = new Customer(opr.customerId);  //根据客户的集货时间点判断是不是进行总拣
                    if (cust.pickStartOn > 0)
                    {
                        try
                        {
                            int hour = Convert.ToInt32(new Node(cust.pickStartOn).value.Trim());
                            if (DateTime.Now.Hour < hour)
                            {
                                logOut.Debug(string.Format(" 分拣单 {0}, customer {1}, 总拣开始时间 {2} ,不取总。 ", opr.pickOrderNo, cust.customerId, hour));
                                continue;
                            }
                        }
                        catch (Exception er)
                        {
                        }
                    } */
                    if (!dicGroup.ContainsKey(opr.pickGroup))
                    {
                        dicGroup[opr.pickGroup] = new List();
                    }
                    dicGroup[opr.pickGroup].Add(opr);
                }
            }
            else
            {
                logOut.Debug(" 不满足 分组总拣 时间点设定" );
            }
          //  logOut.Debug(" 待定位的分拣单,分组数量 " + dicGroup.Count);
            foreach (int group in dicGroup.Keys)
            {
                seedsLst = dicGroup[group];
                if (seedsLst.Count <= 1)  //1 个 订单 不做总拣
                {
                    continue;
                }
            //    logOut.Debug("  分组  " + group);
                WmsOutPickRequest seedPickRequest = new WmsOutPickRequest();
                DataTable dtSeeds = seedPickRequest.getNewSeedDetails(group);
               
               // logSpec.Debug(string.Format("randomMark:{0} , seeds detail count {1}", group, dtSeeds.Rows.Count));
                if (dtSeeds.Rows.Count > 0)
                {
                    using (TransactionScope scope = new TransactionScope())
                    {
                        seedPickRequest.pickOrderNo = Util.getOrderNo(enumCreateOrderType.seedsPickOrder, seedPickRequest.getNextSeq(enumCreateOrderType.seedsPickOrder));
                        seedPickRequest.orderType = seedsLst[0].orderType;// (int)enumOutOrderType.销售出库;
                        seedPickRequest.outStoreType = (int)enumOutStoreType.配货汇总拣货出库;
                        seedPickRequest.seedsPort = group;
                        seedPickRequest.pickGroup = group;
                        seedPickRequest.priority = (int)enumPickPriority.优先;// 优先级别
                        seedPickRequest.state = (int)enumOutStockRequestStatus.待定位;
                        seedPickRequest.tranLocationId = new TmsStock().getSeedsLocation();
                       
                     //   logOut.Debug(string.Format("生成 播种拣选单 :{0} ", seedPickRequest.pickOrderNo));
                       
                        List lstwpd = new List();
                        foreach (DataRow dr in dtSeeds.Rows)
                        {
                            WmsOutPickDetail pd = new WmsOutPickDetail(dr);
                            pd.pickOrderNo = seedPickRequest.pickOrderNo;
                            // logSpec.Debug(" pd state is .." + pd.state);
                           // logTest.Debug(  string.Format(" goodsId {4},is seedsout {5},  canSeedOut {0}.  isZhitong {1}, isWeightOut {2}, WmsConstants.SEEDS_OUT_NOT_WITH_WEIGHT {3}", pd.goods.canSeedOut, pd.goods.isZhitong, pd.goods.isWeightOut(), WmsConstants.SEEDS_OUT_NOT_WITH_WEIGHT, pd.goods.goodsId, pd.goods.isSeedsOut()));
                            if (pd.goods.isSeedsOut()  ) 
                            {
                                lstwpd.Add(pd);
                            }
                            else
                            {
                               // logSpec.Debug(string.Format("goods id {0} is not seeded ,is weight? {1}",pd.goods.goodsId,pd.goods.isWeightOut()));
                            }
                        }
                        if (lstwpd.Count > 0)
                        {
                            seedPickRequest.Add();
                            foreach(WmsOutPickDetail wpd in lstwpd)
                            {
                                wpd.Add();
                                
                            }
                            foreach (WmsOutPickRequest wp in seedsLst)
                            {
                                // wp.seedsPickNo=seedPickRequest.pickOrderNo;
                                foreach (WmsOutPickDetail wpd in lstwpd)
                                {
                                  //  if (wp.pickOrderNo.Equals(wpd.pickOrderNo))
                                    {
                                        wp.setSeedsNo(seedPickRequest.pickOrderNo);
                                        wp.Update();
                                        break;
                                    }
                                        
                                } 
                                  
                            }
                        }
                      
                        scope.Complete();
                    }
                    requestOutStock(seedPickRequest);
                    isSeedsCreated = true;
                }
            }
            #region 在分拣定位时生成补货单
            /*
             * 在分拣定位时生成补货单
             * 
            //比较零库库存  
            foreach (string key in bulkCountRequest.Keys)
                 {
                     string goodsId, skuId, batch;
                     getKeyValueSplit(out goodsId, out skuId, out batch, key);
                     decimal inProcessCnt = bulkReps.ContainsKey(key) ? bulkReps[key] : 0; //getRepingCnt(goodsId, batch);//正补货中的数量
                     WmsGoods goods = new WmsGoods(goodsId,  Convert.ToInt32(skuId), batch);// ObjectsFactory.getGoods(goodsId,  Convert.ToInt32(skuId));//goodsCache[goodsId];//new WmsGoods(goodsId, batch);
                     decimal cnt = bulkCountRequest[key] - goods.stockBulkCountOuting - goods.stockBulkAvCount - inProcessCnt;
                     if (skuId == "3724")
                         LogHelper.debug(this.GetType(), string.Format("key {0},bulkCountRequest {1}, goods.stockBulkCountOuting {2} ,goods.stockBulkAvCount {3}, inProcessCnt {4}"
                                , key, bulkCountRequest[key], goods.stockBulkCountOuting, goods.stockBulkAvCount, inProcessCnt));
                     if (goods.stockBatchAvCount > 0)
                         if (cnt > 0 && goods.canRep(skuId))
                         { // 订单按商品,批号,和客户汇总后发现库存零货不足
                             bulkRepRequest[key] = cnt;
                             //  bulkCountRequest[key] = 0;
                             if (skuId == "3724")
                                 LogHelper.debug(typeof(lWmsOutRequest), " createGoodsRepOrder key: " + key + ",count " + cnt);
                         }
                 }
            
                 //生成补货单
                 if (bulkRepRequest.Count > 0)
                 {
                     createGoodsRepOrder(bulkRepRequest);
                    
                 }
                 Dictionary bulkRepRequestPlus = new Dictionary();
                 DataTable dtReplst = new WmsGoods().getRepLst();
                 foreach (DataRow dr in dtReplst.Rows)
                 {
                     WmsOutPickDetail pd = new WmsOutPickDetail(dr);
                     string key = pd.goodsId.Trim() + WmsConstants.SPLIT + pd.skuId + WmsConstants.SPLIT + pd.batch;
                     WmsGoods goods = new WmsGoods(pd.goodsId, pd.skuId, pd.batch);
                    // LogHelper.debug(this.GetType(), string.Format("stockBatchAvCount {0} ", goods.stockBatchAvCount));
                     if (goods.stockBatchAvCount > 0 && goods.canRep(pd.skuId + ""))
                     {
                         LogHelper.debug(this.GetType(), string.Format("goods.sumBulkOuting {0} ,goods.stockBulkAvCount{1} ", goods.sumBulkOuting(pd.skuId + ""), goods.stockBulkAvCount));
                         if (goods.sumBulkOuting(pd.skuId + "") > goods.stockBulkAvCount)
                         {
                             if (!bulkRepRequest.ContainsKey(key))
                             {
                                 bulkRepRequestPlus.Add(key, pd.count);
                             }
                         }
                     }  
                 }
                 if (bulkRepRequestPlus.Count > 0)
                 {
                     createGoodsRepOrder(bulkRepRequestPlus);
                     bulkRepRequestPlus.Clear();
                 }
                 */
            #endregion
            if (isSeedsCreated)
            {
              //  logOut.Debug(" 从新取待定位的拣货单 --------------------------------------------------------------  ");
                all = pickRequestObj.getRequest4StockOut(enumOutStockRequestStatus.待定位);
            }
          //  logOut.Debug(all.Count + "  个待定位的拣货单 ---------------------------------------------------------- ");
            DateTime dateTime = DateTime.Now;
            foreach (WmsOutPickRequest opr in all)
            {
                opr.checkedTime = string.Empty;
                requestOutStock(opr);
                if (opr.state == (int)enumOutStockRequestStatus.待定位)
                {
                    opr.checkedTime = opr.getDateTime();
                    opr.Update();
                }
                bool isOverTime = DateTime.Now.CompareTo(dateTime.AddMinutes(WmsConstants.OUT_STOCK_PROCESS_MAX_TIME_MINUTE)) > 0;
                //logOut.Debug(" is over time ?" + isOverTime );
                if (isOverTime)
                {
                    logOut.Debug(" is over time ?" + isOverTime);
                    break;
                }
            }
          //  logOut.Debug("开始生成补货单...>");
            createGoodsRepOrder();
         //   logOut.Debug("补货单生成结束...<");
            all = pickRequestObj.getRequest4StockOut(enumOutStockRequestStatus.等待补货);
          //  logTest.Debug(all.Count + "  个等待补货订单 ----------------------------------------------------------------- ");
            foreach (WmsOutPickRequest opr in all)
            {
                logTest.Debug("待补货: " + opr.pickOrderNo + " state " + opr.state);
                opr.checkedTime = string.Empty;
                requestOutStock(opr);
                if (opr.state == (int)enumOutStockRequestStatus.等待补货)
                {
                    opr.checkedTime = opr.getDateTime();
                    opr.Update();
                }
                bool isOverTime = DateTime.Now.CompareTo(dateTime.AddMinutes(WmsConstants.OUT_STOCK_PROCESS_MAX_TIME_MINUTE)) > 0;
                // logOut.Debug(" is over time ?" + isOverTime);
                if (isOverTime)
                {
                    logTest.Debug(" is over time ?" + isOverTime);
                    break;
                }
            }
        }
        bool isStockLack(WmsOutRequest wor)
        {
            if (!WmsConstants.OUT_STOCK_LACK_VALIDATION)
            {
                return false;
            }
            DataTable dtdiff = outRequest.getOverStock();
            foreach (DataRow drx in dtdiff.Rows)
            {
               // LogHelper.WriteLog(typeof(lWmsOutRequest), "goods store lack detected: to insert... ");
                WmsStockLack sl = new WmsStockLack(drx);
                sl.getBySaleOrder(wor.orderNo, sl.goodsId, sl.skuId);
                if (sl.ID == 0)
                {
                    sl.orderNo = wor.orderNo;
                    sl.Add();
                }
            //    LogHelper.WriteLog(typeof(lWmsOutRequest), "goods store lack detected: " + wor.orderNo + ", new id " + sl.ID);
                updateDetailStockShortage(wor, sl.skuId, sl.lackCount);
            }
            return dtdiff.Rows.Count > 0;
        }
        private void updateDetailStockShortage(WmsOutRequest wor, int skuId, decimal lackCount)
        {
            if (WmsConstants.OUT_STOCK_LACK_HOLD_ORDER)
            {
                wor.state = (int)enumOutStockRequestStatus.库存不足;
                wor.operater = this.operId;
                wor.Update();
                outRequest.updateDetailStockShortage(wor.orderNo, skuId, lackCount);
             //   LogHelper.debug(typeof(WmsOutRequest), " begin delete temp   2");
                outRequest.deleteTmp(wor.orderNo);
            }
            else
            {/* //在 outpickdetail处理
                wor.remark += "缺货:";
                foreach (WmsOutDetail wd in wor.outDetails)
                {
                    if (lackCount <= 0)
                    {
                        return;
                    }
                    if (wd.skuId == skuId)
                    {
                        if (wd.count > lackCount)
                        {
                            wd.count -= lackCount; 
                            wd.lackCount = lackCount;
                            lackCount = 0;
                        }
                        else
                        {                           
                            lackCount -= wd.count;  
                            wd.lackCount= wd.count ;
                            wd.count = 0;
 
                        }
                        wd.bulkCount = wd.count % wd.goods.bigCount;
                        wd.batch1Count = wd.count - wd.bulkCount;
                        wd.boxcnt = Convert.ToInt32( wd.batch1Count / wd.goods.bigCount); 
                        wd.Update();
                        wor.remark += ";" + wd.skuId + " lack " + wd.lackCount;
                    }
             
                } * */
                wor.Update();
            }
        }
        private enumOutStoreType getOutStoreType(int lastOrderType)
        {
            enumOrderType orderType = (enumOrderType)lastOrderType;
            switch (orderType)
            {
                case enumOrderType.销售出库:
                    return enumOutStoreType.拣货出库;
                case enumOrderType.退供应商:
                    return enumOutStoreType.返厂出库;
                case enumOrderType.仓间调拨:
                    return enumOutStoreType.调拨出库;
            }
            return enumOutStoreType.拣货出库;
        }
        private void createPickorder(enumOrderType orderType, enumOutStoreType outStoreType,
            Dictionary bulkCountRequest, bool isRequestStock = true, int checkNum = 0)
        {
            DataTable outCust;
            WmsOutPickRequest pr = null;
            // WmsOutPickDetail pd = null;
            List pdCache = new List();
            //  List prCache = new List(); 
            // logSpec.Debug(" special is here! ");
            outCust = outRequest.getNewRequestPickDetails().Tables[0];
            int i = 0;
            foreach (DataRow dr1 in outCust.Rows)
            {
                i++;
                WmsOutPickDetail pd = new WmsOutPickDetail(dr1);
                if (string.IsNullOrEmpty(pd.goodsId))
                {
                    logSpec.Debug(string.Format("goodsId is null exception, customerid is{0} ", pd.customerId));
                    continue;
                }
                if (pr == null)
                {
                    pr = new WmsOutPickRequest(dr1);
                    pr.pickOrderNo = Util.getOrderNo(enumCreateOrderType.pickOrder, pr.getNextSeq(enumCreateOrderType.pickOrder));
                    pr.orderType = (int)orderType;
                    pr.orderTypeName = orderType.ToString();
                    pr.outStoreType = (int)outStoreType;
                    pr.bulkCnt = 0;
                    pr.boxCnt = 0;
                    pr.sumPrice = 0;
                    pr.seedsPort = checkNum;//临时随机记号,标记生成的哪一批
                    //   pr.operater =  LoginInfo.UserId;
                    /*
                    pr.customerId = pd.customerId;
                    pr.customerName = pd.customerName;
                    pr.custAddress = pd.custAddress;
                    pr.salesperson = pd.salesperson;
                    */
                }
                pd.whtype = (int)getWhType((int)outStoreType);
                pd.pickOrderNo = pr.pickOrderNo;
                pr.bulkCnt += pd.bulkCount; //pick request 总bulk cnt,作为拣选、复合工作量的指标
                pr.boxCnt += pd.boxcnt;
                pr.state = (int)enumOutStockRequestStatus.待定位;
                pr.sumPrice += pd.count * pd.price;
                /* 
                 if (WmsConstants.OUT_REQUEST_PROCESS_STOCK)
                  {
                      if (orderType == enumOutOrderType.销售出库)
                          if (pd.bulkCount > 0 && pd.bulkCount > pd.goods.stockBulkAvCount //pd.getGoodsStockCnt(enumWhLocVol.零库))// pd.goods.stockBulkCount)
                          {
                              pd.description = "零库库存不足,等待补货";
                              pr.state = (int)enumOutStockRequestStatus.等待补货;
                              pd.state = (int)enumOutStockDetailStatus.等待补货;
                              pr.description = string.Format("{0} {1} 零库库存不足,等待补货 ", pd.goods.goodsName, pd.skuId);
                              logSpec.Debug( pr.description);
                          }
                  }*/
                pd.operater = this.operId;
                if (!WmsConstants.OUT_REQUEST_PROCESS_STOCK)
                {
                    pd.bulkCount += pd.batch1Count + pd.batch2Count;
                    pd.batch1Count = 0;
                    pd.batch2Count = 0;
                }
                pdCache.Add(pd);
                //calculate the total bulk for each goods
                if (pd.bulkCount > 0)
                {
                    string key = pd.goodsId.Trim() + WmsConstants.SPLIT + pd.skuId + WmsConstants.SPLIT + pd.batch;
                    /*if (bulkCountRequest.Keys.Contains(key))
                     {
                         bulkCountRequest[key] += pd.bulkCount;
                     }
                     else
                     {
                         bulkCountRequest[key] = pd.bulkCount;
                     }
                    */
                    if (pd.count == pd.bulkCount) //batch not exists
                    {
                        pd.batchPickState = (int)enumOutStockPickStatus.无需分拣;
                    }
                }
                else
                {
                    pd.bulkPickState = (int)enumOutStockPickStatus.无需分拣;
                }
            }
            //create new pickorder 
            if (pr != null)
            {
                pr.orderDate = pr.getDateTime();
                pr.operater = this.operId;
                try
                {
                    using (TransactionScope scope1 = new TransactionScope())
                    {
                        pr.batchPickState = (int)enumOutStockPickStatus.无需分拣;
                        //  int jj = 0;
                        updateOutRequestState(pr.pickOrderNo);
                        foreach (WmsOutPickDetail p in pdCache)
                        {
                            if (p.batchPickState != (int)enumOutStockPickStatus.无需分拣)
                            {
                                pr.batchPickState = (int)enumOutStockPickStatus.待处理;
                            }
                            p.Add();
                            pr.outDetails.Add(p);
                        }
                        pr.Add();
                        /*
                        if (pr.state != (int)enumOutStockRequestStatus.等待补货)
                        {
                            prCache.Add(pr);
                        }
                        */
                        //  LogHelper.debug(typeof(WmsOutRequest), " begin delete temp   3");
                        outRequest.deleteTmp("");
                        DataTable dt = outRequest.getRequestByPickOrder(pr.pickOrderNo);
                        decimal fandian = 0m;
                        int delivery = 0;
                        WmsOutRequest wor = new WmsOutRequest();
                        foreach (DataRow dr in dt.Rows)
                        {
                            wor = new WmsOutRequest(dr);
                            fandian += wor.fandian;
                            delivery = wor.delivery;
                        }
                        pr.fandian = fandian;
                        pr.deliveryType = delivery;
                        pr.Update();
                        scope1.Complete();
                        //}
                    }
                }
                catch (Exception er)
                {
                    logSpec.Error(er);
                    //  updateOutRequestState(lastCustId, lastCust, lastCustAddress, "");
                    logSpec.Error("error on creating pickoutrequest " + pr.pickOrderNo);
                    //    logSpec.Error(" begin delete temp   4");
                    outRequest.deleteTmp("");
                    return;
                }
                pdCache.Clear();
                //  logSpec.Debug("pickrequest created " + pr.pickOrderNo);
                if (isRequestStock)
                    requestOutStock(pr.pickOrderNo);
            }
        }
        private enumWhType getWhType(int outStoreType)
        {
            enumOutStoreType outType = (enumOutStoreType)outStoreType;
            switch (outType)
            {
                case enumOutStoreType.报废出库:
                    return enumWhType.报废库;
                case enumOutStoreType.返厂出库:
                    return enumWhType.返厂库;
                default:
                    return enumWhType.合格库;
            }
        }
        private Dictionary> handleErrorObjects(Dictionary> errorObjects)
        {
            if (errorObjects.Count == 0)
            {
                return errorObjects;
            }
            List prCache = new List();
            foreach (WmsOutPickRequest pr1 in errorObjects.Keys)
            {
                try
                {
                    using (TransactionScope scope1 = new TransactionScope())
                    {
                        pr1.operater = this.operId;
                        pr1.Add();
                        foreach (WmsOutPickDetail pd1 in errorObjects[pr1])
                        {
                            pd1.operater = this.operId;
                            pd1.Add();
                        }
                        if (pr1.state != (int)enumOutStockRequestStatus.等待补货)
                        {
                            prCache.Add(pr1);
                        }
                        scope1.Complete();
                    }
                }
                catch (Exception er)
                {
                    //continue loop
                    LogHelper.WriteLog(typeof(lWmsOutRequest), er);
                }
            }
            foreach (WmsOutPickRequest pr in prCache)
            {
                errorObjects.Remove(pr);
            }
            return errorObjects;
        }
        private void getKeyValueSplit(out string goodsId, out string skuId, out string skuCode, string key)
        {
            string[] tmp = key.Split(WmsConstants.SPLIT.ToCharArray());
            goodsId = tmp[0].ToString();
            skuId = tmp[3].ToString(); //TODO: 为什么分解成4条?
            skuCode = tmp[6].ToString(); //TODO: 为什么分解成4条?
        }
        /// 
        /// 批次生成零库补货单(整库出库单)
        /// 补货单捡完货出库完成后, 会生成零库入库单,然后开始补货入库流程
        /// 
        /// 
        /// 
        public bool createGoodsRepOrder(Dictionary requestRep)
        {
            LogHelper.debug(typeof(lWmsOutRequest), " createGoodsRepOrder start  ,detail count: " + requestRep.Count);
            if (requestRep.Count == 0)
            {
                return false;
            }
            WmsOutPickRequest repRequest = new WmsOutPickRequest();
            using (TransactionScope scope = new TransactionScope())
            {
                repRequest.orderType = (int)enumOrderType.补货出库;
                repRequest.outStoreType = (int)enumOutStoreType.补货出库;
                repRequest.operater = this.operId;
                repRequest.pickOrderNo = Util.getOrderNo(enumCreateOrderType.repOrderOut, repRequest.getNextSeq(enumCreateOrderType.repOrderOut));
                repRequest.orderTypeName = enumOrderType.补货出库.ToString();
                repRequest.orderDate = repRequest.getDateTime();// use database default date
                repRequest.bulkPickState = (int)enumOutStockPickStatus.无需分拣;
                repRequest.state = (int)enumOutStockRequestStatus.待定位;//(int)enumOutStockRequestStatus.正在分拣;// (int)enumOutStockRequestStatus.等待分拣;
                //create request detail
                WmsOutPickDetail outd = new WmsOutPickDetail();
                WmsOutPickDetail cachedObj;
                bool kidborn = false;
                foreach (string key in requestRep.Keys)
                {
                    string goodsId, skuId, skuCode;
                    getKeyValueSplit(out goodsId, out skuId, out skuCode, key);
                    //  WmsOutPickDetail outd = new WmsOutPickDetail();
                    cachedObj = new WmsOutPickDetail();// ObjectsFactory.getOutDetail(goodsId,  Convert.ToInt32(skuId));
                    WmsGoods goods = new WmsGoods(goodsId);
                    DataTable dt = goods.getSkuValues(goods.lotId, Convert.ToInt32(skuId), WmsConstants.SKU_RESEVRED_BATCH_ATTNAME);
                    string batch = "";
                    foreach (DataRow dr in dt.Rows)
                    {
                        batch = dr["value"].ToString();
                        break;
                    }
                    // Sku sku = new Sku(skuId);
                    // outd.skuCode = sku.skuCode;
                    outd.skuCode = skuCode;
                    outd.pickOrderNo = repRequest.pickOrderNo;
                    //   outd.operater = repRequest.operater;
                    outd.goodsId = goodsId;
                    outd.batch = batch;
                    outd.skuId = Convert.ToInt32(skuId);
                    outd.productDate = cachedObj.productDate;
                    outd.validDate = cachedObj.validDate;
                    decimal cnt = requestRep[key];
                    outd.count = cnt;
                    //if (cachedObj.goods.bigCount != 0)
                    if (goods.bigCount != 0)
                    {
                        int boxcnt = (int)Math.Ceiling(cnt / goods.bigCount);
                        cnt = boxcnt * goods.bigCount;  //取整箱     
                        outd.count = cnt;
                        outd.boxcnt = boxcnt;
                    }
                    outd.batch1Count = cnt;
                    outd.whtype = cachedObj.whtype;
                    outd.operater = this.operId;
                    outd.bulkPickState = (int)enumOutStockPickStatus.无需分拣;
                    outd.Add();
                    kidborn = true;
                }
                if (kidborn)
                {
                    repRequest.Add();
                    scope.Complete();
                    LogHelper.debug(typeof(lWmsOutRequest), " start process stock for rep request " + repRequest.pickOrderNo);
                    return requestOutStock(repRequest);
                }
                else
                {
                    scope.Dispose();
                }
            }
            return true;
        }
        public bool createGoodsRepOrder()
        {
            WmsStockRep stkrep = new WmsStockRep();
            DataTable dt = stkrep.getNewData();
            if (dt.Rows.Count == 0) { return false; }
            WmsOutPickRequest repRequest = new WmsOutPickRequest();
            repRequest.orderType = (int)enumOrderType.补货出库;
            repRequest.outStoreType = (int)enumOutStoreType.补货出库;
            repRequest.operater = this.operId;
            repRequest.pickOrderNo = Util.getOrderNo(enumCreateOrderType.repOrderOut, repRequest.getNextSeq(enumCreateOrderType.repOrderOut));
            repRequest.orderTypeName = enumOrderType.补货出库.ToString();
            repRequest.orderDate = repRequest.getDateTime();// use database default date
            repRequest.bulkPickState = (int)enumOutStockPickStatus.无需分拣;
            repRequest.state = (int)enumOutStockRequestStatus.待定位;// (int)enumOutStockRequestStatus.正在分拣;// (int)enumOutStockRequestStatus.等待分拣;
            repRequest.priority = (int)enumPickPriority.加急;//高优先级别
            using (TransactionScope scope = new TransactionScope())
            {
                foreach (DataRow dr in dt.Rows)
                {
                    stkrep = new WmsStockRep(dr);
                    //create request detail
                    WmsOutPickDetail outd = new WmsOutPickDetail();
                    outd.pickOrderNo = repRequest.pickOrderNo;
                    //   outd.operater = repRequest.operater;
                    outd.goodsId = stkrep.goodsId;
                    outd.skuId = stkrep.skuId;
                    outd.count = stkrep.toRepCnt;
                    outd.batch1Count = stkrep.toRepCnt;
                    outd.whtype = (int)enumWhType.合格库;
                    outd.operater = this.operId;
                    outd.bulkPickState = (int)enumOutStockPickStatus.无需分拣;
                    outd.Add();
                    logSpec.Debug(string.Format("新增补货单{0}, detail id {1} ", repRequest.pickOrderNo, outd.ID));
                }
                stkrep.repNews();
                repRequest.Add();
                scope.Complete();
                logOut.Debug(string.Format("新增补货单{0}, items count {1} ", repRequest.pickOrderNo, dt.Rows.Count));
            }
            requestOutStock(repRequest);
            return true;
        }
        public bool reportBulkLack(WmsGoods goods, int skuId, string skuCode, decimal count, bool checkOnly = false)
        {
            if (count <= 0)
            {
                return false;
            }
            decimal rpcnt = Math.Ceiling(count / goods.bigCount) * goods.bigCount; ;
            WmsStockRep stkrep = new WmsStockRep(goods.goodsId, skuId);
            logSpec.Debug(string.Format("开始登记补货信息。。goodsId {0}, skuId:{1},skuCode:{2}, 补货数量  {3}", goods.goodsId, skuId, skuCode, count));
            logSpec.Debug(string.Format("1 商品补货情汇总--》 toRepCnt {0}, lacCount:{1}  ", stkrep.toRepCnt, stkrep.lackCount));
            if (!checkOnly)
            {
                if (goods.stockBatch3Count + goods.stockBatch2Count + goods.stockBatch1Count < count)
                {
                    logSpec.Debug(string.Format("整库库存不足,补货单生成失败"));
                    return false;
                }
                stkrep.lackCount += count; ;
            }
            else
            {
                if (stkrep.toRepCnt > 0)
                {
                    return false;
                }
            }
            logSpec.Debug(string.Format(" 2 商品补货情汇总--》 toRepCnt {0}, lacCount:{1}  ", stkrep.toRepCnt, stkrep.lackCount));
            /*
            logSpec.Debug(string.Format(" 商品补货情汇总--》 累计申请数量{0}, 累计缺货数量:{1},需增加补货数量:{2} ",
                stkrep.repCont+stkrep.toRepCnt, stkrep.lackCount,
                stkrep.lackCount - (stkrep.repCont + stkrep.toRepCnt)));
            */
            if (stkrep.toRepCnt - stkrep.lackCount < count)
            {
                logSpec.Debug(string.Format("增加补货 {2}, for: stkrep.toRepCnt - stkrep.lackCount {0} < count:{1}  ", stkrep.toRepCnt - stkrep.lackCount, count, rpcnt));
                stkrep.toRepCnt += rpcnt;
            }
            else
            {
                logSpec.Debug(string.Format("-----------------------------------------------现有补货单可以满足需求,无需创建新补货单 "));
            }
            if (stkrep.ID > 0)
            {
                stkrep.Update();
            }
            else
            {
                stkrep.Add();  //TODO: when rep task on shelf, delete the record
            }
            return true;
        }
        public bool createGoodsRepOrder(string[] goodsRep, int fromDetailId = 0)
        {
            WmsOutPickRequest repRequest = new WmsOutPickRequest();
            using (TransactionScope scope = new TransactionScope())
            {
                repRequest.orderType = (int)enumOrderType.补货出库;
                repRequest.outStoreType = (int)enumOutStoreType.补货出库;
                repRequest.operater = this.operId;
                repRequest.pickOrderNo = Util.getOrderNo(enumCreateOrderType.repOrderOut, repRequest.getNextSeq(enumCreateOrderType.repOrderOut));
                repRequest.orderTypeName = enumOutStoreType.补货出库.ToString();
                repRequest.orderDate = repRequest.getDateTime();// use database default date
                repRequest.bulkPickState = (int)enumOutStockPickStatus.无需分拣;
                repRequest.state = (int)enumOutStockRequestStatus.待定位;// (int)enumOutStockRequestStatus.正在分拣;// (int)enumOutStockRequestStatus.等待分拣;
                repRequest.priority = (int)enumPickPriority.加急;//高优先级别
                                                               //create request detail
                WmsOutPickDetail outd = new WmsOutPickDetail();
                int i = 0;
                foreach (string str in goodsRep)
                {
                    string[] tmp = str.Split(WmsConstants.SPLIT.ToCharArray());
                    string goodsId = tmp[0].ToString();
                    string batch = tmp[3].ToString();
                    string prdDate = tmp[9].ToString();
                    string validDate = tmp[12].ToString();
                    decimal repCnt = Convert.ToDecimal(tmp[6].ToString());
                    int skuId = Convert.ToInt32(tmp[15].ToString());
                    string skuCode = tmp[18].ToString();
                    WmsGoods goods = new WmsGoods(goodsId, skuId, batch);
                    if (goods.stockBatch3Count + goods.stockBatch2Count + goods.stockBatch1Count < repCnt)
                    {
                        continue;
                    }
                    //  WmsOutPickDetail outd = new WmsOutPickDetail();
                    outd.pickOrderNo = repRequest.pickOrderNo;
                    //   outd.operater = repRequest.operater;
                    outd.goodsId = goodsId;
                    outd.batch = batch;
                    outd.skuCode = skuCode;
                    outd.skuId = skuId;
                    outd.productDate = prdDate;
                    outd.validDate = validDate;
                    decimal cnt = repCnt;
                    if (cnt < goods.bigCount)
                    {
                        cnt = goods.bigCount;
                    }
                    outd.count = cnt;
                    outd.state = (int)enumOutStockDetailStatus.等待补货;
                    outd.batch1Count = cnt;
                    outd.whtype = (int)enumWhType.合格库;
                    outd.operater = this.operId;
                    outd.bulkPickState = (int)enumOutStockPickStatus.无需分拣;
                    outd.Add();
                    i++;
                }
                if (i > 0)
                {
                    repRequest.Add();
                }
                else
                {
                    scope.Dispose();
                    return false;
                }
                scope.Complete();
            }
            return requestOutStock(repRequest);
        }
        /// 
        /// 根据补库出库单创建补库手持分拣数据
        /// need transacation scope
        /// 
        /// 
        private void createRepPortData(WmsOutPickRequest outRequest)
        {
            /*
            WmsInRequest repRequest = new WmsInRequest();
            repRequest.orderType = (int)enumInOrderType.repOrderIn;
            // repRequest.operater =  LoginInfo.UserId;
            repRequest.orderNo = Util.getOrderNo(enumCreateOrderType.repOrderIn, repRequest.getNextSeq());
            repRequest.orderTypeName = "补零入库单";
            repRequest.state = (int)enumInStockOrderStatus.normal;
            repRequest.orderDate = DateTime.Now.Date.ToString();// use database default date
            repRequest.operater = this.operId;
            repRequest.Add();
            */
            DataTable dt = new WmsStockRecord().getPickStockRecods(outRequest.pickOrderNo, true).Tables[0];
            int i = 0;
            foreach (DataRow dr in dt.Rows)
            {
                WmsOutPickPort wpp = new WmsOutPickPort();
                if (
                    string.IsNullOrEmpty(dr[WmsStockRecord.fields.count.ToString()].ToString())
                    && string.IsNullOrEmpty(dr[WmsStockRecord.fields.countOuting.ToString()].ToString())
                  || string.IsNullOrEmpty(dr[WmsStockRecord.fields.locationId.ToString()].ToString()))
                {
                    continue;
                }
                wpp.count = Convert.ToDecimal(dr[WmsStockRecord.fields.count.ToString()].ToString())
                            + Convert.ToDecimal(dr[WmsStockRecord.fields.countOuting.ToString()].ToString());
                if (wpp.count == 0)
                {
                    continue;
                }
                wpp.locationId = dr[WmsStockRecord.fields.locationId.ToString()].ToString();
                wpp.pickOrderNo = outRequest.pickOrderNo;
                wpp.recordId = Convert.ToInt32(dr["id"].ToString());
                wpp.volType = wpp.volType = Convert.ToInt32(dr["volType"].ToString());
                wpp.recType = (int)enumStockRecordType.补零出库;
                wpp.partion = Convert.ToInt32(dr["partion"].ToString());
                wpp.pickDetailId = Convert.ToInt32(dr["orderDetailId"].ToString());
                wpp.Add();
                i++;
            }
            if (i > 0)
            {
                outRequest.state = (int)enumOutStockRequestStatus.等待波次;
                outRequest.Update();
            }
        }
        /// 
        /// 获取(今天)的未上架(未完成的)补货商品明细
        /// 
        /// 
        /// 
        public Dictionary getRepingCnt()
        {
            Dictionary ret = new Dictionary();
            DataTable dt = pickRequestObj.getRepRequestDetailsLessThan(enumOutStockPickStatus.复核完成);//取未完成零货上架的补库商品明细
            List lst = new List();
            foreach (DataRow dr in dt.Rows)
            {
                // lst.Add(new WmsOutPickDetail(dr));
                ret[dr["goodsId"] + WmsConstants.SPLIT + dr["skuId"]] = Convert.ToDecimal(dr["count"].ToString());
            }
            return ret;
        }
        public decimal getRepingCnt(string goodsId, string batch)
        {
            return 0m;
        }
        /// 
        /// 出单一订单
        /// 
        /// 
        /// 
        public bool requestOutStock(WmsOutPickRequest requestOrder)
        {
            //string testOrder = "PK23082800097562";
            // requestOrder = new WmsOutPickRequest(testOrder);
            // if( requestOrder.pickOrderNo!= "PK230903059550")
            //  {
            //    return false;
            // }
          
            logSpec.Debug(string.Format("开始库存定位 {0}, order type {1}, itemcnt {2}", requestOrder.pickOrderNo, (enumOrderType)requestOrder.orderType, requestOrder.outDetails.Count));
            if (requestOrder.outDetails.Count == 0 || requestOrder.outDetails[0].isAllPicked(requestOrder.pickOrderNo))
            {
                if (requestOrder.outStoreType == (int)enumOutStoreType.补货出库)
                {
                    requestOrder.state = (int)enumOutStockRequestStatus.订单完成;
                }
                else
                    requestOrder.state = (int)enumOutStockRequestStatus.分拣完成;
                requestOrder.Update();
                return true;
            }
            logSpec.Debug("1");
            // printStockIn(orderNo);
            requestOrder.operater = this.operId;
            if (requestOrder.ID == 0)
            {
                //  return false;
                // throw new DeiNiuException(requestOrder.pickOrderNo + " 不存在");
                return false;
            }
            if (requestOrder.state == (int)enumOutStockRequestStatus.分拣完成)
            {
                // return false;
                //   throw new DeiNiuException(requestOrder.pickOrderNo + " 已经完成分拣");
                return false;
            }
            else
                if (requestOrder.state == (int)enumOutStockRequestStatus.正在分拣)
            {
                // return false;
                //  throw new DeiNiuException(requestOrder.pickOrderNo + " 正在分拣");
                return false;
            }
            //  stockOutType = requestOrder.orderType == (int)enumOutStoreType.补货出库 ? 
            //      enumStockRecordType.补零出库 : enumStockRecordType.销售出库;
            stockOutType = Util.getStockRecordType(requestOrder.outStoreType);
            requestOrder.state = (int)enumOutStockRequestStatus.待定位;
            // TransactionOptions option = new TransactionOptions();
            //  option.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
            //  using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required, option))
            //  ReadUncommitted    可以在事务期间读取和修改可变数据。  
            //  RepeatableRead       可以在事务期间读取可变数据,但是不可以修改。可以在事务期间添加新数据。  
            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
            {
                //IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted,
                IsolationLevel = System.Transactions.IsolationLevel.Serializable,
                Timeout = new TimeSpan(0, 10, 0)
            }
                 ))
            {
                bool isNoBatchOut = true;
                decimal sumBulkCunt = 0m;
                int bulkTypeCnt = 0;
                int boxcnt = 0;
                foreach (WmsOutPickDetail requestDetail in requestOrder.outDetails)
                {
                    // logSpec.Debug("1");
                    try
                    {
                        /*
                        logSpec.Debug(string.Format(" detail seedsNo :{4}, pickgroup is: {0}, seedsNo is  {1} ,  pickdetail state is  :{2}, goods can seed out: {3} ",
                         requestOrder.pickGroup, requestOrder.seedsPickNo, (enumOutStockDetailStatus)requestDetail.state, requestDetail.goods.canSeedOut, requestDetail.seedsPickNo
                        ));*/
                        if (!string.IsNullOrEmpty(requestDetail.seedsPickNo)
                            || requestDetail.state == (int)enumOutStockDetailStatus.另单播种)
                        {
                            //  logSpec.Debug("2");
                            continue;
                        }
                        else
                         if ((enumOutStockDetailStatus)requestDetail.state >= enumOutStockDetailStatus.等待分拣)
                        {
                            //  logSpec.Debug("3");
                            // logSpec.Debug(string.Format("{0} , {1}", (enumOutStockDetailStatus)requestDetail.state, (enumOutStockDetailStatus)requestDetail.state >= enumOutStockDetailStatus.等待分拣));
                            continue;
                        }
                        // else
                        //   if (requestDetail.state >= (int)enumOutStockDetailStatus.等待分拣)
                        //  {
                        //  logSpec.Debug("4");
                        //   continue;
                        //   }
                        else
                          if (requestDetail.state == (int)enumOutStockDetailStatus.分拣异常)
                        {
                            logOut.Debug("异常商品.." + requestDetail);
                            continue;
                        }
                     
                        //   logSpec.Debug("5");
                        if (requestOrder.pickGroup > 0 &&
                           !string.IsNullOrEmpty(requestOrder.seedsPickNo)
                           && string.IsNullOrEmpty(requestDetail.seedsPickNo)
                           && requestDetail.state != (int)enumOutStockDetailStatus.另单播种
                            
                           ) //剔除播种拣货的明细
                        {
                            //  logSpec.Debug("6");
 
                            if(requestDetail.goodsId== "P01971")
                            {
                                logSpec.Debug(string.Format("requestdetail ID {0}, seedsPickNo {1}, goodsId {2}, goods canzhitong {3},  isZhitongFromStore {4}",
                                                                requestDetail.ID, requestDetail.seedsPickNo, requestDetail.goodsId, requestDetail.goods.canZhitong, requestDetail.goods.isZhitongFromStore
                                                                ));
                                logSpec.Debug("P01971 ...shoud   be here");
                            }
                            
                            if (!requestDetail.goods.canZhitong  //非直通商品,参加集中拣货
                                 || requestDetail.goods.isZhitongFromStore)  //直通商品,但允许在库房有库存的情况下 进行下架分拣
                            {
                                if (requestDetail.goodsId == "P01971")
                                {
                                    logSpec.Debug("P01971 ...shoud not be here");
                                }
                                    if (requestDetail.goods.isSeedsOut()  )  // 支持取总分拣
                                {
                                    //   logSpec.Debug(string.Format(" old state is {0} set detai state to {1} ", (enumOutStockDetailStatus)requestDetail.state, (int)enumOutStockDetailStatus.另单播种));
                                    requestDetail.seedsPickNo = requestOrder.seedsPickNo;
                                    requestDetail.state = (int)enumOutStockDetailStatus.另单播种;
                                    requestDetail.Update();
                                    if (requestDetail.goodsId == "P01971")
                                    {
                                        logSpec.Debug("P01971 ...shoud not be here");
                                }
                                    continue;
                                }
                            }
                        }
                        // logSpec.Debug("3");
                        requestDetail.operater = this.operId;
                        //LogHelper.debug("lWmsOutRequest","requestOutStock begin detail ID:  " + requestDetail.ID);
                        //  logSpec.Debug(string.Format("is rep order ?{0},requestOrder.orderType: {1}  "       , requestOrder.orderType == (int)enumOutOrderType.补货出库,    (enumOutOrderType)//requestOrder.orderType
                        //   ));
                        //蔬菜类总拣后分货时,多下架一部分,分货完毕后,剩余部分自动入库。
                      
                        /*if (requestOrder.outStoreType == (int)enumOutStoreType.配货汇总拣货出库
                            && requestDetail.goods.isWeightOut() && !requestDetail.isWeightScaled)
                        {
                            if (WmsConstants.SEEDS_WEIGHT_OUT_RATE > 0)
                            { 
                                  requestDetail.count = requestDetail.count * (1 + WmsConstants.SEEDS_WEIGHT_OUT_RATE / 100) > requestDetail.goods.stockAvCount? requestDetail.count * (1 + WmsConstants.SEEDS_WEIGHT_OUT_RATE / 100) : requestDetail.goods.stockAvCount;
                                    requestDetail.isWeightScaled = true;
                                    requestDetail.Update();
                                logOut.Debug(string.Format("request detail id {0}, weight seedsout scaled count ",requestDetail.ID));
                                 
                            }
                        }
                        */
                        if (
                             !WmsConstants.OUT_REQUEST_PROCESS_STOCK
                            || goodsOutStock(requestDetail, requestOrder.orderType == (int)enumOrderType.补货出库))
                        {
                            if (requestDetail.state == (int)enumOutStockDetailStatus.另单播种)
                            {
                                requestDetail.Update();
                                continue;
                            }
                            //  if (requestOrder.orderType == (int)enumOutOrderType.补货出库)
                            {
                            }
                            if (requestDetail.state == (int)enumOutStockDetailStatus.完成分拣)
                            {
                                requestDetail.Update();
                                if (requestDetail.isAllPicked(requestDetail.pickOrderNo))
                                {
                                    requestOrder.state = (int)enumOutStockRequestStatus.订单完成;
                                    requestOrder.Update();
                                }
                                continue;
                            }
                            if (!WmsConstants.OUT_REQUEST_PROCESS_STOCK)
                            {
                                logStockOutErpLocation(requestDetail);
                            }
                            requestDetail.state = (int)enumOutStockDetailStatus.等待分拣;
                            boxcnt += requestDetail.boxcnt;
                            if (requestDetail.bulkCount > 0)//有零货出库,处理整不足出零的情况
                            {
                                requestDetail.bulkPickState = (int)enumOutStockPickStatus.已定位;
                                if (requestOrder.bulkPickState != (int)enumOutStockPickStatus.已定位)
                                {
                                    requestOrder.bulkPickState = (int)enumOutStockPickStatus.已定位;
                                    //requestOrder.Update();
                                }
                                bulkTypeCnt++;
                                sumBulkCunt += requestDetail.bulkCount;
                            }
                            else
                            {
                                requestDetail.bulkPickState = (int)enumOutStockPickStatus.无需分拣;
                            }
                            if (requestDetail.batch1Count + requestDetail.batch2Count == 0)
                            {
                                requestDetail.batchPickState = (int)enumOutStockPickStatus.无需分拣;
                            }
                            else
                            {
                                requestDetail.batchPickState = (int)enumOutStockPickStatus.已定位;
                            }
                            requestDetail.Update();
                            isNoBatchOut = isNoBatchOut && (requestDetail.batch1Count + requestDetail.batch2Count == 0);
                            //  LogHelper.debug("lWmsOutRequest", "requestOutStock end detail ID succeed:  " + requestDetail.ID);
                        }
                        else
                        {
                            //  LogHelper.debug("lWmsOutRequest", "requestOutStock end detail ID faild :  " + requestDetail.ID);
                            logOut.Error(requestDetail.description);
                            //    LogHelper.WriteLog(typeof(lWmsOutRequest),requestDetail.description);
                            throw new DeiNiuException(requestDetail.description);
                        }
                    }
                    catch (DeiNiuStockBulkCountException bulkEx)
                    {
                        //LogHelper.WriteLog(typeof(lWmsOutRequest), bulkEx);  
                        //  logSpec.Error(string.Format("pickorder {0} stock bulk exception :{1}", requestOrder.pickOrderNo, bulkEx.Message));
                        /*
                        if (requestOrder.pickGroup > 0 && requestOrder.outStoreType == (int)enumOutStoreType.配货汇总拣货出库) //汇总拣货继续
                        {
                            requestDetail.state = (int)enumOutStockDetailStatus.等待补货;
                            requestDetail.description = bulkEx.Message;
                            requestDetail.Update();
                            requestOrder.description = requestDetail.goods.goodsName + " 库存不足; " + DateTime.Now;
                            continue;
                        }
                        */
                        if (requestDetail.state != (int)enumOutStockDetailStatus.库存不足)
                        {
                            requestDetail.state = (int)enumOutStockDetailStatus.等待补货; //整库部分继续分拣,零库部分等待补货
                        }
                        requestDetail.description = bulkEx.Message;
                        if (requestDetail.batch1Count + requestDetail.batch2Count == 0)
                        {
                            requestDetail.batchPickState = (int)enumOutStockPickStatus.无需分拣;
                        }
                        else
                        {
                            requestDetail.batchPickState = (int)enumOutStockPickStatus.已定位;
                        }
                        requestDetail.Update();
                        requestOrder.state = (int)enumOutStockRequestStatus.等待补货;
                        requestOrder.Update();
                        continue;
                        // return false;
                        // throw bulkEx;
                    }
                    catch (DeiNiuNoStockException nostkEr)
                    {
                        logSpec.Error(nostkEr);
                        if (requestOrder.pickGroup > 0 && requestOrder.outStoreType == (int)enumOutStoreType.配货汇总拣货出库) //汇总拣货继续
                        {
                            requestDetail.state = (int)enumOutStockDetailStatus.库存不足;
                            requestDetail.description = nostkEr.Message;
                            requestDetail.Update();
                            requestOrder.description = requestDetail.goods.goodsName + " 库存不足; " + DateTime.Now;
                            continue;
                        }
                        requestDetail.state = (int)enumOutStockDetailStatus.库存不足;
                        requestDetail.description = nostkEr.Message;
                        requestDetail.Update();
                        if (WmsConstants.OUT_STOCK_LACK_HOLD_ORDER)
                        {
                            logSpec.Error("NO STOCK........整单出库定位回滚。。。。。。。。。。。。。。。。。。。。。。。");
                            //requestOrder.state = (int)enumOutStockRequestStatus.库存不足;
                            requestOrder.state = (int)enumOutStockRequestStatus.待定位;
                            requestOrder.Update();
                            scope.Dispose();
                            return false;
                        }
                        continue;
                    }
                    catch (DeiNiuException er)
                    {
                        logSpec.Error(er);
                        requestDetail.state = (int)enumOutStockDetailStatus.分拣异常; ;
                        requestDetail.description = er.Message;
                        requestDetail.Update();
                        continue;
                        /*
                        scope.Dispose();
                        requestDetail.state = (int)enumOutStockDetailStatus.分拣异常; ;
                        requestDetail.description = er.Message;
                        requestDetail.Update();
                        requestOrder.description = er.Message;
                        requestOrder.state = (int)enumOutStockRequestStatus.订单异常;
                        requestOrder.Update();
                        return false;
                        */
                        // throw er;
                    }
                    catch (NullReferenceException ne)
                    {
                        logSpec.Error(ne);
                        throw new DeiNiuException("internal error :(-");
                    }
                    catch (Exception err)
                    {
                        logSpec.Error(err);
                        throw err;
                        // return false;
                    }
                }
                //如果是补零出库单,入手持捡货表
                if (requestOrder.outStoreType == (int)enumOutStoreType.补货出库)
                {
                    createRepPortData(requestOrder);
                }
                else
                    try
                    {
                        if (requestOrder.state != (int)enumOutStockRequestStatus.等待补货)
                        {
                            requestOrder.state = (int)enumOutStockRequestStatus.定位完成;
                            //TODO: update request order status 4 seedspick
                            esale.updatePickStatus(requestOrder.pickOrderNo, enumOutStockRequestStatus.定位完成);
                            outRequest.updatePickState(requestOrder.pickOrderNo, enumOutStockRequestStatus.定位完成, enumOutStockRequestStatus.待定位);
                        }
                        if (WmsConstants.OUT_BULK_SEEDS_PICK_ON && bulkTypeCnt < WmsConstants.OUT_MAX_SEEDS_GOODSTYPE_CNT && sumBulkCunt < WmsConstants.OUT_MAX_SEEDS_BULK_CNT_SUM)
                        {
                            requestOrder.seedsLabelId = WmsConstants.SEEDS_LABLEID_MARK_VALUE; //适合播种的标记
                        }
                        /*
                        bool isNonePick = true;
                    
                        foreach (WmsOutPickDetail d in requestOrder.outDetails)
                        {
                            isNonePick = isNonePick && (d.state > (int)enumOutStockDetailStatus.等待分拣);
                        }
                        if (isNonePick)
                        {
                            //订单明细全部取总分拣,本单不需要直接拣选
                            requestOrder.state = (int)enumOutStockRequestStatus.订单异常;
                        }
                        */
                        if (isNoBatchOut && sumBulkCunt == 0
                                               && !string.IsNullOrEmpty(requestOrder.seedsPickNo)
                                               && requestOrder.pickGroup > 0
                                               && requestOrder.seedsPort > 0)
                        {
                            bool isAllSeeds = true;
                            foreach (WmsOutPickDetail d in requestOrder.outDetails)
                            {
                                if (string.IsNullOrEmpty(d.seedsPickNo))
                                {
                                    isAllSeeds = false;
                                }
                            }
                            if (isAllSeeds)
                            {
                                //订单明细全部取总分拣,本单不需要直接拣选
                                requestOrder.state = (int)enumOutStockRequestStatus.正在分拣;
                            }
                        }
                        else
                        {
                            if (isNoBatchOut)
                            {
                                requestOrder.batchPickState = (int)enumOutStockPickStatus.无需分拣;
                            }
                            if (sumBulkCunt == 0)
                            {
                                requestOrder.bulkPickState = (int)enumOutStockPickStatus.无需分拣;
                            }
                            requestOrder.bulkCnt = sumBulkCunt;
                            requestOrder.boxCnt = boxcnt;
                        }
                        requestOrder.Update();
                    }
                    catch (Exception e)
                    {
                        logSpec.Error(e);
                        scope.Dispose();
                        return false;
                        //throw e;
                    }
                scope.Complete();
            }
            // LogHelper.debug("lWmsOutRequest", "requestOutStock end :  " + requestOrder.pickOrderNo);
            return true;
        }
        public bool requestOutStock(string orderNo)
        {
            return requestOutStock(new WmsOutPickRequest(orderNo));
        }
        private bool goodsOutStock(WmsOutPickDetail requestDetail, bool isRep = false)
        {
            // logSpec.Debug(" ");
            //  logSpec.Debug(string.Format("开始处理出库定位。。。 isRep {1},  requestDetail.state :{0}", (enumOutStockDetailStatus)requestDetail.state,isRep));
            // if (isRep)
            {
                //   logSpec.Debug("补货单 定位..... requestDetail.state " + (enumOutStockDetailStatus)requestDetail.state);
            }
          
                
            WmsGoods goods = new WmsGoods(requestDetail.goodsId, requestDetail.skuId, requestDetail.batch);
            
            //  if (goods.goodsId!= "P01381")
              {
                     //return false;
              }
            logSpec.Debug(string.Format("开始处理出库定位。。。。out request {0} ,detailId {4}, detail status {5}, goodsId :{1},requestDetail.count :{2}, stock av count :{3} ",
             requestDetail.pickOrderNo, requestDetail.goodsId, requestDetail.count, goods.stockAvCount, requestDetail.ID, requestDetail.state));
            if (goods.bigCount == 0)
            {
                // requestDetail.lackCount = requestDetail.count;
                // requestDetail.count=0;
                requestDetail.description = string.Format("detailId {2}:  {0},{1},非法商品,不存在大包装等基础信息", goods.goodsName, goods.goodsId, requestDetail.ID);
                requestDetail.state = (int)enumOutStockDetailStatus.分拣异常;
                requestDetail.Update();
                //  throw new DeiNiuException(requestDetail.description);
                return false;
            }
            if (goods.canZhitong)
            {
                logSpec.Debug(string.Format(" 直通商品, isZhitongFromStore {0},goods.stockAvCount {1}  ", goods.isZhitongFromStore, goods.stockAvCount));
                //---检测库存,有库存则从库存出,无库存则等待直通播种
                if (!goods.isZhitongFromStore || goods.stockAvCount <= 0)
                {
                    requestDetail.state = (int)enumOutStockDetailStatus.另单播种;
                    logSpec.Debug("直通商品 ,不处理定位 或 无库存");
                    return true;
                }
                /*
                 if (goods.isZhitongFromStore)
                 {
                     if (goods.stockAvCount > 0)
                     {
                     }
                     else
                     {
                         requestDetail.state = (int)enumOutStockDetailStatus.另单播种;
                         logSpec.Debug("直通商品 ,不处理定位 或 无库存");
                         return true;
                     }
                 }
                 else
                 {
                     requestDetail.state = (int)enumOutStockDetailStatus.另单播种;
                     logSpec.Debug("直通商品 ,不处理定位 或 无库存");
                     return true;
                 }*/
            }
            decimal batch2bulk = 0m;
            decimal bulkCnt = requestDetail.bulkCount;
            decimal batch1Cnt = requestDetail.batch1Count;
            decimal batch2Cnt = requestDetail.batch2Count;
            if (requestDetail.state == (int)enumOutStockDetailStatus.等待补货) //整库已定位并生成拣货任务(TODO: 是否开始分拣未定?)
            {
                logSpec.Debug("订单明细等待补货。。。。");
                //  bulkCnt = reductStockCnt(goods, bulkCnt, enumWhLocVol.零库, requestDetail);// 出零货 
                if (
                    goods.stockAvCount < requestDetail.count//由缺零到缺货
                    && goods.stockSumCountOuting == 0 //无补货占用
                    )
                {
                    if (goods.isZhitong)
                    {
                        requestDetail.state = (int)enumOutStockDetailStatus.另单播种;
                        return true;
                    }
                    requestDetail.state = (int)enumOutStockDetailStatus.库存不足;
                    throw new DeiNiuStockBulkCountException(); ;  //等待下次重新定位
                } else
                if (bulkCnt > goods.stockBulkAvCount && 1==2) //零库不足,需要补零库; 整库零出的零不够需补货的情况应该不存在
                {
                    // bulkCnt = Math.Ceiling(bulkCnt / goods.bigCount) * goods.bigCount;
                    string msg = string.Format("goods sku {0},required bulkcount {1},stock bulk cnt {2} ", goods.goodsName, bulkCnt, goods.stockBulkAvCount);
                    //logSpec.Debug(msg);
                    logSpec.Debug(msg);
                    /*
                    WmsStockRep wmsStockRep = new WmsStockRep(goods.goodsId,requestDetail.skuId);
                    if(wmsStockRep.toRepCnt - wmsStockRep.lackCount   0)
                    {
                        requestDetail.batch2Count = goods.stockBatch2Count - goods.stockBatch2CountOuting;
                        requestDetail.batch1Count += b2cnt;
                    }
                    decimal b1cnt = requestDetail.batch1Count - (goods.stockBatch1Count - goods.stockBatch1CountOuting);
                    if (!isRep && b1cnt > 0)
                    {
                        if (goods.stockBatch2Count - goods.stockBatch2CountOuting - requestDetail.batch2Count > b1cnt) //batch2 足够
                        {
                            requestDetail.batch2Count += b1cnt;
                            requestDetail.batch1Count = goods.stockBatch1Count - goods.stockBatch1CountOuting;
                        }
                        else
                        {
                            requestDetail.batch2Count = goods.stockBatch2Count - goods.stockBatch2CountOuting;
                            requestDetail.batch1Count = (goods.stockBatch1Count - goods.stockBatch1CountOuting);
                        }
                    }
                    requestDetail.bulkCount = requestDetail.count - requestDetail.batch1Count - requestDetail.batch2Count;
                }
              //  if (requestDetail.goods.stockBatchAvCount == 0)
               if (requestDetail.goods.stockBatchAvCount <= 0)
                    {
                    requestDetail.bulkCount = requestDetail.count;
                    requestDetail.batch1Count = 0;
                    requestDetail.batch2Count = 0;
                }
                else
                {
                   
                    log.Error(" 有整库库存!!!!!!!!!!!!!???????: " + requestDetail.goods);
                    //没有整库 辣得叫
                      requestDetail.bulkCount = requestDetail.count;
                      requestDetail.batch1Count = 0;
                      requestDetail.batch2Count = 0;
                }
             
                bulkCnt = requestDetail.bulkCount;
                batch1Cnt = requestDetail.batch1Count;
                batch2Cnt = requestDetail.batch2Count;
                //  decimal batch3Cnt = requestDetail.bat;
                 logSpec.Debug(string.Format("{3} 出库需求明细: bulkCnt:{0} , batch1Cnt:{1} , batch2Cnt:{2} ", bulkCnt, batch1Cnt, batch2Cnt, goods.goodsId));
             
                if (goods.stockAvCount < requestDetail.count // 库存不足
                  //  && !goods.isZhitong
                    )
                {
                    //  logSpec.Debug(string.Format("goods stockSumCount: {0},goods countOuting :{1}, required count:{2}", goods.stockSumCount, countOuting, requestDetail.count));
                        logSpec.Debug(string.Format("库存不足: 可用总库存:{0}, 需求库存{1}", goods.stockAvCount, requestDetail.count));
                    if (isRep)
                    {
                        requestDetail.description = "应补" + requestDetail.count + ",实际补 " + (goods.stockSumCount - countOuting);
                        /*
                        WmsStockRep wsr = new WmsStockRep(requestDetail.goodsId, requestDetail.skuId);
                        wsr.toRepCnt -= requestDetail.count -goods.stockAvCount;
                        wsr.Update();
                        */
                        if (goods.stockAvCount <= 0)
                        {
                            //requestDetail.Delete();
                            requestDetail.state = (int)enumOutStockDetailStatus.完成分拣;
                            requestDetail.Update();
                            return true;
                        }
                        decimal diff = requestDetail.count - goods.stockAvCount;
                        requestDetail.count = goods.stockAvCount;
                        /**
                         * 
                         requestDetail.count = (goods.stockSumCount - countOuting) / goods.bigCount * goods.bigCount;
                         logSpec.Debug(string.Format("补货订单。。" + requestDetail.description));
                         if (requestDetail.count < goods.bigCount)
                         {
                             logSpec.Debug(string.Format("无整库库存,删除补货明细。。。"));
                             //requestDetail.count = 0;
                             //requestDetail.Delete();
                             // requestDetail.Update();
                             requestDetail.count = goods.bigCount;
                             return true;
                         }*/
                        WmsStockRep stk = new WmsStockRep(requestDetail.goodsId, requestDetail.skuId);
                        if (stk.ID > 0)
                        {
                            stk.toRepCnt -= diff;
                            stk.Update();
                        }
                        requestDetail.batch1Count = requestDetail.count;
                        requestDetail.batch2Count = 0;
                        requestDetail.Update();
                        batch1Cnt = requestDetail.batch1Count;
                        batch2Cnt = 0;
                    }
                    else
                    {
                        goods = new WmsGoods(requestDetail.goodsId, requestDetail.skuId, requestDetail.batch);
                        //   logSpec.Debug(string.Format("库存不足时,全订单暂停出库 ?{0}", WmsConstants.OUT_STOCK_LACK_HOLD_ORDER));
                        if (!WmsConstants.OUT_STOCK_LACK_HOLD_ORDER)
                        {
                           /* WmsStockLack sl = new WmsStockLack();
                            sl.getByPickOrder(requestDetail.pickOrderNo, requestDetail.goodsId, requestDetail.skuId);
                            if (sl.ID == 0)
                            {
                                sl.whType = requestDetail.whtype;
                                sl.goodsId = goods.goodsId;
                                sl.pickOrderNo = requestDetail.pickOrderNo;
                                sl.productDate = requestDetail.productDate;
                                sl.validDate = requestDetail.validDate;
                                sl.skuCode = requestDetail.skuCode;
                                sl.skuId = requestDetail.skuId;
                                sl.lackCount = requestDetail.count - (goods.stockSumCount - countOuting);
                                sl.type = 1;
                                sl.Add();
                            }*/
                            if (WmsConstants.OUT_STOCK_LACK_VIR_OUT) // 库存不足则从虚拟库借出
                            {                               
                                    decimal tmpCount = requestDetail.count;
                                    decimal avCnt = goods.stockAvCount > goods.minOperateCount ? goods.stockAvCount : 0;
                                    requestDetail.lackCount = requestDetail.count - avCnt;
                                if (!WmsConstants.OUT_STOCK_LACK_VIR_OUT_AUTO)
                                {
                                    requestDetail.lackCount = requestDetail.lackCount > 0 ? requestDetail.lackCount : 0;
                                    requestDetail.count = avCnt;
                                    requestDetail.boxcnt = (int)(requestDetail.count / goods.bigCount);
                                    requestDetail.bulkCount = requestDetail.count % goods.bigCount;
                                    requestDetail.batch1Count = requestDetail.count - requestDetail.bulkCount;
                                    requestDetail.batch2Count = 0;
                                    bulkCnt = requestDetail.bulkCount;
                                    batch1Cnt = requestDetail.batch1Count;
                                    batch2Cnt = requestDetail.batch2Count;
                                    requestDetail.state = (int)enumOutStockDetailStatus.等待分拣;
                                    //  requestDetail.count += requestDetail.lackCount;
                                    requestDetail.count = tmpCount;
                                }
                                requestDetail.Update();
                                decimal lackCnt = requestDetail.lackCount;
                                logSpec.Debug(" 1 库存不足,出虚拟库......数量 " + lackCnt);
                                if (!goods.isWeightOut() && lackCnt % goods.minOperateCount > 0)  //借货取整件
                                {
                                    logSpec.Debug("库存 有非整件数量, 余数 " + lackCnt % goods.minOperateCount);
                                    lackCnt = ((int)(lackCnt/goods.minOperateCount)) *   goods.minOperateCount + goods.minOperateCount;
                                    logSpec.Debug("2 库存不足,出虚拟库......数量 " + lackCnt);
                                }
                                WmsLocation loc = new WmsLocation(); 
                               
                                loc = loc.getVirLocations(requestDetail.goods.part); 
 
                                logSpec.Debug(" 出周转 虚拟库库位 。。 " + loc.locationId);
                                WmsStock stkVir = new WmsStock(loc.locationId, requestDetail.skuId, requestDetail.goodsId);
                                /*
                                DataTable dt= stk.getStockLocation(loc.locationId);
                                foreach(DataRow dr in dt.Rows)
                                {
                                    WmsStock tmp = new WmsStock(dr);
                                   if( tmp.goodsId == requestDetail.goods.goodsId)
                                    {
                                        stk= new WmsStock(dr);
                                        break;
                                    }
                                   
                                } 
                                */
                                stkVir.locationId = loc.locationId;
                            
                                stkVir.skuId = requestDetail.skuId;
                                stkVir.skuCode = String.IsNullOrEmpty(stkVir.skuCode) ? requestDetail.skuCode : stkVir.skuCode;
                                stkVir.productDate = String.IsNullOrEmpty(stkVir.productDate) ? stkVir.getDateTime() : stkVir.productDate;
                                stkVir.validDate = String.IsNullOrEmpty(stkVir.validDate) ? stkVir.productDate : stkVir.validDate;
                                stkVir.batch = String.IsNullOrEmpty(stkVir.batch) ? stkVir.productDate : stkVir.batch;
                                 
                                //缺货,拣货任务从虚拟库位出库,还是从真实库存出库
                                if (WmsConstants.OUT_STOCK_LACK_VIR_OUT_AUTO)
                                {
                                    //从虚拟库存借库存,在实体库位出库; 从零库出任务
                                    logSpec.Debug(" goods av bulk cnt befor virtual operation : " + goods.stockBulkAvCount +" ,lackcout " + lackCnt);
                                    bool isHit = false;
                                    foreach (WmsStock st in goods.AllStocks)
                                    {
                                        //  logOut.Debug("to update virtual count for stk " + st.ToString());
                                        if (st.getAvCount() < 0)
                                        {
                                            logSpec.Debug(" 避开负库存。。。。 " + st);
                                            continue;
                                        }
                                        if (st.location.volType == (int)enumWhLocVol.零库)
                                        {
                                            st.virtialCount += lackCnt;
                                            // st.count += lackCnt;
                                           // st.countOuting -= lackCnt;
                                            isHit = true;
                                          //  st.preLockOut = 88888;
                                            st.updateCountOut();
                                            logSpec.Debug("updated  virtual count for stk " + st.ToString());
                                            break;
                                        }
                                    }
                                    logSpec.Debug("is hit ? " + isHit);
                                    if (!isHit)
                                    {
                                        // WmsLocation bulkLoc = loc.getLocation(enumWhLocVol.零库, goods.part, goods.ABC);
                                        List locs =  new List();
                                        try
                                        {
                                            locs = loc.getNewLocations(lackCnt, goods, enumWhLocVol.零库);
                                            if (locs.Count == 0)
                                            {
                                                locs.Add(loc.getLocation(enumWhLocVol.零库, goods.part, goods.ABC));
                                            }
                                        }
                                        catch (Exception er)
                                        {
                                        }
                                        logSpec.Debug(string.Format("  get new locs cnt {0}  ", locs.Count));
                                        if (locs.Count == 0)
                                        {
                                            locs.Add(loc.getLocation(enumWhLocVol.零库, goods.part, goods.ABC));
                                        }
                                        if (locs.Count == 0)
                                        {
                                            locs.Add(new WmsLocation("11.01.01.11"));
                                        }
                                    
                                        foreach (WmsLocation nloc in locs)
                                        {
                                          //  WmsStock newstk = new WmsStock(nloc.locationId, requestDetail.skuId, requestDetail.goodsId);
                                            WmsStock newstk = new WmsStock();
                                            newstk.virtialCount += lackCnt;
                                            if (newstk.ID == 0 || newstk.getAvCount() < 0)
                                            {
                                                newstk.locationId = nloc.locationId;
                                                newstk.skuId = requestDetail.skuId;
                                                newstk.goodsId = requestDetail.goods.goodsId;
                                                newstk.skuCode = requestDetail.skuCode;
                                                newstk.productDate = string.IsNullOrEmpty(requestDetail.productDate) ? getDateStr(DateTime.Now.AddDays(-1000)) : requestDetail.productDate;//  
                                                newstk.validDate = string.IsNullOrEmpty(requestDetail.validDate) ? getDateStr(DateTime.Now.AddDays(1000)) : requestDetail.validDate;
                                                newstk.batch = string.IsNullOrEmpty(requestDetail.batch) ? newstk.productDate : requestDetail.batch;
                                                newstk.Add();
                                            }
                                            else
                                            {
                                                newstk.updateCountOut();
                                            }
                                         //   logOut.Debug("to create new  stk " + newstk.ToString());
                                        } 
                                        //   logOut.Debug("to create new  virtual   stk " + newstk.ToString());
                                    }
                                       //重新加载库存信息
                                    goods = new WmsGoods(requestDetail.goodsId, requestDetail.skuId, requestDetail.batch);
                                    logOut.Debug(" goods av bulk cnt after virtual operation : " + goods.stockBulkAvCount);
                                    stkVir.countOuting += lackCnt;
                                }
                                else
                                {//从虚拟库库位出库
                                    stkVir.countOuting += lackCnt;
                                  
                                }
                                if (stkVir.ID == 0
                                    || string.IsNullOrEmpty(stkVir.goodsId)
                                    || stkVir.goodsId != requestDetail.goodsId) //商品没有虚拟记录
                                {
                                    stkVir.goodsId = requestDetail.goods.goodsId;
                                    stkVir.Add();
                                     logSpec.Debug("新增虚拟库存 " + stkVir);
                                }
                                else
                                {
                                    stkVir.Update();
                                     logSpec.Debug("更新 虚拟库存 " + stkVir);
                                }
                                if (!WmsConstants.OUT_STOCK_LACK_VIR_OUT_AUTO)
                                {
                                    logStockOut(requestDetail, requestDetail.goods, stkVir, lackCnt);
                                    if (requestDetail.count == requestDetail.lackCount) //订单明细缺货
                                    {
                                        return true;
                                    }
                                }
                                  
                            }
                        }
                        else
                        {
                            string msg = string.Format("rquest {3}, goods:{4}, sku {0},required count {1},stock available cnt {2} ", requestDetail.skuId,
                                requestDetail.count, goods.stockSumCount - countOuting, requestDetail.pickOrderNo, goods.goodsId);
                            logSpec.Error(msg);
                            throw new DeiNiuNoStockException(msg);
                        }
                    }
                }
                if (!isRep && bulkCnt > 0 && bulkCnt > goods.stockBulkAvCount /*requestDetail.getGoodsStockCnt(enumWhLocVol.零库)*/)// pd.goods.stockBulkCount)
                {
                    if (requestDetail.whtype == (int)enumWhType.合格库)
                    {
                        // this.createGoodsRepOrder(goods, requestDetail.skuId, requestDetail.skuCode, bulkCnt); //TODO: check if the rep has been created for it.
                    }
                    string msg = string.Format("goods :{3}, sku {0},required bulkcount {1},stock bulk cnt: {2} ", requestDetail.skuId, bulkCnt, goods.stockBulkAvCount, goods.goodsName);
                    logSpec.Debug(msg);
                    //throw new DeiNiuStockBulkCountException(msg);
                }
                if (batch1Cnt + batch2Cnt >
                    goods.stockBatch1Count + goods.stockBatch2Count + goods.stockBatch3Count
                   - goods.stockBatch1CountOuting - goods.stockBatch2CountOuting - goods.stockBatch3CountOuting
                    )
                {
                    string msg = string.Format("整库存库存不足,{0} ,detailId{6},skuId{5}, skuCode {4}, \n {1}  整货需 {2}, 实际整库存 {3} "
                        , requestDetail.pickOrderNo, goods.goodsName
                        , batch1Cnt + batch2Cnt, goods.stockBatch1Count + goods.stockBatch2Count
                        , requestDetail.skuCode, requestDetail.skuId, requestDetail.ID);
                    logSpec.Debug(msg);
                    //  throw new DeiNiuNoStockException(msg);
                }
                //  logSpec.Debug("");
                //  logSpec.Debug(string.Format("{4},开始定位扣库存 : bulkCnt:{0}, batch1Cnt:{1},batch2Cnt{2}, 是否严格按效期出库 ?{3}",
                //    bulkCnt, batch1Cnt, batch2Cnt, WmsConstants.OUT_STOCK_BATCH_FIFO, goods.goodsId));
                #region oldLog, can work.
                /*
                if (batch2Cnt > 0)
                {
                    logSpec.Debug("开始出中整..>>.");
                    batch2Cnt = reductStockCnt(goods, batch2Cnt, enumWhLocVol.中整, requestDetail); //出中整
                    if (batch2Cnt > 0)
                    {
                        requestDetail.batch2Count -= batch2Cnt;
                    }
                    logSpec.Debug("中整不足,出大整");
                    batch2Cnt = reductStockCnt(goods, batch2Cnt, enumWhLocVol.大整, requestDetail);//中整不足,出大整
                    tmp = batch2Cnt;
                    batch2Cnt = reductStockCnt(goods, batch2Cnt, enumWhLocVol.小整, requestDetail);//出小整
                    requestDetail.batch1Count += tmp - batch2Cnt;
                    if (!isRep)
                    {
                        tmp = batch2Cnt;
                        batch2Cnt = reductStockCnt(goods, batch2Cnt, enumWhLocVol.零库, requestDetail);//出零货  
                        requestDetail.bulkCount += tmp - batch2Cnt;
                    }
                    logSpec.Debug(" 出中整...结束...<<");
                }
                if (batch1Cnt > 0)
                {
                    logSpec.Debug("开始出小整..>>.");
                    batch1Cnt = reductStockCnt(goods, batch1Cnt, enumWhLocVol.小整, requestDetail);//出小整
                    if (batch1Cnt > 0)
                    {
                        requestDetail.batch1Count -= batch1Cnt;
                    }
                    tmp = batch1Cnt;
                    logSpec.Debug("小整不足,出中整");
                    batch1Cnt = reductStockCnt(goods, batch1Cnt, enumWhLocVol.中整, requestDetail);//小整不足,出中整
                    requestDetail.batch2Count += tmp - batch1Cnt;
                    tmp = batch1Cnt;
                    logSpec.Debug("中整不足,出大整");
                    batch1Cnt = reductStockCnt(goods, batch1Cnt, enumWhLocVol.大整, requestDetail);//中整不足,出大整
                    tmp = batch1Cnt;
                    if (!isRep)
                    {
                        logSpec.Debug("整不足,出零货");
                        batch1Cnt = reductStockCnt(goods, batch1Cnt, enumWhLocVol.零库, requestDetail);//整不足,出零货 //TODO: HOW TO PROCESS request bulkcount ,batch count?
                        requestDetail.bulkCount += tmp - batch1Cnt;
                    }
                    logSpec.Debug(" 出小整...结束...<<");
                }
              */
                #endregion
            }
            List stks = new List();
            // 
            decimal tmpBatch1Cnt = 0m, tmpBatch2Cnt = 0m, tmpBulkCnt = 0m, tmpCnt = 0m;
            if (!WmsConstants.OUT_STOCK_BATCH_FIFO)//不分货区,全库按近效期优先 ,取待处理货位,所取的货位数量可以满足分配,可能出现零库因为效期问题 补零、整库从零出的情况
            {
                decimal targetCnt = requestDetail.state == (int)enumOutStockDetailStatus.等待补货 ? bulkCnt : requestDetail.count;
                foreach (WmsStock st in goods.stocks)
                {
                    // logSpec.Debug(string.Format("{0},   avcnt {1}, voltype {2}  ", st.skuCode, st.getAvCount(), st.location.volType));
                    if (tmpCnt >= targetCnt)
                    {
                        break;
                    }
                    tmpCnt += st.getAvCount(); ;
                    stks.Add(st);
                }
            }
            else  //分货区,各个分区按近效期优先 ,取待处理货位; 结果可能出远效期商品,按分区可能不满足分配需求,可能需要补充
            {
                logSpec.Debug("goods.stocks count : " + goods.stocks.Count);
                foreach (WmsStock st in goods.stocks)
                {
                    logSpec.Debug(string.Format("{0},   avcnt {1}, voltype {2}  ", st.skuCode, st.getAvCount(), st.location.volType));
                    if (st.location.volType < (int)enumWhLocVol.小整)//零库
                    {
                        if (tmpBulkCnt < bulkCnt) //满足零货需求
                        {
                                                       
                            tmpBulkCnt += st.getAvCount();  
                            stks.Add(st);
                        }
                    }
                    else if (st.location.volType == (int)enumWhLocVol.小整)
                    {
                        if (tmpBatch1Cnt < batch1Cnt)
                        {
                            tmpBatch1Cnt += st.getAvCount(); ;
                            stks.Add(st);
                        }
                    }
                    else if (st.location.volType == (int)enumWhLocVol.中整)
                    {
                        if (tmpBatch2Cnt < batch2Cnt)
                        {
                            tmpBatch2Cnt += st.getAvCount();
                            stks.Add(st);
                        }
                    }
                    if (!goods.isWeightOut() && goods.minOperateCount > 0)
                    {
                        tmpBulkCnt -= tmpBulkCnt % goods.minOperateCount;
                        tmpBatch1Cnt -= tmpBatch1Cnt % goods.minOperateCount;
                        tmpBatch2Cnt -= tmpBatch2Cnt % goods.minOperateCount;  
                    }
                    if (tmpBulkCnt >= bulkCnt && tmpBatch1Cnt >= batch1Cnt && tmpBatch2Cnt >= batch2Cnt)
                    {
                        break;
                    }
                }
                if (tmpBatch1Cnt < batch1Cnt || tmpBatch2Cnt < batch2Cnt)
                {
                    List tmpStks = new List();
                    bool ishit = false;
                    if (batch1Cnt > 0)
                    {
                        foreach (WmsStock st in goods.stocks) // copy stocklist
                        {
                            foreach (WmsStock st2 in stks)
                            {
                                if (st.ID == st2.ID)
                                {
                                    ishit = true;
                                    break;
                                }
                            }
                            if (ishit)
                            {
                                ishit = false;
                            }
                            else
                            {
                                tmpStks.Add(st);
                            }
                        }
                        logSpec.Debug(string.Format("开始处理 batch1"));
                        tmpBatch1Cnt = 0;
                        foreach (WmsStock st in tmpStks)
                        {
                            if (st.location.volType == (int)enumWhLocVol.中整)
                            {
                                if (tmpBatch1Cnt < batch1Cnt)
                                {
                                    tmpBatch1Cnt += st.getAvCount();
                                    stks.Add(st);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                        if (tmpBatch1Cnt < batch1Cnt)
                        {
                            foreach (WmsStock st in tmpStks)
                            {
                                if (st.location.volType == (int)enumWhLocVol.大整)
                                {
                                    if (tmpBatch1Cnt < batch1Cnt)
                                    {
                                        tmpBatch1Cnt += st.getAvCount();
                                        stks.Add(st);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                        if (!isRep)
                            if (tmpBatch1Cnt < batch1Cnt)
                            {
                                foreach (WmsStock st in tmpStks)
                                {
                                    if (st.location.volType == (int)enumWhLocVol.零库)
                                    {
                                        if (tmpBatch1Cnt < batch1Cnt)
                                        {
                                            tmpBatch1Cnt += st.getAvCount();
                                            stks.Add(st);
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                }
                            }
                        /*
                        foreach (WmsStock st in stks)
                        {
                            logSpec.Debug(string.Format("{0}, avCount{1}, volType {2} ", st.skuCode, st.getAvCount(), st.location.volType));
                        }*/
                    }
                    if (batch2Cnt > 0)
                    {
                        logSpec.Debug(string.Format("开始处理 batch2"));
                        tmpStks.Clear();
                        foreach (WmsStock st in goods.stocks) // copy stocklist
                        {
                            foreach (WmsStock st2 in stks)
                            {
                                if (st.ID == st2.ID)
                                {
                                    ishit = true;
                                    break;
                                }
                            }
                            if (ishit)
                            {
                                ishit = false;
                            }
                            else
                            {
                                tmpStks.Add(st);
                            }
                        }
                        tmpBatch2Cnt = 0;
                        foreach (WmsStock st in tmpStks)
                        {
                            if (st.location.volType == (int)enumWhLocVol.大整)
                            {
                                if (tmpBatch2Cnt < batch2Cnt)
                                {
                                    tmpBatch2Cnt += st.getAvCount();
                                    stks.Add(st);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                        if (tmpBatch2Cnt < batch2Cnt)
                        {
                            foreach (WmsStock st in tmpStks)
                            {
                                if (st.location.volType == (int)enumWhLocVol.小整)
                                {
                                    if (tmpBatch2Cnt < batch2Cnt)
                                    {
                                        tmpBatch2Cnt += st.getAvCount();
                                        stks.Add(st);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                        if (!isRep)
                            if (tmpBatch2Cnt < batch2Cnt)
                            {
                                foreach (WmsStock st in tmpStks)
                                {
                                    if (st.location.volType == (int)enumWhLocVol.零库)
                                    {
                                        if (tmpBatch2Cnt < batch2Cnt)
                                        {
                                            tmpBatch1Cnt += st.getAvCount();
                                            stks.Add(st);
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                }
                            }
                    }
                }
            }
            // 开始按货位分区类型处理定位
            {
                goods.tmpStocks = stks;
                logSpec.Debug("tmp stklst cnt " + goods.tmpStocks.Count);
                if (batch2Cnt > 0)
                {
                    logSpec.Debug(string.Format("{0}", "开始处理  中整。。。。。"));
                    batch2Cnt = reductStockCnt(goods, batch2Cnt, enumWhLocVol.中整, requestDetail);
                    logSpec.Debug(string.Format(" 中整 剩余数量 {0}", batch2Cnt));
                    batch2Cnt = reductStockCnt(goods, batch2Cnt, enumWhLocVol.大整, requestDetail);
                    logSpec.Debug(string.Format("大整 剩余数量 {0}", batch2Cnt));
                    batch2Cnt = reductStockCnt(goods, batch2Cnt, enumWhLocVol.小整, requestDetail); batch2bulk += batch2Cnt;
                    logSpec.Debug(string.Format("小整 剩余数量 {0}", batch2Cnt));
                    if (!isRep)
                        batch2Cnt = reductStockCnt(goods, batch2Cnt, enumWhLocVol.零库, requestDetail);
                    logSpec.Debug(string.Format("零库 剩余数量 {0}", batch2Cnt));
                    /*  foreach (WmsStock st in stks)
                      {
                          if (st.location.volType == 2)
                              logSpec.Debug(string.Format("{0}, avCount{1}, volType {2} ", st.skuCode, st.getAvCount(), st.location.volType));
                      }*/
                }
                /*
                foreach (WmsStock st in stks)
                {
                    logSpec.Debug(string.Format("{0}, avCount{1}, volType {2} ", st.skuCode, st.getAvCount(), st.location.volType));
                }*/
                if (batch1Cnt > 0)
                {
                    logSpec.Debug(string.Format("{0}", "开始处理  小整。。。。。"));
                    batch1Cnt = reductStockCnt(goods, batch1Cnt, enumWhLocVol.小整, requestDetail);
                    batch1Cnt = reductStockCnt(goods, batch1Cnt, enumWhLocVol.中整, requestDetail);
                    batch1Cnt = reductStockCnt(goods, batch1Cnt, enumWhLocVol.大整, requestDetail); batch2bulk += batch1Cnt;
                    if (!isRep)
                        batch1Cnt = reductStockCnt(goods, batch1Cnt, enumWhLocVol.零库, requestDetail);
                    /*
                    foreach (WmsStock st in stks)
                    {
                        //  if (st.location.volType == 1)
                        logSpec.Debug(string.Format("{0}, avCount{1}, volType {2} ", st.skuCode, st.getAvCount(), st.location.volType));
                    }
                     */
                }
                if (bulkCnt > 0)
                {
                    goods.getStockInfo(goods.goodsId);
                    logSpec.Debug(string.Format("开始处理  零库。。。。。bulkCnt :{0}, goods.stockBulkAvCount {1}, goods.tmpStocks count {2} ", bulkCnt, goods.stockBulkAvCount, goods.tmpStocks.Count));
                    /*
                    foreach (WmsStock st in goods.tmpStocks)
                    {
                         logSpec.Debug(string.Format("  {0}, avCount{1}, volType {2} ", st.skuCode, st.getAvCount(), st.location.volType));
                    }
                    */
                    if (bulkCnt <= goods.stockBulkAvCount)
                    {
                        bulkCnt = reductStockCnt(goods, bulkCnt, enumWhLocVol.零库, requestDetail);
                        /*
                        foreach (WmsStock st in stks)
                        {
                            logSpec.Debug(string.Format(" {0}, avCount{1}, volType {2} ", st.skuCode, st.getAvCount(), st.location.volType));
                        }*/
                    }
                }
                logSpec.Debug(string.Format(" {3}  定位后...数量 : bulkCnt:{0}, batch1Cnt:{1},batch2Cnt{2} ", bulkCnt, batch1Cnt, batch2Cnt, goods.goodsId));
                //  logSpec.Debug(string.Format(" {3}  定位后...数量 : bulkCnt:{0}, batch1Cnt:{1},batch2Cnt{2} ", bulkCnt, batch1Cnt, batch2Cnt, goods.goodsId));
                tmpCnt = batch1Cnt + batch2Cnt + bulkCnt;
                if (tmpCnt == 0) //库存正常,不需补零、按库位类型出
                {
                    logSpec.Debug("定位结束");
                    return true;
                }
                else
                {
                    logSpec.Debug("!!!! 需要补零或库存不足或不满足最小分拣数量");
                }
                if (bulkCnt > 0 &&1==2)
                {
                    string msg = string.Format("goods {3}, skuId {0},required bulkcount {1},stock bulk cnt {2} ", requestDetail.skuId, bulkCnt, goods.stockBulkAvCount, goods.goodsId);
                    logSpec.Debug(msg);
                   
                    requestDetail.state = (int)enumOutStockDetailStatus.等待补货;
                  this.reportBulkLack(goods, requestDetail.skuId, requestDetail.skuCode, bulkCnt);
                   throw new DeiNiuStockBulkCountException(msg);
                     
                }
            }
            logSpec.Debug(string.Format("整库处理完毕,未处理数量: bulkCnt: {0} , batch1Cnt: {1} ,batch2Cnt: {2}", bulkCnt, batch1Cnt, batch2Cnt));
            if (batch2Cnt > 0 || batch1Cnt > 0) //货物不足,异常,
            {
                if (isRep)
                {
                    //  logSpec.Debug("补货定位结束");
                    if (batch1Cnt + batch2Cnt == requestDetail.count) // no stock get
                    {
                        logSpec.Debug(" 整货不足,补货缺货。。。关闭拣货任务");
                        requestDetail.state = (int)enumOutStockDetailStatus.完成分拣;
                    }
                    return true;
                }
                if (goods.isZhitong)
                {
                    logOut.Debug("goods is zhitong!!!");
                    requestDetail.state = (int)enumOutStockDetailStatus.另单播种;
                }
                else if (!isRep)
                {
                    throw new DeiNiuNoStockException("库存异常");
                }
            }
            decimal batchCont = batch2Cnt + batch1Cnt - batch2bulk;// +requestDetail.batch2Count;
            int boxcnt = (int)Math.Ceiling(batchCont / requestDetail.goods.bigCount);
            requestDetail.boxcnt = boxcnt;
            requestDetail.pcs = (int)Math.Ceiling((requestDetail.count - requestDetail.lackCount) / goods.minOperateCount);
            /*
             * 在开始已判断是否零库缺货
             * 整库不足出零库的情况,在总货量足够的情况下,不会出现零库不足的问题
             if (bulkCnt > 0 && bulkCnt > requestDetail.getGoodsStockCnt(enumWhLocVol.零库))// pd.goods.stockBulkCount)
             {
                 throw new DeiNiuStockBulkCountException();
             }
             */
            logSpec.Debug("定位结束");
            return true; ;
        }
        private decimal reductStockCnt(WmsGoods goods, decimal targetCnt, enumWhLocVol locVol, WmsOutPickDetail requestDetail, bool useTemp = true)
        {
            List stks = useTemp ? goods.tmpStocks : goods.stocks;
              logSpec.Debug(string.Format(" {2} 开始定位 {0},待定位数量 {1}", locVol, targetCnt,goods.goodsName));
            if (locVol == enumWhLocVol.零库) //零库出库单笔捡货不能超过9999  //TODO: to test the logic
            {
                decimal tmpCnt = 0;
               // while (stks.Count > 0 && targetCnt > 0)
                {
                      logSpec.Debug(string.Format("targetcnt {0} ",   targetCnt));
                    if (WmsConstants.OUT_LIGHT_ENABLE && targetCnt/goods.minOperateCount > WmsConstants.MAX_PICK_CNT_BULK)
                    {
                        tmpCnt = WmsConstants.MAX_PICK_CNT_BULK;
                    }
                    else
                    {
                        tmpCnt = targetCnt;
                    }
                    targetCnt = targetCnt - tmpCnt;
                    decimal decnt = 0;
                    int i = 0;
                    foreach (WmsStock st in stks)
                    {
                           logSpec.Debug(string.Format("零库。。。tmpCnt {0} ,location volType {1}, av cnt {2}", tmpCnt, st.location.volType, st.getAvCount()));
                        if (tmpCnt == 0)
                        {
                            break;
                        }
                        if (st.location.volType == (int)locVol)
                        {
                            decimal cnt = st.getAvCount();
                            decimal reductCnt = cnt >= tmpCnt ? tmpCnt : cnt;
                          
                            /*if ( goods.minOperateCount > 1 && !goods.isWeightOut()  )
                            {
                                reductCnt = ((int)(reductCnt/goods.minOperateCount)) * goods.minOperateCount;
                            }
                            */
                            if (  !goods.isWeightOut() && goods.minOperateCount>0)
                            {
                                reductCnt -=   reductCnt % goods.minOperateCount  ;
                            }
                            if (reductCnt <= 0)
                            {
                                continue;
                            }
                            i++;
                            if (WmsConstants.OUT_STOCK_DEDUCT)
                            {
                                st.countOuting += reductCnt;
                            }
                            else
                            {
                                st.countOut += reductCnt;
                            }
                            st.operater = this.operId;
                            // st.Update();
                            st.updateCountOut();
                            logStockOut(requestDetail, goods, st, reductCnt); 
                            
                         
                            
                            tmpCnt -= reductCnt;
                            decnt += reductCnt;
                        }
                    }
                    //   logSpec.Debug(string.Format("tmpCnt {0} ,decnt {1} ", tmpCnt,decnt));
                    if (i > 0 && decnt <= 0 && tmpCnt > 0) //零库不足
                    {
                        logSpec.Debug("零库扣库存异常");
                        // logSpec.Debug("零库扣库存异常");
                      //  throw new DeiNiuStockBulkCountException();
                    }
                    targetCnt += tmpCnt;
                }
            }
            else
                foreach (WmsStock st in stks)
                {
                    // logSpec.Debug(string.Format(" targetCnt {0} ,location volType {1}, av cnt {2}", targetCnt, st.location.volType, st.getAvCount()));
                    if (targetCnt == 0)
                    {
                        break;
                    }
                    // logSpec.Debug(string.Format(" st.location.volType == (int)locVol {0}  ", st.location.volType == (int)locVol));
                    if (st.location.volType == (int)locVol)
                    {
                        decimal cnt = st.getAvCount();
                        decimal reductCnt = cnt >= targetCnt ? targetCnt : cnt;
                        //  logSpec.Debug(string.Format(" reductCnt {0}  ", reductCnt));
                        if (reductCnt <= 0)
                        {
                            continue;
                        }
                        if (WmsConstants.OUT_STOCK_DEDUCT)
                        {
                            st.countOuting += reductCnt;
                        }
                        else
                        {
                            st.countOut += reductCnt;
                            if (st.countIn + st.count - st.countOut <= 0) //库存扣完,删除记录
                            {
                                st.Delete();
                            }
                        }
                        st.operater = this.operId;
                        st.Update();
                        logStockOut(requestDetail, goods, st, reductCnt);
                        targetCnt -= reductCnt;
                    }
                }
             logSpec.Debug(string.Format( "{0} 定位完成,未定位数量{1}" , locVol, targetCnt));
            return targetCnt;
        }
        private enumStockRecordType stockOutType = enumStockRecordType.销售出库;
        private void logStockOut(WmsOutPickDetail pickDetail, WmsGoods goods, WmsStock stock, decimal count)
        {
            decimal maxFull = goods.full_max > 0 ? goods.full_max : count; //单个容器最大装载数量 ——> 最大单次分拣数量
           decimal leftCnt =count;
            decimal recCnt = 0;
            decimal lackCnt = pickDetail.lackCount;
           while (leftCnt>0)
            {
               
                recCnt = leftCnt >= maxFull ? maxFull : leftCnt;
                leftCnt -=recCnt;
                log.Debug(string.Format("1  goodsId {4},maxFull {0}, leftCnt:{1},recCnt {2}, locId {3},lackCnt {5},stock virtialCnt {6}", maxFull, leftCnt, recCnt, stock.locationId, goods.goodsId,lackCnt,stock.virtialCount));
                WmsStockRecord r = new WmsStockRecord();
                r.batch = stock.batch.Trim();
                r.skuCode = stock.skuCode;
                r.skuId = stock.skuId;
                if (WmsConstants.OUT_STOCK_DEDUCT)
                {
                    r.countOuting = recCnt;
                }
                else
                {
                    r.count = recCnt;
                }
                r.goodsId = pickDetail.goodsId.Trim();
                r.locationId = stock.locationId.Trim();
                r.productDate = stock.productDate;
                r.validDate = stock.validDate;
                //  r.orderNo = request.orderNo.Trim();
                r.orderNo = pickDetail.pickOrderNo.Trim();
                r.rectype = (int)stockOutType;//out
              //  logOut.Debug("1 stock.virtialCount  " + stock.virtialCount);
                //  if (stock.virtialCount >0)
                if (pickDetail.lackCount > 0)
                { 
                   decimal virCnt = 0; 
                    if(recCnt < lackCnt)
                    {
                        virCnt = recCnt;
                        lackCnt -= recCnt;
                    }
                    else
                    {
                        virCnt = lackCnt;
                        lackCnt = 0;
                    }
                    r.virCount = virCnt;
                    pickDetail.lackCount -= virCnt;
                    // stock.virtialCount -= virCnt; //////为什么这里不能对 stock 进行赋值操作????????????????????????????
                    //  stock.virtialCount = stock.virtialCount < 0 ? 0 : stock.virtialCount;
                    //   stock.updateCountOut();
                }
             //   logOut.Debug("2 stock.virtialCount  " + stock.virtialCount);
                // r.regeditCode = goods..Trim();
                r.operater = this.operId;
                r.orderDetailId = pickDetail.ID;//order detailId,同步 零货捡取临时数据、复核临时数据 的状态
                /*
                if (stock.location.partion > 0)
                {
                    Node nd = new Node(stock.location.partion);
                    r.partion = nd.flag;
                }
                */
                r.partion = stock.location.partion;
               int i = r.Add();
                if (stock.location.volType == (int)enumWhLocVol.虚拟)
                {
                    leftCnt = 0;// return;
                }
                log.Debug(string.Format("2  goodsId {4},maxFull {0}, leftCnt:{1},recCnt {2}, locId {3},lackCnt {5},stock virtialCnt {6}, new rec id {7}", maxFull, leftCnt, recCnt, stock.locationId, goods.goodsId, lackCnt, stock.virtialCount ,i));
            }
            pickDetail.Update();
        }
        private void logStockOutErpLocation(WmsOutPickDetail pd)
        {
            LogHelper.debug("lWmsOutRequest", "logStockOutErpLocation:  " + pd.ID);
            WmsStockRecord r = new WmsStockRecord();
            r.batch = pd.batch.Trim();
            r.skuCode = pd.skuCode;
            r.skuId = pd.skuId;
            if (WmsConstants.OUT_STOCK_DEDUCT)
            {
                r.countOuting = pd.bulkCount;
            }
            else
            {
                r.count = pd.bulkCount;
            }
            r.goodsId = pd.goodsId.Trim();
            r.locationId = pd.locationId.Trim();
            r.productDate = pd.productDate;
            r.validDate = pd.validDate;
            //  r.orderNo = request.orderNo.Trim();
            r.orderNo = pd.pickOrderNo.Trim();
            r.rectype = (int)enumStockRecordType.销售出库; ;//out
                                                        // r.regeditCode = goods..Trim();
            r.operater = this.operId;
            r.orderDetailId = pd.ID;//order detailId,同步 零货捡取临时数据、复核临时数据 的状态
            /*
            if (pd.location.partion > 0)
            {
                Node nd = new Node(pd.location.partion);
                r.partion = nd.flag;
            }*/
            r.partion = pd.location.partion;
            r.Add();
        }
        internal int approveOrder(string orderNo, int status, int priority, bool canMerge)
        {
            WmsOutRequest order = new WmsOutRequest(orderNo);
            if (string.IsNullOrEmpty(order.pickOrderNo))
            {
                order.state = status;
                order.operater = outRequest.operater;
                order.priority = priority;
                order.isMergable = canMerge;
                Erp_sale es = new Erp_sale(orderNo);
                es.wms_state = status;
                using (TransactionScope scope = new TransactionScope())
                {
                    es.Update();
                    order.Update();
                    scope.Complete();
                }
                return 1;
            }
            else
            {
                throw new Exception("操作失败,订单已经进入分拣作业");
            }
        }
        internal string genPickOrder(string orderNo)
        {
            WmsOutRequest order = new WmsOutRequest(orderNo);
            if (order.ID == 0)
            {
                return "";
            }
            if (string.IsNullOrEmpty(order.pickOrderNo))
            {
                List outds = order.outDetails;
                WmsOutPickRequest pr = new WmsOutPickRequest();
                DataTable dt = order.getOutDetailForPick();
                pr = new WmsOutPickRequest();
                pr.pickOrderNo = Util.getOrderNo(enumCreateOrderType.pickOrder, pr.getNextSeq(enumCreateOrderType.pickOrder));
                pr.orderType = order.orderType;
                pr.outStoreType = (int)getOutStoreType(order.orderType);// (int)enumOutStoreType.拣货出库;
                pr.operater = this.operId;
                pr.customerId = order.customerId;
                pr.customerName = order.customerName;
                pr.custAddress = order.custAddress;
                List pdCache = new List();
                foreach (DataRow dr in dt.Rows)
                {
                    WmsOutPickDetail pd = new WmsOutPickDetail(dr);
                    pd.pickOrderNo = pr.pickOrderNo;
                    pr.bulkCnt += pd.bulkCount; //pick request 总bulk cnt,作为拣选、复合工作量的指标
                    pr.boxCnt += pd.boxcnt;
                    if (pd.bulkCount > 0 && pd.bulkCount > pd.goods.stockBulkAvCount /* pd.getGoodsStockCnt(enumWhLocVol.零库)*/)// pd.goods.stockBulkCount)
                    {
                        pd.description = "零库库存不足,等待补货";
                        pr.state = (int)enumOutStockRequestStatus.等待补货;
                        pd.state = (int)enumOutStockDetailStatus.等待补货;
                        pr.description = string.Format("{0} 零库库存不足,等待补货 ", pd.goods.goodsName);
                        LogHelper.debug(typeof(lWmsOutRequest), pr.description);
                    }
                    pd.operater = this.operId;
                    //calculate the total bulk for each goods
                    if (pd.bulkCount > 0)
                    {
                        if (pd.count == pd.bulkCount) //batch not exists
                        {
                            pd.batchPickState = (int)enumOutStockPickStatus.无需分拣;
                        }
                    }
                    else
                    {
                        pd.bulkPickState = (int)enumOutStockPickStatus.无需分拣;
                    }
                    pdCache.Add(pd);
                }
                if (pdCache.Count > 0 && pr != null)
                {
                    pr.orderDate = pr.getDateTime();
                    try
                    {
                        using (TransactionScope scope1 = new TransactionScope())
                        {
                            pr.batchPickState = (int)enumOutStockPickStatus.无需分拣;
                            foreach (WmsOutDetail wd in outds)
                            {
                                wd.state = (int)enumOutStockDetailStatus.等待分拣;
                                wd.Update();
                            }
                            order.pickOrderNo = pr.pickOrderNo;
                            order.state = (int)Utils.enumOutStockRequestStatus.待定位;
                            order.Update();
                            esale.updatePickStatus(pr.pickOrderNo, Utils.enumOutStockRequestStatus.待定位);
                            foreach (WmsOutPickDetail p in pdCache)
                            {
                                if (p.batchPickState != (int)enumOutStockPickStatus.无需分拣)
                                {
                                    pr.batchPickState = (int)enumOutStockPickStatus.待处理;
                                }
                                p.Add();
                                // pr.outDetails.Add(p); //why duplicated sometimes?
                            }
                            pr.Add();
                            scope1.Complete();
                        }
                    }
                    catch (Exception er)
                    {
                        LogHelper.WriteLog(typeof(lWmsOutRequest), er);
                        //   updateOutRequestState(order.customerId,order.customerName, order.custAddress, "");
                    }
                    requestOutStock(pr.pickOrderNo);
                    return pr.pickOrderNo;
                    // pdCache.Clear();
                }
            }
            else
            {
                throw new Exception(string.Format("操作失败,订单{0}已经进入分拣作业", orderNo));
            }
            return "";
        }
        internal string genPickOrderByOrders(string[] orderNos)
        {
            return null;
        }
        internal string createPickOrderByDetails(int[] detailIds)
        {
            return null;
        }
        internal string createSeedsOrder(int pickGroup, int pickStartOn, string dueDate)
        {
            enumOutStockRequestStatus enOs = enumOutStockRequestStatus.待审核;
            enumOutStockDetailStatus enOd = enumOutStockDetailStatus.待处理;
            //  DataTable dt = outRequest.getSeedsSumDetail(pickGroup, pickStartOn, dueDate, enOs, enOd);
            WmsOutPickRequest pr = new WmsOutPickRequest(pickGroup, pickStartOn, dueDate);
            if (pr.ID == 0)
            {
                using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions()
                {
                    IsolationLevel = System.Transactions.IsolationLevel.Serializable,
                    Timeout = new TimeSpan(0, 10, 0)
                }
                  ))
                {
                    pr.pickGroup = pickGroup;
                    pr.pickStartOn = pickStartOn;
                    pr.dueDate = dueDate;
                    pr.orderType = (int)enumOrderType.销售出库;
                    pr.outStoreType = (int)enumOutStoreType.配货汇总拣货出库;
                    pr.pickOrderNo = Util.getOrderNo(enumCreateOrderType.pickOrder, pr.getNextSeq(enumCreateOrderType.pickOrder));
                    pr.operater = operId;
                    LogHelper.debug(typeof(lWmsOutRequest), "开始新建拣货明细,  ");
                    int cnt = outRequest.groupPickStart(pickGroup, pickStartOn, dueDate, pr.pickOrderNo, this.operId);
                    if (cnt > 0)
                    {
                        pr.Add();
                    }
                    #region slow way, 1 second slower
                    /*  DataTable dt = outRequest.getSeedsSumDetail(pickGroup, pickStartOn, dueDate, enOs, enOd);
                    
                    foreach (DataRow dr in dt.Rows)
                     {
                         WmsOutPickDetail pd = new WmsOutPickDetail(dr);
                         pd.pickOrderNo = pr.pickOrderNo;
                         pd.state = (int)enumOutStockPickStatus.待处理;
                         pd.Add();
                     }
                    if (dt.Rows.Count > 0)
                    {
                        pr.Add();
                    }*/
                    #endregion
                    LogHelper.debug(typeof(lWmsOutRequest), " 新建拣货明细 完成   ");
                    scope.Complete();
                }
            }
            LogHelper.debug(typeof(LoginInfo), "------!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!---------NOT -set userId:---------------- ");
            LogHelper.debug(typeof(lWmsOutRequest), "开始计算出库: ");
            requestOutStock(pr);
            LogHelper.debug(typeof(lWmsOutRequest), "计算出库结束  ");
            return pr.pickOrderNo;
        }
        internal DataTable getSeedsSumDetail(int pickGroup, int pickStartOn, string dueDate, int enOrderState, int enDetailState)
        {
            return outRequest.getSeedsSumDetail(pickGroup, pickStartOn, dueDate,
                (enumOutStockRequestStatus)enDetailState, (enumOutStockDetailStatus)enDetailState);
        }
        internal DataSet getSeedsSumDetail(string queryStr, int rowStart, int rowEnd)
        {
            queryStr = pareseCondition(queryStr);
            return outRequest.getSeedsSumDetail(queryStr, rowStart, rowEnd);
        }
        internal DataTable getSeedsDetailByGoods(string goodsId)
        {
            return outRequest.getSeedsDetailByGoods(goodsId);
        }
        internal DataTable getSeedsDetailBySku(int skuId)
        {
            return outRequest.getSeedsDetail(skuId);
        }
        //------------------------------test begin
        /// 
        /// 
        /// 
        internal void updateTestData()
        {
            Erp_sale sale = new Erp_sale();
            DataTable dt = sale.QueryActived().Tables[0];
            foreach (DataRow dr in dt.Rows)
            {
                sale = new Erp_sale(dr);
                sale.updateCreatetime();
                Thread.Sleep(10000);
            }
            Erp_purch ep = new Erp_purch();
            dt = ep.QueryActived().Tables[0];
            foreach (DataRow dr in dt.Rows)
            {
                ep = new Erp_purch(dr);
                ep.updateCreatetime();
                Thread.Sleep(10000);
            }
        }
        /// 
        /// 创建销售出库单
        /// 
        public void testCreateSales(string custId)
        {
            int itemCnt = new Random().Next(2, 5);
            //logSpec.Debug(string.Format("to create sales out , custId :{0}, itemCnt :{1}", custId, itemCnt));
            Customer cust = new Customer(); ;
            if (!string.IsNullOrEmpty(custId))
            {
                cust = new Customer(custId);
                testCreateOut(cust.ID, itemCnt);
                return;
            }
            DataTable dtCust = new Erp_customer().QueryActived().Tables[0];
            foreach (DataRow dr in dtCust.Rows)
            {
                testCreateOut(new Erp_customer(dr).ID, itemCnt);
            }
        }
        void testCreateOut(int custId, int itemCnt, int type = 0)
        {
            Erp_sale saleObj = new Erp_sale();
            Erp_customer cust = new Erp_customer(custId);
            //logSpec.Debug(string.Format("  cust ID :{0}, customerID :{1}", custId, cust.custId));
            saleObj.custor_id = cust.custId;
            saleObj.order_type = type;
            saleObj.orgid = "LDJNBYXGS";
            saleObj.receive_man = cust.contact;
            saleObj.salse_people = "hi chen";
            saleObj.send_address = cust.address;
            saleObj.entid = "LDJNBYXGS";
            saleObj.dueDate = DateTime.Now.AddDays(20).ToShortDateString();
            saleObj.sale_order = "s" + Utils.Util.getOrderNo(enumCreateOrderType.pickOutInvoice, saleObj.getNextSeq(enumCreateOrderType.pickOutInvoice));
            saleObj.Add();
            WmsGoods goods = new WmsGoods();
            DataTable goodDt = goods.QueryActived().Tables[0];
            int i = 0;
            itemCnt = itemCnt > 0 ? itemCnt : goodDt.Rows.Count;
            for (int j = 0; j < itemCnt; j++)
            {
                i = new Random().Next(goodDt.Rows.Count - itemCnt) - j;
                i = i > 0 ? i : j;
                goods = new WmsGoods(goodDt.Rows[i]);
                Erp_sale_d saled = new Erp_sale_d();
                saled.add_date = saled.getDateTime();
                saled.goods_id = goods.goodsId;
                saled.count = goods.stockBatchAvCount > 10 ? goods.stockBatchAvCount / 10 + 1 : 1;
                saled.sale_order_sn = j + 1;
                saled.sale_order = saleObj.sale_order;
                saled.Add();
                if (j > 5)
                {
                    break;
                }
            }
        }
        lWmsOutPickPort lpp;
        public void testPickOut()
        {
            lpp = new lWmsOutPickPort(operId);
            logTest.Debug("开始测试 出库拣货 .......................》》》");
            testFinishPickItem();
            if (WmsConstants.TEST_PICK_OUT_SEEDS)
            {
                logTest.Debug("开始测试 ....播种出库。。  ");
                testSeedsOut();
            }
            logTest.Debug("结束测试 出库拣货 ......................《《《");
        }
        void testTaskAssign(int partion, int lineId, int maxLots, int maxBoxCnt, bool batchOnly, enumOrderType orderType)
        {
            lpp.taskAssignByJob(operId, partion, lineId, maxLots, maxBoxCnt, batchOnly, (enumOrderType)orderType);
        }
        DataTable testGetAssignedTask(int partion, int lineId, bool batchOnly, enumOrderType orderType)
        {
            int me = this.operId;
            return lpp.getAssignedOutTasks(me, "",partion, lineId, batchOnly, (enumOrderType)orderType);
        }
        int limit = WmsConstants.TEST_PICK_OUT_ITEM_CNT;
        void testFinishPickItem()
        {
            lWmsOutPickRequest lop = new lWmsOutPickRequest(this.operId);
            WmsOutPickPort wop;
            int partion;
            int lineId = 0;
            bool batchOnly = WmsConstants.OUT_TASK_ASSIGN_BATCH_ONLY;
            int maxLots = WmsConstants.MAX_PICK_LOT_CNT;
            int maxBoxCnt = WmsConstants.MAX_PICK_BOX_CNT;
            DataTable dtPartion = lpp.getPartions(operId);
            Dictionary orderType = Util.convertEnumToDic(typeof(enumOrderType));
            int f = new Random().Next(1000);
            string flowNo;
             logTest.Debug(string.Format("1 maxLocCnt {0},maxBoxs {1}", maxLots, maxBoxCnt));
            int i = 0;
           
            foreach (DataRow dr in dtPartion.Rows)
            {
                partion = Convert.ToInt32(dr["partion"].ToString());
                WmsLocation loc = new WmsLocation().getByPartion(partion, 1);
                if (loc.ID == 0)
                {
                    continue;
                }
                foreach (int type in orderType.Keys)
                {
                       logTest.Debug(string.Format("order type {2} ,maxLocCnt {0},maxBoxs {1}, partion {3}, locationid {4}", maxLots, maxBoxCnt, orderType[type],partion,loc.locationId));
                    // testTaskAssign(partion, lineId, maxLots, maxBoxCnt, batchOnly, (enumOrderType)type);  
                    lpp.taskAssignByJob("", loc.locationId);
 
                    DataTable dt = testGetAssignedTask(partion, lineId, batchOnly, (enumOrderType)type); 
                    string waveNo = null;
                     logTest.Debug(string.Format("已完成 {0}条,开始下架任务 : {1}条待拣货记录", i,dt.Rows.Count));
                    string lastCustId = "";
                    foreach (DataRow dr2 in dt.Rows)
                    {
                        flowNo = string.Format("o{0}-{1}-{2}", f, partion, type);
                        if (string.IsNullOrEmpty(lastCustId))
                        {
                            lastCustId = dr2["customerId"].ToString();
                        }
                        if (lastCustId != dr2["customerId"].ToString())  //拣货容器不能放多个订单, 播种单除外
                        {
                            flowNo += i;
                        }
                        wop = new WmsOutPickPort(dr2);
                        enumPickResult result = lop.finishPickItem(flowNo, waveNo, wop.pickOrderNo, wop.ID, wop.count);
                        i++;
                       //  logTest.Debug(string.Format("finished pickItem, result {4}, partion {0}, outOrderType {1}, taskId {2}, pickOrderNO {3} ", partion, (enumOrderType)type, wop.ID, wop.pickOrderNo, result )); ;
                        if (i > limit * 2)
                        {
                           logTest.Debug(string.Format("1 总共下架了{0}条记录", i));
                            return;
                        }
                    }
                }
            }
             logTest.Debug(string.Format("2 总共下架了{0}条记录", i));
        }
        void testSeedsOut()
        {
            DataTable dt = lpp.getFlows4SeedsOut();
            bool isByCust = false;
            int j = 0;
            foreach (DataRow dr in dt.Rows)
            {
                j += testDoSeedsOut(dr["flowNo"].ToString(), isByCust);
                isByCust = !isByCust;
            }
            logTest.Debug(string.Format("取总分拣 总共分播了{0}条记录", j));
            dt = lpp.getFlows4ZhitongSeedsOut();
              isByCust = false;
 
            j = 0;
            foreach (DataRow dr in dt.Rows)
            {
                j += testDoSeedsOut(dr["flowNo"].ToString(), isByCust);
                isByCust = !isByCust;
            }
            logTest.Debug(string.Format("直通分货 总共分播了{0}条记录", j));
        }
        int testDoSeedsOut(string flowNo, bool isByCust)
        {
            string batch = "", toFlowNo = "", custId = "";
            int outDetailId = 0;
            decimal seedCnt = 0m;
            DataTable dt = lpp.getSeedsPickDetail(flowNo, isByCust);//容器的拣货明细
            int f = new Random().Next(1000);
            int i = 0;
            Dictionary map = new Dictionary();
            foreach (DataRow dr in dt.Rows)
            {
                custId = dr["customerId"].ToString();
                if (map.Keys.Contains(custId))
                {
                    toFlowNo = map[custId];
                }
                else
                {
                    toFlowNo = String.Format("t{0}-{1}", f, i);
                    map.Add(custId, toFlowNo);
                }
                batch = dr["batch"].ToString();
                outDetailId = Convert.ToInt32(dr["outDetailId"].ToString());
                decimal wantCount = Convert.ToDecimal(dr["wantCount"].ToString());
                string prdDate = dr["productDate"].ToString();
                int skuId = Convert.ToInt32(dr["skuId"].ToString());
                int inDetailId = Convert.ToInt32(dr["inDetailId"].ToString());
                seedCnt = Convert.ToDecimal(dr["availablecnt"].ToString());
                seedCnt = (wantCount <= seedCnt) ? wantCount : seedCnt;
                if (seedCnt <= 0)
                {
                    continue;
                }
                enumRepResult rt = lpp.seedsPickOut(flowNo, skuId, prdDate, batch, outDetailId, seedCnt, toFlowNo, inDetailId,false);
                if (rt == enumRepResult.成功)
                {
                    i++;
                }
                else
                {
                    logTest.Debug(rt);
                }
                if (i > limit)
                {
                    //  logTest.Debug(string.Format("总共分播了{0}条记录", i));
                    return i;
                }
            }
            return i;
        }
        //---test plate
        public void inPlateTest()
        {
            try
            {
                // public static bool TEST_PLATE_OUT_CUSTOMER;
                //  public static bool TEST_PLATE_OUT_LINE;
                // public static bool TEST_PLATE_OUT_VC;
                if (WmsConstants.TEST_PLATE_OUT_CUSTOMER)
                {
                    logTest.Debug(string.Format(" inPlateByCustomerTest cnt: {0}", inPlateByCustomerTest()));
                }
            } catch (Exception e)
            {
                logTest.Error(e);
            }
            try
            {
                if (WmsConstants.TEST_PLATE_OUT_LINE)
                {
                    logTest.Debug(string.Format(" inPlateLineTest cnt: {0}", inPlateLineTest()));
                }
            }
            catch (Exception e)
            {
                logTest.Error(e);
            }
            try
            {
                if (WmsConstants.TEST_PLATE_OUT_VC)
                {
                    logTest.Debug(string.Format(" inPlateTranTest cnt: {0}", inPlateTranTest()));
                }
            }
            catch (Exception e)
            {
                logTest.Error(e);
            }
            try
            {
                if (WmsConstants.TEST_PLATE_OUT_LOAD_TRUCK)
                {
                    logTest.Debug(string.Format(" loadTruckTest cnt: {0}", loadTruckTest()));
                }
            }
            catch (Exception e)
            {
                logTest.Error(e);
            }
            try
            {
                if (WmsConstants.TEST_PLATE_OUT_START_TRAN)
                {
                    logTest.Debug(string.Format(" startTranTest cnt: {0}", startTranTest()));
                }
            }
            catch (Exception e)
            {
                logTest.Error(e);
            }
            
        }
        /// 
        /// 客户集货测试
        /// 
        /// 
        int inPlateByCustomerTest()
        {
            logTest.Debug(" start inPlateByCustomerTest");
            List requests = new List();
            List listport = new List();
            requests = pickRequestObj.getObjs(pickRequestObj.getRequests(enumOutStoreType.拣货出库,2));
            List plates = new List();
            DataTable dt = new WmsPlate().QueryActived().Tables[0];
            int i = 0;
            foreach (DataRow dr in dt.Rows)
            {
                WmsPlate p = new WmsPlate(dr);
                if (p.type == (int)enumPlateLevel.客户集货)
                {
                    plates.Add(new WmsPlate(dr));
                    i++;
                }
             
                if(i == requests.Count)
                {
                    break;
                }
            }
            log.Debug(string.Format("客户集货测试 pickrequest cnt {0},plate cnt {1}  ",requests.Count,plates.Count));
       WmsOutPickPort wpp = new WmsOutPickPort();
            lWmsPlate lplate = new lWmsPlate(operId);
            i = 0;
            foreach (WmsOutPickRequest request in requests)
            { 
                if (request.orderType != (int)enumOrderType.销售出库 || string.IsNullOrEmpty(request.customerId))
                {
                    continue;
                }
                WmsPlate p=null;
                foreach (WmsPlate p1 in plates)
                {
                    if (p1.customerId.Equals(request.customerId))
                    {
                     
                        p1.customerId = request.customerId; 
                        p= p1;
                        break;
                    }
                }
                if (p == null)
                {
                    foreach (WmsPlate p1 in plates)
                    {
                        if ( string.IsNullOrEmpty(p1.customerId ))
                        {
                            p = p1;
                            break;
                        }
                    }
                }
                 
                listport = wpp.getObjs(wpp.getPickDetails(request.pickOrderNo));
                log.Debug(string.Format("客户集货测试 pickrequest {0},list port cnt {1}, to plate {2} ", request.pickOrderNo, listport.Count, p.plateId));
                foreach (WmsOutPickPort port in listport)
                {
                    enumRegPlateResult rs = lplate.putPlateIntoPlate(port.flowNo, p.plateId);
                    if (rs == enumRegPlateResult.成功)
                    {
                        i++;
                    }
                    log.Debug(string.Format("客户集货测试 pickrequest {0},fromPlate {1},toPlate {2}, result{3}", request.pickOrderNo, port.flowNo, p.plateId, rs));
                   
                }
                
                p.customerId = request.customerId; 
            }
            logTest.Debug(" end inPlateByCustomerTest");
            return i;
        }
        /// 
        /// 线路集货测试
        /// 
        /// 
        int inPlateLineTest()
        {
            int i = 0;
            logTest.Debug(" start inPlateLineTest");
            List plates = new List();
            List linePlates = new List();
            DataTable dt = new WmsPlate().QueryActived().Tables[0];
            lWmsPlate lplate = new lWmsPlate(operId);
            foreach (DataRow dr in dt.Rows)
            {
                plates.Add(new WmsPlate(dr));
            }
            foreach (WmsPlate p in plates)
            {
                if (p.type == (int)enumPlateLevel.线路集货)
                {
                    linePlates.Add(p);
                }
            }
            foreach (WmsPlate p2 in linePlates)
            {
                foreach (WmsPlate p in plates)
                {
                    if (!string.IsNullOrEmpty(p.customerId) && p.type == (int)enumPlateLevel.客户集货)
                    {
                        enumRegPlateResult rs = lplate.putPlateIntoPlate(p.plateId, p2.plateId);
                        logTest.Debug(string.Format(" from plate {0},线路集货结果: {1}", p.plateId, rs));
                        if (rs == enumRegPlateResult.成功)
                        {
                            i++;
                        }
                    }
                }
            }
            logTest.Debug("end inPlateLineTest");
            return i;
        }
        int inPlateTranTest()
        {
            int i = 0;
            logTest.Debug("start  inPlateTranTest()");
            List plates = new List();
            List vPlates = new List();
            DataTable dt = new WmsPlate().QueryActived().Tables[0];
            lWmsPlate lplate = new lWmsPlate(operId);
            foreach (DataRow dr in dt.Rows)
            {
                plates.Add(new WmsPlate(dr));
            }
            foreach (WmsPlate p in plates)
            {
                if (p.type == (int)enumPlateLevel.运输车)
                {
                    vPlates.Add(p);
                }
            }
            foreach (WmsPlate p2 in vPlates)
            {
                foreach (WmsPlate p in plates)
                {
                    if (p.type == (int)enumPlateLevel.线路集货)
                    {
                        enumRegPlateResult rs = lplate.putPlateIntoPlate(p.plateId, p2.plateId);
                        logTest.Debug(string.Format(" from plate {0},装车集货结果: {1}", p.plateId, rs));
                        if (rs == enumRegPlateResult.成功)
                        {
                            i++;
                        }
                    }
                }
            }
            logTest.Debug("end inPlateTranTest()");
            return i;
        }
        /// 
        /// 装车测试
        /// 
        /// 
        int loadTruckTest()
        {
            int i = 0;
            logTest.Debug(" start loadTruckTest");
            List plates = new List();
            List truckPlates = new List();
            DataTable dt = new WmsPlate().QueryActived().Tables[0];
            lWmsPlate lplate = new lWmsPlate(operId);
            foreach (DataRow dr in dt.Rows)
            {
                plates.Add(new WmsPlate(dr));
            }
            foreach (WmsPlate p in plates)
            {
                if (p.type == (int)enumPlateLevel.运输车)
                {
                    truckPlates.Add(p);
                }
            }
            foreach (WmsPlate p2 in truckPlates)
            {
                foreach (WmsPlate p in plates)
                {
                    if (!string.IsNullOrEmpty(p.customerId) && p.type == (int)enumPlateLevel.客户集货)
                    {
                        enumRegPlateResult rs = lplate.loadTruck(p.plateId, p2.plateId);
                        logTest.Debug(string.Format(" from plate {0} , to plate {2},装车结果: {1}", p.plateId, rs,p2.plateId));
                        if (rs == enumRegPlateResult.成功)
                        {
                            i++;
                        }
                    }
                }
                  
            }
            logTest.Debug("end loadTruckTest");
            return i;
        }
        int startTranTest()
        {
            int i = 0;
            logTest.Debug(" start startTranTest");
            List plates = new List();
            List truckPlates = new List();
            DataTable dt = new WmsPlate().QueryActived().Tables[0];
            lWmsPlate lplate = new lWmsPlate(operId);
            foreach (DataRow dr in dt.Rows)
            {
                plates.Add(new WmsPlate(dr));
            }
            foreach (WmsPlate p in plates)
            {
                if (p.type == (int)enumPlateLevel.运输车)
                {
                    truckPlates.Add(p);
                }
            }
            foreach (WmsPlate p2 in truckPlates)
            {
                logTest.Debug(" truck plate id "+ p2.plateId);
                logTest.Debug(" test startTran, result " + lplate.startTran(p2.plateId)); 
            }
            logTest.Debug("end startTranTest");
            return i;
        }
    }
}