using Rhea.Common;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tiger.IBusiness;
using Tiger.Model;
using Tiger.Model.Entitys.MES.Position;
using static IronPython.Modules._ast;
namespace Tiger.Business.WMS.Transaction
{
///
/// 仓库作业任务,包括清点、上架、下架、移库、盘点等
///
public class WmsTask : WMSTransactionBase, IWmsTask
{
#region Propertys & Variables
public string UserCode { get; set; }
public string OrgCode { get; set; }
private DbClient _MainDB;
public DbClient MainDB => _MainDB;
private DbClient CommitDB;
public Inventory CurInvItem { get; set; }
public ScanShelfInfo CurScanShelf { get; set; }
///
/// 跟客户端通讯时的指令,有具体功能定义,默认为Normal
///
public string Command { get; set; } = "Normal";
///
/// 是否需要临时存储数据库提交操作,待需要的时候再提交
///
public bool NeedTemporaryStoreDBCommitAction { get; set; } = false;
protected Dictionary> DBCommitList { get; set; } = new();
#endregion Propertys & Variables
#region Functions
public IWmsTask Init(string id, string userCode, string apiHost, string orgCode)
{
TransID = id;
UserCode = userCode;
ApiHost = apiHost;
OrgCode = orgCode;
_MainDB = Biz.Db;
return this;
}
///
/// 获取提交数据的DbClient对象
///
///
public DbClient GetCommitDB()
{
return CommitDB ??= Biz.Db;
}
///
/// 增加暂存的数据库操作
///
/// 暂存的分组
/// 暂存的数据库操作
public void AddCommitAction(string group, Action action)
{
//增加附加的保存内容
if (!action.IsNullOrEmpty())
{
if (!DBCommitList.ContainsKey(group))
{
DBCommitList.Add(group, new List());
}
var commitList = DBCommitList[group];
commitList.Add(action);
}
}
///
/// 暂存的数据库操作提交到数据库
///
/// 附加的保存内容
public void SaveCommitListToDB(Action appendToSave = null)
{
//增加附加的保存内容
if (!appendToSave.IsNullOrEmpty())
{
if (!DBCommitList.ContainsKey("AppendSaveAction"))
{
DBCommitList.Add("AppendSaveAction", new List());
}
var appendList = DBCommitList["AppendSaveAction"];
appendList.Add(appendToSave);
}
//如果不需要临时存储数据库提交操作,则把提交操作列表提交到数据库
if (!NeedTemporaryStoreDBCommitAction)
{
//恢复临时存储标记为false
NeedTemporaryStoreDBCommitAction = false;
var dbTran = GetCommitDB().UseTran(() =>
{
//在同一个事务中保存所有工步的数据
foreach (var wipSn in DBCommitList.Keys.Where(q => q != "AppendSaveAction"))
{
foreach (var action in DBCommitList[wipSn])
{
action.Invoke();
}
}
//附加的保存内容
if (DBCommitList.ContainsKey("AppendSaveAction"))
{
foreach (var action in DBCommitList["AppendSaveAction"])
{
action.Invoke();
}
}
});
//保存成功则清空提交操作列表
DBCommitList.Clear();
if (!dbTran.IsSuccess)
{
//抛出异常
throw dbTran.ErrorException;
}
}
}
///
/// 获取条码库存信息,包括仓库,储区,货架,储位,父条码,包装明细等
///
/// 查询的条码
/// 授权查询选项
/// 是否同时执行拆包操作,解除与父条码之间的包装关系
///
public Result GetInventory(string sn, AuthOption option, bool doUnPack)
{
var result = new Result(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().ByAuth(option).Where(q => q.SN == barcode.SN).IncludesAllFirstLayer().First();
//var query = Biz.Db.Queryable().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("sp_wms_get_item_pkg", new SugarParameter("root", barcode.SN));
inv.Items = Biz.Db.Ado.UseStoredProcedure().SqlQuery("sp_wms_get_items", new SugarParameter("root", barcode.SN));
inv.ItemsExt = Biz.Db.Queryable().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().SetColumns(q => q.PARENT_SN == null).Where(q => q.ID == query.ID).ExecuteCommand();
db.Updateable().SetColumns(q => q.QTY == q.QTY - unPackQty).Where(q => q.ID == query.Parent.ID).ExecuteCommand();
if (!Biz.Db.Queryable().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().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;
}
///
/// 上架
///
/// 要上架的库存对象
/// 授权查询选项
/// 要上架的储位代码
/// 是否移库操作
///
public Result PutOn(AuthOption option, string targetLocation)
{
var result = new Result(Result.Flags.Success);
try
{
var location = Biz.Db.Queryable().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;
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;
item.WH_ID = location.WH_ID;
item.REGION_ID = location.REGION_ID;
item.SHELF_ID = location.SHELF_ID;
item.LOCATION_ID = location.LOCATION_ID;
CurInvItem.History.Add(new WMS_ITEM_HIS(item, $"条码[{CurInvItem.SN}]{(isTransfer ? $"从储位[{CurInvItem?.Location?.LOCATION_CODE}]移库" : "上架")}到储位[{location.LOCATION_CODE}]成功{(isTransfer ? "" : $",操作单据[{item.TRANS_NO}]")}"));
}
foreach (var item in CurInvItem.Packages)
{
item.WH_ID = location.WH_ID;
item.REGION_ID = location.REGION_ID;
item.SHELF_ID = location.SHELF_ID;
item.LOCATION_ID = location.LOCATION_ID;
}
foreach (var item in CurInvItem.ItemsExt)
{
item.AUTH_ORG = option.OrgCode;
item.SN = CurInvItem.Barcode.SN;
}
//更新储存信息
CurInvItem.Warehouse = location.Warehouse;
CurInvItem.Region = location.Region;
CurInvItem.Shelf = location.Shelf;
CurInvItem.Location = location.Location;
//创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值
var _Items = CurInvItem.Items.Clone();
var _Packages = CurInvItem.Packages.Clone();
var _History = CurInvItem.History.Clone();
var _ItemsExt = CurInvItem.ItemsExt.Clone();
AddCommitAction("PutOn", () =>
{
//使用统一的事务DB对象
var db = GetCommitDB();
//数据保存逻辑
db.Storageable(_Items, UserCode).ExecuteCommand();
db.Storageable(_Packages, UserCode).ExecuteCommand();
db.Insertable(_History, UserCode).ExecuteCommand();
var x = db.Storageable(_ItemsExt, UserCode).ToStorage();
x.AsInsertable.ExecuteCommand();//不存在插入
x.AsUpdateable.ExecuteCommand();//存在更新
});
}
else
{
result.Flag = Result.Flags.Failed;
result.LocaleMsg = new("WMS.WmsItem.PutOn.LocationNotExists", targetLocation);
}
}
catch (Exception ex)
{
result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.PutOn.Exception", CurInvItem.SN, targetLocation));
}
return result;
}
///
/// 下架物料推荐,返回固定个数的最小包装物料库存列表
///
/// 领料单号
/// 物料编码
/// 物料的ERP库位
/// 物料所在的仓库编码
/// 物料所在的储区编码
/// 物料所在的货架编码
/// 授权查询选项
/// 返回的最小包装物料个数,默认返回1个
///
public Result> Suggest(string order, string itemCode, string erpWH, string whID, string regionID, string shelfID, AuthOption option, int returnCount = 1)
{
var result = new Result>(Result.Flags.Success, new List()) { LocaleMsg = new("WMS.WmsItem.Suggest.Success") };
try
{
var items = Biz.Db.Queryable((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(option)
//允许使用已经分配到库存池中的物料
.Where((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID) || (!SqlFunc.IsNullOrEmpty(order) && p.STATUS <= WMS_ITEM_POOL.STATUSs.WaitPick.GetValue() && p.TRANS_NO == order))
//只允许未锁定的
.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(!erpWH.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ERP_WH == erpWH && q.AUTH_ORG == option.CurOrg)
//如果有传入仓库,则只允该仓库的物料
.WhereIF(!whID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.WH_ID == whID && q.AUTH_ORG == option.CurOrg)
//如果有传入储区,则只允该储区的物料
.WhereIF(!regionID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.REGION_ID == regionID && q.AUTH_ORG == option.CurOrg)
//如果有传入货架,则只允该货架的物料
.WhereIF(!shelfID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.SHELF_ID == shelfID && q.AUTH_ORG == option.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"))
//按生产日期先进先出,再按物料数量从小到大,最后按条码排序
.OrderBy((q, p, w, r, s, l) => q.PROD_DATE).OrderBy(q => q.QTY).OrderBy(q => q.SN)
.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;
}
///
/// 下架物料推荐,按需求数量返回满足需求的物料库存列表
///
/// 领料单号
/// 物料编码
/// 物料的ERP库位
/// 物料所在的仓库编码
/// 物料所在的储区编码
/// 物料所在的货架编码
/// 授权查询选项
/// 需求数量,会返回满足需求的物料个数
///
public Result> Suggest(string order, string itemCode, string erpWH, string whID, string regionID, string shelfID, AuthOption option, double reqQty)
{
var result = new Result>(Result.Flags.Success, new List()) { LocaleMsg = new("WMS.WmsItem.Suggest.Success") };
try
{
var takeCount = 0;
var checkSum = 0.0;
var checkCount = 0;
do
{
takeCount += 50;
var check = Biz.Db.Queryable((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(option)
//允许使用已经分配到库存池中的物料
.Where((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID) || (!SqlFunc.IsNullOrEmpty(order) && p.STATUS <= WMS_ITEM_POOL.STATUSs.WaitPick.GetValue() && p.TRANS_NO == order))
//只允许未锁定的
.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(!erpWH.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ERP_WH == erpWH && q.AUTH_ORG == option.CurOrg)
//如果有传入仓库,则只允该仓库的物料
.WhereIF(!whID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.WH_ID == whID && q.AUTH_ORG == option.CurOrg)
//如果有传入储区,则只允该储区的物料
.WhereIF(!regionID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.REGION_ID == regionID && q.AUTH_ORG == option.CurOrg)
//如果有传入货架,则只允该货架的物料
.WhereIF(!shelfID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.SHELF_ID == shelfID && q.AUTH_ORG == option.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"))
//按生产日期先进先出,再按物料数量从小到大,最后按条码排序
.OrderBy((q, p, w, r, s, l) => q.PROD_DATE).OrderBy(q => q.QTY).OrderBy(q => q.SN)
.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 = Biz.Db.Queryable((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(option)
//允许使用已经分配到库存池中的物料
.Where((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID) || (!SqlFunc.IsNullOrEmpty(order) && p.STATUS <= WMS_ITEM_POOL.STATUSs.WaitPick.GetValue() && p.TRANS_NO == order))
//只允许未锁定的
.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(!erpWH.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ERP_WH == erpWH && q.AUTH_ORG == option.CurOrg)
//如果有传入仓库,则只允该仓库的物料
.WhereIF(!whID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.WH_ID == whID && q.AUTH_ORG == option.CurOrg)
//如果有传入储区,则只允该储区的物料
.WhereIF(!regionID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.REGION_ID == regionID && q.AUTH_ORG == option.CurOrg)
//如果有传入货架,则只允该货架的物料
.WhereIF(!shelfID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.SHELF_ID == shelfID && q.AUTH_ORG == option.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"))
//按生产日期先进先出,再按物料数量从小到大,最后按条码排序
.OrderBy((q, p, w, r, s, l) => q.PROD_DATE).OrderBy(q => q.QTY).OrderBy(q => q.SN)
.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;
}
///
/// 下架
///
/// 授权查询选项
/// 下架后状态
/// 是否清理储区货架储位信息
///
public Result TakeDown(AuthOption option, WMS_ITEM.STATUSs status)
{
return TakeDown(CurInvItem.Items.ToDictionary(k => k.SN, v => v.QTY), option, status);
}
///
/// 下架
///
/// 要下架的最小包装数量字典,key:sn,value:qty
/// 授权查询选项
/// 下架后状态
///
public Result TakeDown(Dictionary qtyList, AuthOption option, WMS_ITEM.STATUSs status)
{
var result = new Result(Result.Flags.Success);
try
{
//如果要下架的数量字典为空则认为是全部下架
qtyList = qtyList.IsNullOrEmpty(CurInvItem.Items.ToDictionary(k => k.SN, v => v.QTY));
foreach (var item in CurInvItem.Items)
{
if (qtyList.ContainsKey(item.SN) && qtyList[item.SN] > 0)
{
var downQty = qtyList[item.SN];
if (item.QTY > downQty)
{
item.QTY -= downQty;
var pkg = CurInvItem.Packages.First(q => q.SN == item.SN);
pkg.QTY = item.QTY;
}
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;
//如果下架数量等于库存数量则清理储区货架储位信息,否则保留仓库信息
//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}]下架数量[{downQty}]成功,状态[{item.STATUS.GetEnumDesc()}],操作单据[{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();
AddCommitAction("TakeDown", () =>
{
//使用统一的事务DB对象
var db = GetCommitDB();
//数据保存逻辑
db.Updateable(_Items, UserCode).ExecuteCommand();
db.Insertable(_History, UserCode).ExecuteCommand();
db.Updateable(_Packages, UserCode).ExecuteCommand();
});
}
catch (Exception ex)
{
result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.TakeDown.Exception", CurInvItem.SN, CurInvItem?.Location?.LOCATION_CODE));
}
return result;
}
///
/// 备料下架
///
/// 要下架的最小包装数量字典,key:sn,value:qty
/// 授权查询选项
/// 下架后状态
///
public Result TakeDown(List 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()}],原条码[{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()}],操作单据[{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;
}
///
/// 设置当前条码的工序信息
///
public ApiAction SetOutPutMqttMsg(ApiAction 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;
}
#endregion Functions
///
/// 重置本次扫码信息
///
public virtual void ResetScan()
{
//清理暂存数据提交操作
DBCommitList.Clear();
}
public override bool Close(bool needSaveHistoryLog = false)
{
//needSaveHistoryLog = true;
//保存操作日志
this.IsFinished = true;
return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished;
}
}
}