/// ///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 = 6; int hour = DateTime.Now.AddMinutes(offset).Hour; int minute = DateTime.Now.AddMinutes(offset).Minute; if (hour == WmsConstants.ERP_TRANS_DATA_AT_CLOCK) { if (minute < WmsConstants.ERP_TRANS_DATA_SLEEP_MINUES+ 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_MINUES)); return true; } } 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.Hour <= WmsConstants.SEEDS_END_MINUTES; 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); } // 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}, 可出虚拟库?{1},goods.canLackOut ?{2} ", WmsConstants.OUT_STOCK_LACK_HOLD_ORDER, WmsConstants.OUT_STOCK_LACK_VIR_OUT , goods.canLackOut)); 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 && goods.canLackOut) // 库存不足则从虚拟库借出 { 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)); 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 (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("库存异常"); } } /* * 在开始已判断是否零库缺货 * 整库不足出零库的情况,在总货量足够的情况下,不会出现零库不足的问题 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; } } }