| | |
| | | using Tiger.Business.WMS.Common; |
| | | using Org.BouncyCastle.Ocsp; |
| | | using Tiger.Model.Sharetronic.Shelf; |
| | | using MailKit.Search; |
| | | using Tiger.Business.WMS.Extensions; |
| | | using static Tiger.Model.BIZ_WMS_PREP_BTH; |
| | | |
| | | namespace Tiger.Business.WMS.Transaction |
| | | { |
| | |
| | | } |
| | | |
| | | #region Propertys & Variables |
| | | private Preparation CurPREP; |
| | | public Preparation CurPREP { get; set; } |
| | | private List<BIZ_WMS_PREP_SN> CurSn = new(); |
| | | private BIZ_WMS_PREP_DTL CurPrepDtl = new(); |
| | | public List<SuggestItem> Suggests { get; set; } = new(); |
| | |
| | | catch (Exception ex) |
| | | { |
| | | //取消当前操作 |
| | | ResetScan(); |
| | | ResetTrans(); |
| | | //action.CatchExceptionWithLog(ex, $"扫描[{input.SN}]异常"); |
| | | action.CatchExceptionWithLog(ex, Biz.L("WMS.Default.Scan.ScanException", input.SN)); |
| | | } |
| | |
| | | catch (Exception ex) |
| | | { |
| | | //取消当前操作 |
| | | ResetScan(); |
| | | ResetTrans(); |
| | | //action.CatchExceptionWithLog(ex, $"备料任务扫描单据异常(Data: {0})"); |
| | | action.CatchExceptionWithLog(ex, Biz.L("WMS.Out_BIZ_WMS_PREP.ScanOrderException", input?.Data)); |
| | | } |
| | |
| | | { |
| | | var action = new ApiAction<BIZ_WMS_PREP>(); |
| | | CurPREP.Order = MainDB.Queryable<BIZ_WMS_PREP>().Where(q => q.ID == CurPREP.Order.ID).IncludesAllFirstLayer().First(); |
| | | |
| | | action.Data = CurPREP.Order; |
| | | return action; |
| | | } |
| | |
| | | var action = new ApiAction<ScanOutput>(new ScanOutput()); |
| | | try |
| | | { |
| | | var inputDtl = input?.Data?.JsonToObject<BIZ_WMS_PREP_DTL>(); |
| | | var prepDtl = MainDB.Queryable<BIZ_WMS_PREP_DTL>().Where(q => q.ID == inputDtl.ID).First(); |
| | | var option = CurPREP.Option = new BaseInput<SuggestOption>(input).Data; |
| | | var prepDtl = MainDB.Queryable<BIZ_WMS_PREP_DTL>().Where(q => q.ID == option.LineID).First(); |
| | | if (prepDtl.IsNullOrEmpty()) |
| | | { |
| | | action.IsSuccessed = false; |
| | |
| | | action.LocaleMsg = Biz.L("WMS.Out_BIZ_WMS_PREP.ScanItem.NotSelectItem"); |
| | | return action; |
| | | } |
| | | if (prepDtl.QTY_PREP > GetActReqQty(prepDtl)) |
| | | if (prepDtl.QTY_PREP > CurPREP.BizType.GetActReqQty(prepDtl)) |
| | | { |
| | | action.IsSuccessed = false; |
| | | //action.LocaleMsg = Biz.L("当前选择物料行[{0}]已备料数量[{1}],以满足实际需求数量[{2}],无需继续备料"); |
| | | action.LocaleMsg = Biz.L("WMS.Out_BIZ_WMS_PREP.SelectItem.PrepFinish", prepDtl.ITEM_CODE, prepDtl.QTY_PREP, GetActReqQty(prepDtl)); |
| | | action.LocaleMsg = Biz.L("WMS.Out_BIZ_WMS_PREP.SelectItem.PrepFinish", prepDtl.ITEM_CODE, prepDtl.QTY_PREP, CurPREP.BizType.GetActReqQty(prepDtl)); |
| | | return action; |
| | | } |
| | | //删除物料池中上一次分配的物料 |
| | |
| | | } |
| | | |
| | | //如果是首套发料,则只推荐当前物料行的一盘物料 |
| | | if (CurPREP.Order.CurBatch.DLVY_MODE == BIZ_WMS_PREP_BTH.DLVY_MODEs.First.GetValue()) |
| | | if (option.DlvyMode == WMS_ITEM_POOL.DLVY_MODEs.First) |
| | | { |
| | | //推荐物料 |
| | | Result<List<SuggestItem>> result = Suggest(CurPrepDtl.ORDER_NO, CurPrepDtl.ITEM_CODE, null, inputDtl.WH_ID, inputDtl.REGION_ID, inputDtl.SHELF_ID, input.AuthOption, 1); |
| | | Result<List<SuggestItem>> result = Suggest(CurPrepDtl.ORDER_NO, CurPrepDtl.ITEM_CODE, option, input.AuthOption, 1); |
| | | action.LocaleMsg = result.LocaleMsg; |
| | | if (result.IsException) |
| | | { |
| | |
| | | if (Suggests.Count > 0) |
| | | { |
| | | var inv = Suggests.First(); |
| | | var actQty = CurPrepDtl.QTY_PREP > GetActReqQty(CurPrepDtl) ? 0 : (GetActReqQty(CurPrepDtl) - CurPrepDtl.QTY_PREP); |
| | | var actQty = CurPrepDtl.QTY_PREP > CurPREP.BizType.GetActReqQty(CurPrepDtl) ? 0 : (CurPREP.BizType.GetActReqQty(CurPrepDtl) - CurPrepDtl.QTY_PREP); |
| | | if (inv != null && actQty > 0) |
| | | { |
| | | inv.poolItem = inv.Item.GetPoolItem(OrgCode, nameof(CurPREP.Order), CurPrepDtl.ORDER_NO, CurPrepDtl.ORDER_LINE, actQty, true); |
| | |
| | | } |
| | | |
| | | //如果是正常发料,则按实际需求数量推荐当前物料行的所有物料 |
| | | if (CurPREP.Order.CurBatch.DLVY_MODE == BIZ_WMS_PREP_BTH.DLVY_MODEs.Supply.GetValue()) |
| | | if (option.DlvyMode == WMS_ITEM_POOL.DLVY_MODEs.Supply) |
| | | { |
| | | //推荐物料 |
| | | var actQty = CurPrepDtl.QTY_PREP > GetActReqQty(CurPrepDtl) ? 0 : (GetActReqQty(CurPrepDtl) - CurPrepDtl.QTY_PREP); |
| | | Result<List<SuggestItem>> result = Suggest(CurPrepDtl.ORDER_NO, CurPrepDtl.ITEM_CODE, null, inputDtl.WH_ID, inputDtl.REGION_ID, inputDtl.SHELF_ID, input.AuthOption, actQty); |
| | | var actQty = CurPrepDtl.QTY_PREP > CurPREP.BizType.GetActReqQty(CurPrepDtl) ? 0 : (CurPREP.BizType.GetActReqQty(CurPrepDtl) - CurPrepDtl.QTY_PREP); |
| | | Result<List<SuggestItem>> result = Suggest(CurPrepDtl.ORDER_NO, CurPrepDtl.ITEM_CODE, option, input.AuthOption, actQty); |
| | | action.LocaleMsg = result.LocaleMsg; |
| | | if (result.IsException) |
| | | { |
| | |
| | | catch (Exception ex) |
| | | { |
| | | //取消当前操作 |
| | | ResetScan(); |
| | | ResetTrans(); |
| | | //action.CatchExceptionWithLog(ex, $"备料任务选择要物料行异常(Data: {0})"); |
| | | action.CatchExceptionWithLog(ex, Biz.L("WMS.Out_BIZ_WMS_PREP.SelectItemException", input?.Data)); |
| | | } |
| | |
| | | { |
| | | var action = new ApiAction<BIZ_WMS_PREP_DTL>(); |
| | | var prepDtl = MainDB.Queryable<BIZ_WMS_PREP_DTL>().Where(q => q.ID == CurPrepDtl.ID).First(); |
| | | prepDtl.ERP_WH = CurPrepDtl.ERP_WH; |
| | | prepDtl.WH_ID = CurPrepDtl.WH_ID; |
| | | prepDtl.REGION_ID = CurPrepDtl.REGION_ID; |
| | | prepDtl.SHELF_ID = CurPrepDtl.SHELF_ID; |
| | | prepDtl.Suggests = Suggests; |
| | | CurPrepDtl = prepDtl; |
| | | CurPREP.Order.Details.RemoveAll(q => q.ID == CurPrepDtl.ID); |
| | |
| | | action.LocaleMsg = Biz.L("WMS.Default.ScanItem.ItemIsLock", inv.CurPkg.SN); |
| | | return SetOutPutMqttMsg(action, input.Locale); |
| | | } |
| | | //验证条码是否被其他用户和单据锁定 |
| | | if (inv.Items.Any(q => q.IS_LOCKED == "Y")) |
| | | { |
| | | action.IsSuccessed = false; |
| | | //action.LocaleMsg = Biz.L("条码[{0}]已被锁定,请重新扫描"); |
| | | action.LocaleMsg = Biz.L("WMS.Default.ScanItem.ItemIsLock", inv.CurPkg.SN); |
| | | return SetOutPutMqttMsg(action, input.Locale); |
| | | } |
| | | //储位验证 |
| | | if (inv.Location.IsNullOrEmpty()) |
| | | { |
| | |
| | | return SetOutPutMqttMsg(action, input.Locale); |
| | | } |
| | | //判断是否在备料中的物料 |
| | | if (!CurPREP.Order.Details.Any(q => q.ITEM_CODE == inv.ItemInfo.ITEM_CODE)) |
| | | if (inv.ItemInfo.ITEM_CODE != CurPrepDtl.ITEM_CODE) |
| | | { |
| | | action.IsSuccessed = false; |
| | | //action.LocaleMsg = Biz.L($"当前备料任务[{0}]不包含条码[{1}]的物料编码[{2}],请放回原储位"); |
| | | action.LocaleMsg = Biz.L("WMS.Out_BIZ_WMS_PREP.ScanItem.NoNeedItemCode", inv.ItemInfo.ITEM_CODE.IsNullOrEmpty(inv.Barcode.ItemCode)); |
| | | //action.LocaleMsg = Biz.L($"条码[{0}]不是当前选中的物料行[{1}],请放回原储位或者重新选择下架物料行"); |
| | | action.LocaleMsg = Biz.L("WMS.Out_BIZ_WMS_PREP.ScanItem.NoNeedItemCode", inv.CurPkg.SN, CurPrepDtl.ITEM_CODE); |
| | | return action; |
| | | } |
| | | //判断是否在备料中的物料 |
| | | //if (!CurPREP.Order.Details.Any(q => q.ITEM_CODE == inv.ItemInfo.ITEM_CODE)) |
| | | //{ |
| | | // action.IsSuccessed = false; |
| | | // //action.LocaleMsg = Biz.L($"当前备料任务[{0}]不包含条码[{1}]的物料编码[{2}],请放回原储位"); |
| | | // action.LocaleMsg = Biz.L("WMS.Out_BIZ_WMS_PREP.ScanItem.NoNeedItemCode", inv.ItemInfo.ITEM_CODE.IsNullOrEmpty(inv.Barcode.ItemCode)); |
| | | // return action; |
| | | //} |
| | | |
| | | //ProcessingOrderDetail = input.SN; |
| | | //if (WMSContext.TransactionDic.Where(q => !string.IsNullOrWhiteSpace(q.Value.ProcessingSn)).Any(q => q.Value.ProcessingSn == ProcessingSn && q.Value.TransID != this.TransID)) |
| | | //{ |
| | |
| | | CurSn = CurInvItem.Items.Select(q => new BIZ_WMS_PREP_SN() { |
| | | ORDER_NO = CurPREP.Order.ORDER_NO, |
| | | ORDER_LINE = CurPrepDtl.ORDER_LINE, |
| | | ORDER_BATCH = CurPREP.Order.CurBatch.BATCH.ToString(), |
| | | SN = q.SN, |
| | | ITEM_CODE = q.ITEM_CODE, |
| | | UNIT = q.UNIT, |
| | | QTY = q.QTY, |
| | | QTY_DLVY = q.QTY, |
| | | STATUS = q.STATUS, |
| | | LOTNO = q.LOTNO, |
| | | WH_ID = CurInvItem.Warehouse.ID, |
| | | WH_CODE = CurInvItem.Warehouse.WH_CODE, |
| | | REGION_ID = CurInvItem.Region.ID, |
| | | REGION_CODE = CurInvItem.Region.REGION_CODE, |
| | | SHELF_ID = CurInvItem.Shelf.ID, |
| | | SHELF_CODE = CurInvItem.Shelf.SHELF_CODE, |
| | | LOCATION_ID = CurInvItem.Location.ID, |
| | | LOCATION_CODE = CurInvItem.Location.LOCATION_CODE, |
| | | FTY_CODE = CurPREP.Order.CurBatch.FTY_CODE, |
| | | WS_CODE = CurPREP.Order.CurBatch.WS_CODE, |
| | | LINE_CODE = CurPREP.Order.CurBatch.LINE_CODE, |
| | | POST_CODE = CurPREP.Order.CurBatch.POST_CODE, |
| | | OPER_CODE = CurPREP.Order.CurBatch.OPER_CODE, |
| | | SEGMENT = CurPREP.Order.CurBatch.SEGMENT, |
| | | SMT_NO = CurPrepDtl.SMT_NO, |
| | | STATION_NO = CurPrepDtl.STATION_NO, |
| | | FEEDER_NO = CurPrepDtl.FEEDER_NO, |
| | | FEEDER_TYPE = CurPrepDtl.FEEDER_TYPE, |
| | | IS_FIRST = CurPREP.Order.CurBatch.DLVY_MODE == BIZ_WMS_PREP_BTH.DLVY_MODEs.First.GetValue() ? "Y" : "N", |
| | | IS_FIRST = CurPREP.Option.DlvyMode == WMS_ITEM_POOL.DLVY_MODEs.First ? "Y" : "N", |
| | | NEED_CUTTING = "N", |
| | | TRACE_ID = TransID, |
| | | }).ToList(); |
| | | |
| | | |
| | | //判断是否超发 |
| | | isExceed = false; |
| | | //计算剩余需求数量和条码中的发出数量 |
| | | var actQty = CurPrepDtl.QTY_PREP > GetActReqQty(CurPrepDtl) ? 0 : (GetActReqQty(CurPrepDtl) - CurPrepDtl.QTY_PREP); |
| | | var actQty = CurPrepDtl.QTY_PREP > CurPREP.BizType.GetActReqQty(CurPrepDtl) ? 0 : (CurPREP.BizType.GetActReqQty(CurPrepDtl) - CurPrepDtl.QTY_PREP); |
| | | if (actQty < CurInvItem.CurPkg.QTY) |
| | | { |
| | | isExceed = true; |
| | |
| | | { |
| | | //action.LocaleMsg = Biz.L($"条码[{0}]扫描成功,备料物料[{1}]需求[{2}]还需备料[{3}],条码需要截料,发出数量[{4}]"); |
| | | //action.LocaleMsg = Biz.L($"条码[{0}]扫描成功,备料物料[{1}]需求[{2}]还需备料[{3}],请选择要超发还是截料?"); |
| | | action.LocaleMsg = Biz.L($"WMS.Out_BIZ_WMS_PREP.ScanItem.Success{(isNeedCut ? "" : "Confirm")}", CurInvItem.SN, CurInvItem.ItemInfo.ITEM_CODE, GetActReqQty(CurPrepDtl), actQty); |
| | | action.LocaleMsg = Biz.L($"WMS.Out_BIZ_WMS_PREP.ScanItem.Success{(isNeedCut ? "" : "Confirm")}", CurInvItem.SN, CurInvItem.ItemInfo.ITEM_CODE, CurPREP.BizType.GetActReqQty(CurPrepDtl), actQty); |
| | | action.Data.Command = "ConfirmExceed"; |
| | | action.Data.Data = new |
| | | { |
| | |
| | | var sns = (input.Data ?? "").JsonToObject<List<BIZ_WMS_PREP_SN>>() ?? new List<BIZ_WMS_PREP_SN>(); |
| | | if (!sns.Any()) |
| | | { |
| | | var actQty = CurPrepDtl.QTY_PREP > GetActReqQty(CurPrepDtl) ? 0 : (GetActReqQty(CurPrepDtl) - CurPrepDtl.QTY_PREP); |
| | | var actQty = CurPrepDtl.QTY_PREP > CurPREP.BizType.GetActReqQty(CurPrepDtl) ? 0 : (CurPREP.BizType.GetActReqQty(CurPrepDtl) - CurPrepDtl.QTY_PREP); |
| | | action.IsSuccessed = false; |
| | | //action.LocaleMsg = Biz.L($"条码[{0}]扫描成功,备料物料[{1}]需求[{2}]还需备料[{3}],条码需要截料,发出数量[{4}]"); |
| | | //action.LocaleMsg = Biz.L($"条码[{0}]扫描成功,备料物料[{1}]需求[{2}]还需备料[{3}],请选择要超发还是截料?"); |
| | | action.LocaleMsg = Biz.L($"WMS.Out_BIZ_WMS_PREP.ScanItem.Success{(isNeedCut ? "" : "Confirm")}", CurInvItem.SN, CurInvItem.ItemInfo.ITEM_CODE, GetActReqQty(CurPrepDtl), actQty); |
| | | action.LocaleMsg = Biz.L($"WMS.Out_BIZ_WMS_PREP.ScanItem.Success{(isNeedCut ? "" : "Confirm")}", CurInvItem.SN, CurInvItem.ItemInfo.ITEM_CODE, CurPREP.BizType.GetActReqQty(CurPrepDtl), actQty); |
| | | action.Data.Command = "ConfirmExceed"; |
| | | action.Data.Data = new |
| | | { |
| | |
| | | { |
| | | action.IsSuccessed = false; |
| | | action.LocaleMsg = downResult.LocaleMsg; |
| | | ResetScanInfo(); |
| | | ResetScan(); |
| | | return SetOutPutMqttMsg(action, input.Locale); |
| | | } |
| | | else//处理备料任务数据 |
| | |
| | | } |
| | | CurPrepDtl.QTY_PREP += CurSn.Sum(q => q.QTY_DLVY); |
| | | CurPREP.Order.STATUS = BIZ_WMS_PREP.STATUSs.Picking.GetValue(); |
| | | CurPREP.Order.CurBatch.STATUS = BIZ_WMS_PREP_BTH.STATUSs.Picking.GetValue(); |
| | | CurPREP.Order.CurBatch.PICK_TIME = DateTime.Now; |
| | | |
| | | //创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值 |
| | | var _CurSn = CurSn.Clone(); |
| | | var _CurPrepDtl = CurPrepDtl.Clone(); |
| | | var _CurPREPOrder = CurPREP.Order.Clone(); |
| | | var _CurPREPCurBatch = CurPREP.Order.CurBatch.Clone(); |
| | | AddCommitAction("UpdatePrep", () => |
| | | { |
| | | //使用统一的事务DB对象 |
| | |
| | | _CurPrepDtl.QTY_PREP = db.Queryable<BIZ_WMS_PREP_SN>().Where(q => q.ORDER_NO == _CurPrepDtl.ORDER_NO && q.ORDER_LINE == _CurPrepDtl.ORDER_LINE).Sum(q => q.QTY_DLVY); |
| | | db.Updateable(_CurPrepDtl, UserCode).UpdateColumns(q => new { q.QTY_PREP, q.UPDATE_TIME, q.UPDATE_USER }).ExecuteCommand(); |
| | | db.Updateable(_CurPREPOrder, UserCode).UpdateColumns(q => new { q.STATUS, q.UPDATE_TIME, q.UPDATE_USER }).ExecuteCommand(); |
| | | db.Updateable(_CurPREPCurBatch, UserCode).UpdateColumns(q => new { q.STATUS, q.PICK_TIME, q.UPDATE_TIME, q.UPDATE_USER }).ExecuteCommand(); |
| | | }); |
| | | |
| | | //灭灯 |
| | |
| | | catch (Exception ex) |
| | | { |
| | | //取消当前操作 |
| | | ResetScan(); |
| | | //清理暂存数据提交操作 |
| | | DBCommitList.Clear(); |
| | | ResetTrans(); |
| | | //action.CatchExceptionWithLog(ex, $"扫描条码[{input.SN}]复核异常"); |
| | | action.CatchExceptionWithLog(ex, Biz.L("WMS.Default.ScanItem.ScanException", input.SN)); |
| | | } |
| | | return SetOutPutMqttMsg(action, input.Locale); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 实际需求数量计算方法 |
| | | /// </summary> |
| | | /// <param name="dtl"></param> |
| | | /// <returns></returns> |
| | | private double GetActReqQty(BIZ_WMS_PREP_DTL dtl) |
| | | { |
| | | return dtl.QTY_REQ; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | catch (Exception ex) |
| | | { |
| | | //取消当前操作 |
| | | ResetScan(); |
| | | ResetTrans(); |
| | | //action.CatchExceptionWithLog(ex, $"扫描货架/储位[{0}]异常"); |
| | | action.CatchExceptionWithLog(ex, Biz.L("WMS.Default.ScanShelf.ScanException", Code)); |
| | | } |
| | |
| | | action.LocaleMsg = Biz.L("WMS.Default.ScanItem.TakeDownSucceeded", CurInvItem.SN, CurInvItem.Location?.LOCATION_CODE); |
| | | |
| | | //重置工序 |
| | | ResetScanInfo(); |
| | | ResetScan(); |
| | | return SetOutPutMqttMsg(action, locale); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 创建发料批次以完成本次发料,调用发料单据的ERP接口 |
| | | /// </summary> |
| | | /// <param name="input"></param> |
| | | /// <returns></returns> |
| | | public async Task<ApiAction> GenerateDlvyBatch(BaseInput input) |
| | | { |
| | | var range = input.Data.ToInt32().GetEnum<BATCH_RANGEs>(); |
| | | var action = await CurPREP.Order.BIZ_TYPE.GetEnum<BIZ_WMS_PREP.BIZ_TYPEs>() .GenerateDlvyBatch(this, range); |
| | | return action; |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | /// <summary> |
| | | /// 重置当前操作,有需要则重写此方法 |
| | | /// 重置事务数据,有需要则重写此方法 |
| | | /// </summary> |
| | | public override void ResetScan() |
| | | public override void ResetTrans() |
| | | { |
| | | base.ResetScan(); |
| | | ResetScanInfo(); |
| | | ResetScan(); |
| | | CurPREP = new(MainDB, UserCode, OrgCode); |
| | | CurPrepDtl = new(); |
| | | CurScanShelf = null; |
| | | base.ResetTrans(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 重置扫码信息 |
| | | /// 重置本次扫码信息 |
| | | /// </summary> |
| | | public void ResetScanInfo() |
| | | public override void ResetScan() |
| | | { |
| | | Command = "Normal"; |
| | | CurInvItem = null; |
| | | CurSn = new(); |
| | | base.ResetScan(); |
| | | } |
| | | |
| | | public override bool Close(bool needSaveHistoryLog = false) |