| | |
| | | using Rhea.Common; |
| | | using Microsoft.Extensions.Options; |
| | | using Rhea.Common; |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | |
| | | using System.Threading.Tasks; |
| | | using Tiger.IBusiness; |
| | | using Tiger.Model; |
| | | using Tiger.Model.Entitys.MES.Position; |
| | | using Tiger.Model.Entitys.MES.U9C; |
| | | using static IronPython.Modules._ast; |
| | | |
| | | namespace Tiger.Business.WMS.Transaction |
| | | { |
| | |
| | | action.Invoke(); |
| | | } |
| | | } |
| | | }); |
| | | if (dbTran.IsSuccess) |
| | | { |
| | | //保存成功则清空提交操作列表 |
| | | DBCommitList.Clear(); |
| | | } |
| | | else |
| | | }); |
| | | //保存成功则清空提交操作列表 |
| | | DBCommitList.Clear(); |
| | | if (!dbTran.IsSuccess) |
| | | { |
| | | //抛出异常 |
| | | throw dbTran.ErrorException; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取条码库存信息,包括仓库,储区,货架,储位,父条码,包装明细等 |
| | | /// </summary> |
| | | /// <param name="sn">查询的条码</param> |
| | | /// <param name="option">授权查询选项</param> |
| | | /// <param name="doUnPack">是否同时执行拆包操作,解除与父条码之间的包装关系</param> |
| | | /// <returns></returns> |
| | | public Result<IInventory> GetInventory(string sn, AuthOption option, bool doUnPack) |
| | | { |
| | | var result = new Result<IInventory>(Result.Flags.Success); |
| | | try |
| | | { |
| | | var inv = new Inventory(); |
| | | Barcode barcode = new Barcode(sn); |
| | | if (sn.IsNullOrEmpty()) |
| | | { |
| | | result.Flag = Result.Flags.Failed; |
| | | result.LocaleMsg = new("WMS.WmsItem.Barcode.EmptyFailure"); |
| | | } |
| | | else if (barcode.IsException) |
| | | { |
| | | throw barcode.AnalyseException; |
| | | } |
| | | //非法条码 |
| | | else if (!barcode.IsRegular) |
| | | { |
| | | result.Flag = Result.Flags.Failed; |
| | | result.LocaleMsg = new("WMS.WmsItem.Barcode.IllegalFailure"); |
| | | } |
| | | //else if (barcode.Qty <= 0) |
| | | //{ |
| | | // result.Flag = Result.Flags.Failed; |
| | | // result.LocaleMsg = new("数量不能小于等于零,请检查二维码!"); |
| | | //} |
| | | else |
| | | { |
| | | var query = Biz.Db.Queryable<WMS_ITEM_PKG>().ByAuth(option).Where(q => q.SN == barcode.SN).IncludesAllFirstLayer().First(); |
| | | //var query = Biz.Db.Queryable<WMS_ITEM_PKG>().Where(q => q.SN == barcode.SN).IncludesAllFirstLayer().First();//.ByAuth(option) |
| | | |
| | | //包装表中找到条码 |
| | | if (!query.IsNullOrEmpty())// && query.QTY > 0) |
| | | { |
| | | inv.SN = barcode.SN; |
| | | inv.Barcode = barcode; |
| | | inv.ExtInfo = query.ExtInfo; |
| | | inv.ItemInfo = query.ItemInfo; |
| | | inv.Warehouse = query.Warehouse; |
| | | inv.Region = query.Region; |
| | | inv.Shelf = query.Shelf; |
| | | inv.Location = query.Location; |
| | | inv.Packages = Biz.Db.Ado.UseStoredProcedure().SqlQuery<WMS_ITEM_PKG>("sp_wms_get_item_pkg", new SugarParameter("root", barcode.SN)); |
| | | inv.Items = Biz.Db.Ado.UseStoredProcedure().SqlQuery<WMS_ITEM>("sp_wms_get_items", new SugarParameter("root", barcode.SN)); |
| | | inv.ItemsExt = Biz.Db.Queryable<WMS_ITEM_EXT>().Where(q => inv.Items.Any(s => s.SN == q.SN)).ToList(); |
| | | //var data = inv.Items.Select(i => i.SN).ToList().Except(inv.ItemsExt.Select(i => i.SN).ToList()); |
| | | var data = inv.Items.Where(q => !inv.ItemsExt.Any(s => s.SN == q.SN)).ToList(); |
| | | if (data.Count > 0) |
| | | { |
| | | foreach (var item in data) |
| | | { |
| | | inv.ItemsExt.Add(new() |
| | | { |
| | | SN = item.SN, |
| | | META_SN = barcode.MetaSn, |
| | | QR_CODE = barcode.MetaSn |
| | | }); |
| | | } |
| | | } |
| | | result.LocaleMsg = new($"WMS.WmsItem.Barcode.Get{(doUnPack ? "UnPack" : "")}Success", barcode.SN, query.Parent?.SN); |
| | | if (!query.Parent.IsNullOrEmpty() && doUnPack && query.Parent.SN != query.SN) |
| | | { |
| | | inv.ParentPkg = null; |
| | | //保存数据到数据库 |
| | | var db = Biz.Db; |
| | | var dbTran = db.UseTran(() => |
| | | { |
| | | var unPackQty = inv.Items.Sum(q => q.QTY); |
| | | db.Updateable<WMS_ITEM_PKG>().SetColumns(q => q.PARENT_SN == null).Where(q => q.ID == query.ID).ExecuteCommand(); |
| | | db.Updateable<WMS_ITEM_PKG>().SetColumns(q => q.QTY == q.QTY - unPackQty).Where(q => q.ID == query.Parent.ID).ExecuteCommand(); |
| | | if (!Biz.Db.Queryable<WMS_ITEM_PKG>().Any(q => q.PARENT_SN == query.PARENT_SN && q.SN != query.SN)) |
| | | { |
| | | db.Deleteable(query.Parent); |
| | | } |
| | | }); |
| | | if (!dbTran.IsSuccess) |
| | | { |
| | | throw dbTran.ErrorException; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | inv.ParentPkg = query.Parent; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | inv.SN = barcode.SN; |
| | | inv.Barcode = barcode; |
| | | inv.ItemInfo = Biz.Db.Queryable<BAS_ITEM>().Where(q => q.ITEM_CODE == barcode.ItemCode).First(); |
| | | result.LocaleMsg = new($"WMS.WmsItem.Barcode.NotFound", barcode.SN); |
| | | } |
| | | } |
| | | result.Data = inv; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.Barcode.GetException", sn)); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | var location = Biz.Db.Queryable<V_WH_UNIT>().Where(q => q.LOCATION_CODE == targetLocation && q.AUTH_ORG == option.CurOrg).IncludesAllFirstLayer().First(); |
| | | if (!location.IsNullOrEmpty()) |
| | | { |
| | | var isTransfer = CurInvItem.Location.LOCATION_CODE != location.LOCATION_CODE; |
| | | var isTransfer = CurInvItem?.Location?.LOCATION_CODE != location.LOCATION_CODE; |
| | | foreach (var item in CurInvItem.Items) |
| | | { |
| | | item.STATUS = WMS_ITEM.STATUSs.InStore.GetValue(); |
| | | item.LOTNO = item.LOTNO.IsNullOrEmpty(new Barcode(item.SN).LotNo); |
| | | item.SUPP_LOTNO = CurInvItem.Barcode.LotNo; |
| | | item.FIRST_IN_DATE = item.FIRST_IN_DATE <= DateTime.MinValue ? DateTime.Now : item.FIRST_IN_DATE; |
| | | item.PROD_DATE = item.PROD_DATE <= DateTime.MinValue ? item.FIRST_IN_DATE : item.PROD_DATE; |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 下架物料推荐,返回固定个数的最小包装物料库存列表 |
| | | /// </summary> |
| | | /// <param name="order">领料单号</param> |
| | | /// <param name="itemCode">物料编码</param> |
| | | /// <param name="option">备料物料推荐选项</param> |
| | | /// <param name="auth">授权查询选项</param> |
| | | /// <param name="returnCount">返回的最小包装物料个数,默认返回1个</param> |
| | | /// <returns></returns> |
| | | public Result<List<SuggestItem>> Suggest(string order, string itemCode, SuggestOption option, AuthOption auth, int returnCount = 1) |
| | | { |
| | | var result = new Result<List<SuggestItem>>(Result.Flags.Success, new List<SuggestItem>()) { LocaleMsg = new("WMS.WmsItem.Suggest.Success") }; |
| | | try |
| | | { |
| | | var query = Biz.Db.Queryable<WMS_ITEM, WMS_ITEM_POOL, WMS_WAREHOUSE, WMS_REGION, WMS_SHELF, WMS_LOCATION>((q, p, w, r, s, l) => new JoinQueryInfos( |
| | | JoinType.Left, q.SN == p.SN, |
| | | JoinType.Left, q.WH_ID == w.ID, |
| | | JoinType.Left, q.REGION_ID == r.ID, |
| | | JoinType.Left, q.SHELF_ID == s.ID, |
| | | JoinType.Left, q.LOCATION_ID == l.ID)) |
| | | //检查用户权限 |
| | | .ByAuth(auth) |
| | | //允许使用已经分配到库存池中同一个单据的物料 |
| | | .Where((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID) || (!SqlFunc.IsNullOrEmpty(order) && p.TRANS_NO == order) || p.IS_LOCKED == "N") |
| | | //只允许未锁定的 |
| | | .Where((q, p, w, r, s, l) => q.IS_LOCKED == "N") |
| | | //只允许物料状态是在库的 |
| | | .Where((q, p, w, r, s, l) => q.STATUS == WMS_ITEM.STATUSs.InStore.GetValue()) |
| | | //如果有传入料号,则只允该料号的物料 |
| | | .WhereIF(!itemCode.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ITEM_CODE == itemCode) |
| | | //如果有传入库位,则只允该库位中的物料 |
| | | .WhereIF(!option.ErpWH.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ERP_WH == option.ErpWH && q.AUTH_ORG == auth.CurOrg) |
| | | //如果有传入仓库,则只允该仓库的物料 |
| | | .WhereIF(!option.WHID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.WH_ID == option.WHID && q.AUTH_ORG == auth.CurOrg) |
| | | //如果有传入储区,则只允该储区的物料 |
| | | .WhereIF(!option.RegionID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.REGION_ID == option.RegionID && q.AUTH_ORG == auth.CurOrg) |
| | | //如果有传入货架,则只允该货架的物料 |
| | | .WhereIF(!option.ShelfID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.SHELF_ID == option.ShelfID && q.AUTH_ORG == auth.CurOrg) |
| | | //优先使用库存池中的物料 |
| | | .OrderBy((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID)) |
| | | //优先使用尾数物料(截料或者退料之后的物料) |
| | | //.OrderByDescending((q, p, w, r, s, l) => q.SN.Contains("_C") || q.SN.Contains("_T")) |
| | | //备料策略:按生产日期先进先出 |
| | | .OrderByIF(option.Strategy.HasFlag(WMS_ITEM_POOL.STRATEGYs.FIFO), (q, p, w, r, s, l) => q.PROD_DATE) |
| | | //按生产日期先进先出,再按物料数量从小到大, |
| | | .OrderByIF(option.Strategy.HasFlag(WMS_ITEM_POOL.STRATEGYs.FSFO), q => q.QTY) |
| | | //最后按条码排序 |
| | | .OrderBy(q => q.SN); |
| | | var items = query.Select((q, p, w, r, s, l) => new SuggestItem |
| | | { |
| | | Item = q, |
| | | poolItem = null, |
| | | Warehouse = w, |
| | | Region = r, |
| | | Shelf = s, |
| | | Location = l, |
| | | }).Take(returnCount).ToList(); |
| | | //foreach (var item in items) |
| | | //{ |
| | | // var inv = Get(item.SN, option, false); |
| | | // if (inv.IsSuccessed) |
| | | // { |
| | | // result.Data.Add(inv.Data); |
| | | // } |
| | | //} |
| | | result.Data = items; |
| | | var totalQty = result.Data.Sum(q => q.Item.QTY); |
| | | var total = result.Data.Count; |
| | | if (0 <= total && total < returnCount) |
| | | { |
| | | result.Flag = Result.Flags.Warning; |
| | | result.LocaleMsg = new("WMS.WmsItem.Suggest.Warning", total); |
| | | } |
| | | //if (total == 0) |
| | | //{ |
| | | // result.Flag = Result.Flags.Failed; |
| | | // result.LocaleMsg = new("WMS.WmsItem.Suggest.Failed"); |
| | | //} |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.Suggest.Exception")); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 下架物料推荐,按需求数量返回满足需求的物料库存列表 |
| | | /// </summary> |
| | | /// <param name="order">领料单号</param> |
| | | /// <param name="itemCode">物料编码</param> |
| | | /// <param name="option">备料物料推荐选项</param> |
| | | /// <param name="auth">授权查询选项</param> |
| | | /// <param name="reqQty">需求数量,会返回满足需求的物料个数</param> |
| | | /// <returns></returns> |
| | | public Result<List<SuggestItem>> Suggest(string order, string itemCode, SuggestOption option, AuthOption auth, double reqQty) |
| | | { |
| | | var result = new Result<List<SuggestItem>>(Result.Flags.Success, new List<SuggestItem>()) { LocaleMsg = new("WMS.WmsItem.Suggest.Success") }; |
| | | try |
| | | { |
| | | var query = Biz.Db.Queryable<WMS_ITEM, WMS_ITEM_POOL, WMS_WAREHOUSE, WMS_REGION, WMS_SHELF, WMS_LOCATION>((q, p, w, r, s, l) => new JoinQueryInfos( |
| | | JoinType.Left, q.SN == p.SN, |
| | | JoinType.Left, q.WH_ID == w.ID, |
| | | JoinType.Left, q.REGION_ID == r.ID, |
| | | JoinType.Left, q.SHELF_ID == s.ID, |
| | | JoinType.Left, q.LOCATION_ID == l.ID)) |
| | | //检查用户权限 |
| | | .ByAuth(auth) |
| | | //允许使用已经分配到库存池中的物料 |
| | | .Where((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID) || (!SqlFunc.IsNullOrEmpty(order) && p.TRANS_NO == order) || p.IS_LOCKED == "N") |
| | | //只允许未锁定的 |
| | | .Where((q, p, w, r, s, l) => q.IS_LOCKED == "N") |
| | | //只允许物料状态是在库的 |
| | | .Where((q, p, w, r, s, l) => q.STATUS == WMS_ITEM.STATUSs.InStore.GetValue()) |
| | | //如果有传入料号,则只允该料号的物料 |
| | | .WhereIF(!itemCode.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ITEM_CODE == itemCode) |
| | | //如果有传入库位,则只允该库位中的物料 |
| | | .WhereIF(!option.ErpWH.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ERP_WH == option.ErpWH && q.AUTH_ORG == auth.CurOrg) |
| | | //如果有传入仓库,则只允该仓库的物料 |
| | | .WhereIF(!option.WHID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.WH_ID == option.WHID && q.AUTH_ORG == auth.CurOrg) |
| | | //如果有传入储区,则只允该储区的物料 |
| | | .WhereIF(!option.RegionID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.REGION_ID == option.RegionID && q.AUTH_ORG == auth.CurOrg) |
| | | //如果有传入货架,则只允该货架的物料 |
| | | .WhereIF(!option.ShelfID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.SHELF_ID == option.ShelfID && q.AUTH_ORG == auth.CurOrg) |
| | | //优先使用库存池中的物料 |
| | | .OrderBy((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID)) |
| | | //优先使用尾数物料(截料或者退料之后的物料) |
| | | //.OrderByDescending((q, p, w, r, s, l) => q.SN.Contains("_C") || q.SN.Contains("_T")) |
| | | //备料策略:按生产日期先进先出 |
| | | .OrderByIF(option.Strategy.HasFlag(WMS_ITEM_POOL.STRATEGYs.FIFO), (q, p, w, r, s, l) => q.PROD_DATE) |
| | | //按生产日期先进先出,再按物料数量从小到大, |
| | | .OrderByIF(option.Strategy.HasFlag(WMS_ITEM_POOL.STRATEGYs.FSFO), q => q.QTY) |
| | | //最后按条码排序 |
| | | .OrderBy(q => q.SN); |
| | | var takeCount = 0; |
| | | var checkSum = 0.0; |
| | | var checkCount = 0; |
| | | do |
| | | { |
| | | takeCount += 50; |
| | | var check = query.Select((q, p, w, r, s, l) => new |
| | | { |
| | | ItemCode = q.ITEM_CODE, |
| | | Sn = q.SN, |
| | | Qty = q.QTY |
| | | }) |
| | | .Take(takeCount) |
| | | .MergeTable() |
| | | .GroupBy(t => t.ItemCode) |
| | | .Select(t => new |
| | | { |
| | | Count = SqlFunc.AggregateCount(t.Sn), |
| | | Sum = SqlFunc.AggregateSum(t.Qty), |
| | | }).First(); |
| | | if (!check.IsNullOrEmpty()) |
| | | { |
| | | checkSum = check.Sum; |
| | | checkCount = check.Count; |
| | | } |
| | | else |
| | | { |
| | | checkSum = 0; |
| | | checkCount = 0; |
| | | } |
| | | } while (checkSum < reqQty && checkCount >= takeCount); |
| | | |
| | | var items = query.Select((q, p, w, r, s, l) => new SuggestItem |
| | | { |
| | | Item = q, |
| | | poolItem = null, |
| | | Warehouse = w, |
| | | Region = r, |
| | | Shelf = s, |
| | | Location = l, |
| | | }) |
| | | .Take(takeCount).ToList(); |
| | | var curQty = 0.0; |
| | | foreach (var item in items) |
| | | { |
| | | result.Data.Add(item); |
| | | curQty += item.Item.QTY; |
| | | if (curQty >= reqQty) |
| | | { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | var totalQty = result.Data.Sum(q => q.Item.QTY); |
| | | var total = result.Data.Count; |
| | | if (0 <= totalQty && totalQty < reqQty) |
| | | { |
| | | result.Flag = Result.Flags.Warning; |
| | | result.LocaleMsg = new("WMS.WmsItem.Suggest.Warning", totalQty); |
| | | } |
| | | //if (totalQty == 0) |
| | | //{ |
| | | // result.Flag = Result.Flags.Failed; |
| | | // result.LocaleMsg = new("WMS.WmsItem.Suggest.Failed"); |
| | | //} |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.Suggest.Exception")); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 下架 |
| | | /// </summary> |
| | | /// <param name="option">授权查询选项</param> |
| | |
| | | /// <summary> |
| | | /// 下架 |
| | | /// </summary> |
| | | /// <param name="inventory">要下架的库存对象</param> |
| | | /// <param name="qtyList">要下架的最小包装数量字典,key:sn,value:qty</param> |
| | | /// <param name="option">授权查询选项</param> |
| | | /// <param name="status">下架后状态</param> |
| | | /// <param name="clearLocation">是否清理储区货架储位信息</param> |
| | | /// <returns></returns> |
| | | public Result TakeDown(Dictionary<string, double> qtyList, AuthOption option, WMS_ITEM.STATUSs status) |
| | | { |
| | |
| | | else |
| | | { |
| | | item.STATUS = status.GetValue(); |
| | | item.CARTON_NO = null; |
| | | item.PALLET_NO = null; |
| | | var pkg = CurInvItem.Packages.First(q => q.SN == item.SN); |
| | | pkg.PARENT_SN = null; |
| | | pkg.Parent = null; |
| | |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 备料下架 |
| | | /// </summary> |
| | | /// <param name="qtyList">要下架的最小包装数量字典,key:sn,value:qty</param> |
| | | /// <param name="option">授权查询选项</param> |
| | | /// <param name="status">下架后状态</param> |
| | | /// <returns></returns> |
| | | public Result TakeDown(List<BIZ_WMS_PREP_SN> snList, AuthOption option, WMS_ITEM.STATUSs status) |
| | | { |
| | | var result = new Result(Result.Flags.Success); |
| | | try |
| | | { |
| | | foreach (var item in CurInvItem.Items) |
| | | { |
| | | var sn = snList.First(q => q.SN == item.SN); |
| | | var pkg = CurInvItem.Packages.First(q => q.SN == item.SN); |
| | | //前端返回Y认为是截料发料,N认为是整盘发料 |
| | | if (sn.QTY > sn.QTY_DLVY && sn.NEED_CUTTING == "Y") |
| | | { |
| | | CurInvItem.History.Add(new WMS_ITEM_HIS(item, $"条码[{item.SN}]截料发料,截料发出条码[{sn.DeliverySN}]数量[{sn.QTY_DLVY}],保留在库条码[{sn.ReserveSN}]数量[{sn.QTY - sn.QTY_DLVY}],操作单据[{item.TRANS_NO}]")); |
| | | |
| | | item.SN = sn.ReserveSN; |
| | | item.QTY = sn.QTY - sn.QTY_DLVY; |
| | | pkg.SN = sn.ReserveSN; |
| | | pkg.QTY = sn.QTY - sn.QTY_DLVY; |
| | | CurInvItem.History.Add(new WMS_ITEM_HIS(item, $"条码[{item.SN}]截料发料后保留在库,原条码[{sn.SN}]数量[{sn.QTY}],操作单据[{item.TRANS_NO}]")); |
| | | |
| | | //创建截料发出的物料信息 |
| | | var newItem = item.Clone(); |
| | | newItem.ID = Guid.NewGuid().ToString(); |
| | | newItem.SN = sn.DeliverySN; |
| | | newItem.STATUS = status.GetValue(); |
| | | newItem.QTY = sn.QTY_DLVY; |
| | | newItem.CARTON_NO = null; |
| | | newItem.PALLET_NO = null; |
| | | newItem.REGION_ID = null; |
| | | newItem.SHELF_ID = null; |
| | | newItem.LOCATION_ID = null; |
| | | WMS_ITEM_HIS his = new(newItem, $"条码[{newItem.SN}]从储位[{CurInvItem?.Location?.LOCATION_CODE}]截料发料成功,发出数量[{newItem.QTY}],状态[{newItem.STATUS.GetEnumDesc<WMS_ITEM.STATUSs>()}],原条码[{sn.SN}]数量[{sn.QTY}],操作单据[{item.TRANS_NO}]"); |
| | | |
| | | var newPkg = pkg.Clone(); |
| | | newPkg.ID = Guid.NewGuid().ToString(); |
| | | newPkg.PARENT_SN = null; |
| | | newPkg.Parent = null; |
| | | newPkg.REGION_ID = null; |
| | | newPkg.SHELF_ID = null; |
| | | newPkg.LOCATION_ID = null; |
| | | |
| | | CurInvItem.ItemsExt.Add(new() |
| | | { |
| | | SN = newItem.SN, |
| | | META_SN = newItem.SN, |
| | | }); |
| | | |
| | | CurInvItem.Items.Add(newItem); |
| | | CurInvItem.History.Add(his); |
| | | CurInvItem.Packages.Add(newPkg); |
| | | } |
| | | else |
| | | { |
| | | item.STATUS = status.GetValue(); |
| | | item.CARTON_NO = null; |
| | | item.PALLET_NO = null; |
| | | pkg.PARENT_SN = null; |
| | | pkg.Parent = null; |
| | | //如果下架数量等于库存数量则清理储区货架储位信息,否则保留仓库信息 |
| | | //item.WH_ID = null; |
| | | item.REGION_ID = null; |
| | | item.SHELF_ID = null; |
| | | item.LOCATION_ID = null; |
| | | //pkg.WH_ID = null; |
| | | pkg.REGION_ID = null; |
| | | pkg.SHELF_ID = null; |
| | | pkg.LOCATION_ID = null; |
| | | CurInvItem.History.Add(new WMS_ITEM_HIS(item, $"条码[{CurInvItem.SN}]从储位[{CurInvItem?.Location?.LOCATION_CODE}]发料下架成功,状态[{item.STATUS.GetEnumDesc<WMS_ITEM.STATUSs>()}],操作单据[{item.TRANS_NO}]")); |
| | | } |
| | | } |
| | | CurInvItem.Packages = WMS_ITEM_PKG.UpdateQty(CurInvItem.Packages); |
| | | |
| | | //创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值 |
| | | var _Items = CurInvItem.Items.Clone(); |
| | | var _Packages = CurInvItem.Packages.Clone(); |
| | | var _History = CurInvItem.History.Clone(); |
| | | var _ItemsExt = CurInvItem.ItemsExt.Clone(); |
| | | AddCommitAction("TakeDown", () => |
| | | { |
| | | //使用统一的事务DB对象 |
| | | var db = GetCommitDB(); |
| | | //数据保存逻辑 |
| | | db.Storageable(_Items, UserCode).ExecuteCommand(); |
| | | db.Insertable(_History, UserCode).ExecuteCommand(); |
| | | db.Storageable(_Packages, UserCode).ExecuteCommand(); |
| | | db.Storageable(_ItemsExt, UserCode).ToStorage().AsInsertable.ExecuteCommand(); |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.TakeDown.Exception", CurInvItem.SN, CurInvItem?.Location?.LOCATION_CODE)); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 设置当前条码的工序信息 |
| | | /// </summary> |
| | | public ApiAction<ScanOutput> SetOutPutMqttMsg(ApiAction<ScanOutput> action, string locale = null) |
| | | { |
| | | MQTT.Message msg = new() |
| | | { |
| | | IsSuccessed = action.IsSuccessed, |
| | | Content = Biz.T(action.LocaleMsg, locale), |
| | | }; |
| | | switch (action.Status) |
| | | { |
| | | case ApiAction.StatusCodes.Success: |
| | | msg.Voice = MQTT.Voice.Success; |
| | | msg.Color = "#FF1E90FF"; |
| | | break; |
| | | case ApiAction.StatusCodes.Warning: |
| | | msg.Voice = MQTT.Voice.Warning; |
| | | msg.Color = "#FFB8860B"; |
| | | break; |
| | | case ApiAction.StatusCodes.Error: |
| | | case ApiAction.StatusCodes.Failed: |
| | | msg.Voice = MQTT.Voice.Fail; |
| | | msg.Color = "#FFFF0000"; |
| | | break; |
| | | case ApiAction.StatusCodes.Exception: |
| | | msg.Voice = MQTT.Voice.Fail; |
| | | msg.Color = "#FF8B0000"; |
| | | break; |
| | | case ApiAction.StatusCodes.Normal: |
| | | case ApiAction.StatusCodes.NeedConfrim: |
| | | case ApiAction.StatusCodes.Confrimed: |
| | | default: |
| | | msg.Voice = MQTT.Voice.Silent; |
| | | msg.Color = "#FF000000"; |
| | | break; |
| | | } |
| | | if (action.IsSuccessed) |
| | | { |
| | | msg.Voice = MQTT.Voice.Pass; |
| | | msg.Color = "#FF228B22"; |
| | | } |
| | | else if (!action.IsSuccessed) |
| | | { |
| | | msg.Voice = MQTT.Voice.Fail; |
| | | msg.Color = "#FFFF0000"; |
| | | } |
| | | else |
| | | { |
| | | msg.Voice = MQTT.Voice.Silent; |
| | | msg.Color = "#FF000000"; |
| | | } |
| | | action.Data.MqttMsg = msg; |
| | | return action; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 设置当前物料的默认储位 |
| | | /// </summary> |
| | | public ApiAction<ScanOutput> SetDefaultLocation(DbClient db, BAS_ITEM Item, WMS_LOCATION location) |
| | | { |
| | | var action = new ApiAction<ScanOutput>(new ScanOutput()); |
| | | |
| | | //调用设置默认储位接口 |
| | | //var iInput = new CreateRcvLineLocationInput |
| | | //{ |
| | | |
| | | //}; |
| | | //var result = await DI.Resolve<IWMS_U9C>().CreateRcvLineLocation(iInput); |
| | | //if (!result.IsSuccessed) |
| | | //{ |
| | | // action.IsSuccessed = false; |
| | | // action.LocaleMsg = result.LocaleMsg; |
| | | //} |
| | | //else |
| | | { |
| | | Item.DEFAULT_LOCATION = location.LOCATION_CODE; |
| | | db.Updateable(Item, UserCode).UpdateColumns(q => new { q.DEFAULT_LOCATION, q.UPDATE_TIME, q.UPDATE_USER }).ExecuteCommand(); |
| | | } |
| | | |
| | | return action; |
| | | } |
| | | #endregion Functions |
| | | |
| | | /// <summary> |
| | | /// 重置本次扫码信息 |
| | | /// </summary> |
| | | public virtual void ResetScan() |
| | | { |
| | | //清理暂存数据提交操作 |
| | | DBCommitList.Clear(); |
| | | } |
| | | |
| | | public override bool Close(bool needSaveHistoryLog = false) |
| | | { |
| | | //needSaveHistoryLog = true; |