using Microsoft.CodeAnalysis;
|
using Rhea.Common;
|
using SqlSugar;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Threading.Tasks;
|
using Tiger.IBusiness;
|
using Tiger.Model;
|
|
namespace Tiger.Business.WMS
|
{
|
public class WMS_ITEM_Biz
|
{
|
private static _Biz_WmsItem _WmsItem = new();
|
|
/// <summary>
|
/// WMS_ITEM 业务
|
/// </summary>
|
public static _Biz_WmsItem WmsItem => _WmsItem;
|
|
/// <summary>
|
/// WMS_ITEM 业务类
|
/// </summary>
|
public partial class _Biz_WmsItem : IBiz_WmsItem
|
{
|
/// <summary>
|
/// 获取条码库存信息,包括仓库,储区,货架,储位,父条码,包装明细等
|
/// </summary>
|
/// <param name="sn">查询的条码</param>
|
/// <param name="option">授权查询选项</param>
|
/// <param name="doUnPack">是否同时执行拆包操作,解除与父条码之间的包装关系</param>
|
/// <returns></returns>
|
public Result<IInventory> Get(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>
|
/// 客供料专用:获取条码库存信息,包括仓库,储区,货架,储位,父条码,包装明细等
|
/// 注:物料编码自动加K判断和处理
|
/// </summary>
|
/// <param name="sn">查询的条码</param>
|
/// <param name="option">授权查询选项</param>
|
/// <param name="doUnPack">是否同时执行拆包操作,解除与父条码之间的包装关系</param>
|
/// <returns></returns>
|
public Result<IInventory> GetK(string sn, AuthOption option, bool doUnPack)
|
{
|
var result = new Result<IInventory>(Result.Flags.Success, new Inventory());
|
try
|
{
|
var inv = new Inventory();
|
Barcode barcode = new Barcode(sn);
|
barcode.ItemCode = (barcode.ItemCode.IsNullOrEmpty("K").StartsWith("K") ? "" : "K") + barcode.ItemCode;
|
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();
|
|
//包装表中找到条码
|
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>("pkg_wms_get_item_pkg", new SugarParameter("root", barcode.SN));
|
inv.Items = Biz.Db.Ado.UseStoredProcedure().SqlQuery<WMS_ITEM>("pkg_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>
|
/// 上架
|
/// </summary>
|
/// <param name="inventory">要上架的库存对象</param>
|
/// <param name="option">授权查询选项</param>
|
/// <param name="targetLocation">要上架的储位代码</param>
|
/// <param name="isTransfer">是否移库操作</param>
|
/// <returns></returns>
|
public Result<PutOnInfo> PutOn(IInventory inventory, AuthOption option, string targetLocation, bool isTransfer = false)
|
{
|
var result = new Result<PutOnInfo>(Result.Flags.Success, new PutOnInfo());
|
try
|
{
|
var inv = inventory as Inventory;
|
var location = Biz.Db.Queryable<V_WH_UNIT>().Where(q => q.LOCATION_CODE == targetLocation && q.AUTH_ORG == option.CurOrg).IncludesAllFirstLayer().First();
|
if (!location.IsNullOrEmpty())
|
{
|
result.Data.Warehouse = location.Warehouse;
|
result.Data.Region = location.Region;
|
result.Data.Shelf = location.Shelf;
|
result.Data.Location = location.Location;
|
foreach (var item in inventory.Items)
|
{
|
item.STATUS = WMS_ITEM.STATUSs.InStore.GetValue();
|
item.SUPP_LOTNO = inv.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;
|
inventory.History.Add(new WMS_ITEM_HIS(item, $"条码[{inventory.SN}]{(isTransfer ? "移库" : "上架")}到储位[{location.LOCATION_CODE}]成功{(isTransfer ? "" : $",操作单据[{item.TRANS_NO}]")}"));
|
}
|
foreach (var item in inventory.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 inventory.ItemsExt)
|
{
|
item.AUTH_ORG = option.OrgCode;
|
item.SN = inv.Barcode.SN;
|
}
|
|
result.Data.Items = inventory.Items;
|
result.Data.History = inventory.History;
|
result.Data.Packages = inventory.Packages;
|
result.Data.ItemsExt = inventory.ItemsExt;
|
}
|
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", inventory.SN, targetLocation));
|
}
|
return result;
|
}
|
|
/// <summary>
|
/// 下架
|
/// </summary>
|
/// <param name="inventory">要下架的库存对象</param>
|
/// <param name="option">授权查询选项</param>
|
/// <param name="status">下架后状态</param>
|
/// <param name="clearLocation">是否清理储区货架储位信息</param>
|
/// <returns></returns>
|
public Result<TakeDownInfo> TakeDown(IInventory inventory, AuthOption option, WMS_ITEM.STATUSs status, bool clearLocation = true)
|
{
|
return TakeDown(inventory, inventory.Items.ToDictionary(k => k.SN, v => v.QTY), option, status, clearLocation);
|
var result = new Result<TakeDownInfo>(Result.Flags.Success, new TakeDownInfo());
|
try
|
{
|
foreach (var item in inventory.Items)
|
{
|
item.STATUS = status.GetValue();
|
if (clearLocation)
|
{
|
//item.WH_ID = null;
|
item.REGION_ID = null;
|
item.SHELF_ID = null;
|
item.LOCATION_ID = null;
|
}
|
inventory.History.Add(new WMS_ITEM_HIS(item, $"条码[{inventory.SN}]从储位[{inventory?.Location?.LOCATION_CODE}]下架成功,操作单据[{item.TRANS_NO}]"));
|
}
|
foreach (var item in inventory.Packages)
|
{
|
if (clearLocation)
|
{
|
//item.WH_ID = null;
|
item.REGION_ID = null;
|
item.SHELF_ID = null;
|
item.LOCATION_ID = null;
|
}
|
}
|
result.Data.Items = inventory.Items;
|
result.Data.History = inventory.History;
|
result.Data.Packages = inventory.Packages;
|
}
|
catch (Exception ex)
|
{
|
result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.TakeDown.Exception", inventory.SN, inventory?.Location?.LOCATION_CODE));
|
}
|
return result;
|
}
|
|
/// <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<TakeDownInfo> TakeDown(IInventory inventory, Dictionary<string, decimal> qtyList, AuthOption option, WMS_ITEM.STATUSs status, bool clearLocation = true)
|
{
|
var result = new Result<TakeDownInfo>(Result.Flags.Success, new TakeDownInfo());
|
try
|
{
|
//如果要下架的数量字典为空则认为是全部下架
|
qtyList = qtyList.IsNullOrEmpty(inventory.Items.ToDictionary(k => k.SN, v => v.QTY));
|
|
foreach (var item in inventory.Items)
|
{
|
if (qtyList.ContainsKey(item.SN) && qtyList[item.SN] > 0)
|
{
|
var downQty = qtyList[item.SN];
|
if (item.QTY > downQty)
|
{
|
item.QTY -= downQty;
|
var pkg = inventory.Packages.First(q => q.SN == item.SN);
|
pkg.QTY = item.QTY;
|
}
|
else
|
{
|
item.STATUS = status.GetValue();
|
var pkg = inventory.Packages.First(q => q.SN == item.SN);
|
pkg.PARENT_SN = null;
|
pkg.Parent = null;
|
if (clearLocation)
|
{
|
//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;
|
}
|
}
|
inventory.History.Add(new WMS_ITEM_HIS(item, $"条码[{inventory.SN}]从储位[{inventory?.Location?.LOCATION_CODE}]下架数量[{downQty}]成功,状态[{item.STATUS.GetEnumDesc<WMS_ITEM.STATUSs>()}],操作单据[{item.TRANS_NO}]"));
|
}
|
}
|
inventory.Packages = WMS_ITEM_PKG.UpdateQty(inventory.Packages);
|
|
result.Data.Items = inventory.Items;
|
result.Data.History = inventory.History;
|
result.Data.Packages = inventory.Packages;
|
}
|
catch (Exception ex)
|
{
|
result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.TakeDown.Exception", inventory.SN, inventory?.Location?.LOCATION_CODE));
|
}
|
return result;
|
}
|
|
/// <summary>
|
/// 下架物料推荐,返回固定个数的最小包装物料库存列表
|
/// </summary>
|
/// <param name="order">领料单号</param>
|
/// <param name="itemCode">物料编码</param>
|
/// <param name="erpWH">物料的ERP库位</param>
|
/// <param name="whID">物料所在的仓库编码</param>
|
/// <param name="regionID">物料所在的储区编码</param>
|
/// <param name="shelfID">物料所在的货架编码</param>
|
/// <param name="option">授权查询选项</param>
|
/// <param name="returnCount">返回的最小包装物料个数,默认返回1个</param>
|
/// <returns></returns>
|
public Result<List<SuggestItem>> Suggest(string order, string itemCode, string erpWH, string whID, string regionID, string shelfID, AuthOption option, int returnCount = 1)
|
{
|
var result = new Result<List<SuggestItem>>(Result.Flags.Success, new List<SuggestItem>()) { LocaleMsg = new("WMS.WmsItem.Suggest.Success") };
|
try
|
{
|
var items = 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(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;
|
}
|
|
/// <summary>
|
/// 下架物料推荐,按需求数量返回满足需求的物料库存列表
|
/// </summary>
|
/// <param name="order">领料单号</param>
|
/// <param name="itemCode">物料编码</param>
|
/// <param name="erpWH">物料的ERP库位</param>
|
/// <param name="whID">物料所在的仓库编码</param>
|
/// <param name="regionID">物料所在的储区编码</param>
|
/// <param name="shelfID">物料所在的货架编码</param>
|
/// <param name="option">授权查询选项</param>
|
/// <param name="reqQty">需求数量,会返回满足需求的物料个数</param>
|
/// <returns></returns>
|
public Result<List<SuggestItem>> Suggest(string order, string itemCode, string erpWH, string whID, string regionID, string shelfID, AuthOption option, decimal reqQty)
|
{
|
var result = new Result<List<SuggestItem>>(Result.Flags.Success, new List<SuggestItem>()) { LocaleMsg = new("WMS.WmsItem.Suggest.Success") };
|
try
|
{
|
var takeCount = 0;
|
var checkSum = (decimal)0;
|
var checkCount = 0;
|
do
|
{
|
takeCount += 50;
|
var check = 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(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<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(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 = (decimal)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>
|
/// 根据SN返回相应的二维码
|
/// </summary>
|
/// <param name="sn"></param>
|
/// <returns></returns>
|
public string GetQRCode(string sn)
|
{
|
return Biz.Db.Queryable<WMS_ITEM>().Where(q => q.SN == sn).First()?.GetQRCode();
|
}
|
|
/// <summary>
|
/// 储位查询
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
public ApiAction<PageAble<V_WMS_ITEM>> QueryLocation(BasePageInput input)
|
{
|
var action = new ApiAction<PageAble<V_WMS_ITEM>>();
|
if (input.Code != "")
|
{
|
var query = Biz.Db.Queryable<V_WMS_ITEM>().ByAuth(input.AuthOption).Where(q => q.LOCATION_CODE == input.Code).ToPage(input.pageIndex, input.pageSize);
|
if (query.data.Count > 0)
|
{
|
action.Data = query;
|
}
|
else
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L("储位未找到有物品");
|
}
|
}
|
else
|
{
|
action.IsSuccessed = false;
|
}
|
return action;
|
}
|
|
/// <summary>
|
/// 物料汇总查询
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
public PageAble<V_WMS_ITEM> QueryItemSum(QueryItemInputDtl input)
|
{
|
var ItemCode = Biz.Db.Queryable<WMS_ITEM_PKG>().ByAuth(input.AuthOption).Where(q => q.SN == input.Code).First()?.ITEM_CODE ??
|
(input.IsK.IsNullOrEmpty() ? input.Code : (((bool)input.IsK ? "K" : "") + new Barcode(input.Code).ItemCode));
|
var itemInfo = Biz.Db.Queryable<BAS_ITEM>().Where(q => q.ITEM_CODE == ItemCode).First();
|
if (!itemInfo.IsNullOrEmpty())
|
{
|
var sumInfo = Biz.Db.Queryable<V_WMS_ITEM>().Where(q => q.ITEM_CODE == ItemCode && q.STATUS == WMS_ITEM.STATUSs.InStore.GetValue())
|
.ByAuth(input.AuthOption).GroupBy(q => new { q.WH_CODE, q.ITEM_CODE }).Select(q => new { WH_CODE = q.WH_CODE, SumQty = SqlFunc.AggregateSum(q.QTY) }).ToList();
|
var items = Biz.Db.Queryable<V_WMS_ITEM>().Where(q => q.ITEM_CODE == ItemCode && q.STATUS == WMS_ITEM.STATUSs.InStore.GetValue())
|
.ByAuth(input.AuthOption).ToPage(input.pageIndex, input.pageSize);
|
items.data2 = new { ItemCode = ItemCode, ItemName = itemInfo.ITEM_NAME, SumInfo = $"{string.Join("\r\n", sumInfo.Select(q => $"{q.WH_CODE}总库存: {(double)q.SumQty}"))}" };
|
return items;
|
}
|
else
|
{
|
throw new Exception("物料编码不存在");
|
}
|
}
|
}
|
}
|
|
/// <summary>
|
/// WMS_ITEM扩展方法
|
/// </summary>
|
public static class WMS_ITEMExtension
|
{
|
/// <summary>
|
/// 物料添加到物料池
|
/// </summary>
|
/// <param name="item"></param>
|
/// <param name="orgCode"></param>
|
/// <param name="transCode"></param>
|
/// <param name="transNo"></param>
|
/// <param name="transLine"></param>
|
/// <param name="actQty"></param>
|
/// <param name="isFirst"></param>
|
public static WMS_ITEM_POOL GetPoolItem(this WMS_ITEM item, string orgCode, string transCode, string transNo, string transLine, decimal actQty, bool isFirst)
|
{
|
var poolItem = new WMS_ITEM_POOL()
|
{
|
AUTH_ORG = orgCode,
|
TRANS_CODE = transCode,
|
TRANS_NO = transNo,
|
TRANS_LINE = transLine,
|
ITEM_CODE = item.ITEM_CODE,
|
SN = item.SN,
|
QTY = item.QTY,
|
ALLOC_QTY = actQty >= item.QTY ? item.QTY : actQty,
|
PROD_DATE = item.PROD_DATE,
|
LOCATION_ID = item.LOCATION_ID,
|
IS_FIRST = isFirst ? "Y" : "N",
|
ALLOC_MODE = actQty >= item.QTY ? WMS_ITEM_POOL.ALLOC_MODEs.AllAllocated.GetValue() : WMS_ITEM_POOL.ALLOC_MODEs.PartialAllocate.GetValue(),
|
STATUS = WMS_ITEM_POOL.STATUSs.WaitPick.GetValue(),
|
};
|
return poolItem;
|
}
|
|
/// <summary>
|
/// 获取相应二维码
|
/// </summary>
|
/// <param name="item"></param>
|
/// <returns></returns>
|
public static string GetQRCode(this WMS_ITEM item)
|
{
|
try
|
{
|
//var code = Biz.Db.Queryable<WMS_ITEM_EXT>().Where(q => q.SN == item.SN).First()?.QR_CODE;
|
var code = "";
|
if (code.IsNullOrEmpty() && !item.IsNullOrEmpty())
|
{
|
code += $"V{item.TRANS_NO},";
|
code += $"P{item.ITEM_CODE},";
|
code += $"Q{item.QTY},";
|
code += $"U{item.UNIT},";
|
code += $"M{item.ITEM_CODE},";
|
code += $"D{item.PROD_DATE:yyyyMMdd},";
|
code += $"L{item.SUPP_LOTNO.IsNullOrEmpty(item.PROD_DATE.ToString("yyyyMMdd"))},";
|
code += $"S{item.SN},";
|
code = code.IsNullOrEmpty(item?.SN, code.Substring(0, code.Length - 1));
|
}
|
return code;
|
}
|
catch (System.Exception ex)
|
{
|
return item?.SN;
|
}
|
}
|
|
/// <summary>
|
/// 获取组织编码
|
/// </summary>
|
/// <returns></returns>
|
public static List<string> GetOrgList()
|
{
|
var DB = Biz.DataSource["WMS57"].Client;
|
var dataList = Biz.Db.Queryable<SYS_ORGANIZATION>().Select(i => i.ORG_CODE).Distinct().ToList();// 获取组织编码
|
|
return dataList;
|
}
|
}
|
}
|