using Rhea.Common;
|
using Microsoft.AspNetCore.Http;
|
using SqlSugar;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Linq.Expressions;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using Tiger.Model;
|
|
using Newtonsoft.Json;
|
using Tiger.IBusiness;
|
|
namespace Tiger.Business.WMS.Transaction
|
{
|
/// <summary>
|
/// 生产领料事务
|
/// </summary>
|
public class OutSplit : WMSTransactionBase, IOutSplit
|
{
|
public IOutSplit Init(string id, string userCode, string apiHost, string orgCode, string fty)
|
{
|
TransID = id;
|
UserCode = userCode;
|
ApiHost = apiHost;
|
OrgCode = orgCode;
|
FTY_CODE = fty;
|
Logger.Console.Info($"Start {this.GetType().Name} Transaction[ID: {TransID}]");
|
return this;
|
}
|
|
#region Propertys & Variables
|
public string UserCode { get; set; }
|
public long UserId { get; set; }
|
public string OrgCode { get; set; }
|
public string FTY_CODE { get; set; }
|
public string ReqNo { get; set; }
|
public string ExceedTranId { get; set; }
|
public Inventory CurInv { get; set; }
|
public ProductionPickToMes toMes { get; set; }
|
public AuthOption option { get; set; }
|
#endregion
|
|
#region Functions
|
|
/// <summary>
|
/// 拆批扫描物料条码
|
/// </summary>
|
/// <param name="input"></param>
|
/// <returns></returns>
|
public async Task<ApiAction<OutSplitOutput>> ScanItem(OutSplitInput input)
|
{
|
var action = new ApiAction<OutSplitOutput>();
|
try
|
{
|
if (input.SN.IsNullOrEmpty())
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L("条码不能为空");
|
return action;
|
}
|
//解析条码
|
Result<IInventory> result = WMS_ITEM_Biz.WmsItem.Get(input.SN, input.AuthOption, true);
|
if (!result.IsSuccessed)
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = result.LocaleMsg;
|
return action;
|
}
|
CurInv = result.Data as Inventory;
|
if (string.IsNullOrEmpty(CurInv.ItemInfo?.ITEM_CODE))
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L("WMS.InReceipt.ScanItem.NotFound", CurInv.ItemInfo?.ITEM_CODE);
|
return action;
|
}
|
//物料验证
|
if (CurInv.ItemInfo.IsNullOrEmpty() || CurInv.ItemInfo.IS_ACTIVE == "N")
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L("WMS.ProdMReq.ScanItem.ItemCodeNotExistsOrNotActive", CurInv.ItemInfo.ITEM_CODE.IsNullOrEmpty(CurInv.Barcode.ItemCode));
|
return action;
|
}
|
if (!CurInv.isExists || CurInv.Status == WMS_ITEM.STATUSs.WaitIn)
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L("WMS.InReceipt.ScanItem.NotExist", CurInv.SN); //条码[{0}]不存在于系统中
|
return action;
|
}
|
|
ReqNo = input.ReqNo;
|
ExceedTranId = input.ExceedTranId;
|
option = input.AuthOption;
|
|
action.LocaleMsg = Biz.L($"条码[{CurInv.CurPkg.SN}]扫描成功!");
|
action.Data = new OutSplitOutput() {
|
MaterialCode = CurInv.ItemInfo.ITEM_CODE,
|
MaterialName = CurInv.ItemInfo.ITEM_NAME,
|
SupplierCode = CurInv.Items[0].SUPP_CODE,
|
Barcode = CurInv.SN, //批次号即为条码
|
DateCode = CurInv.Items[0].PROD_DATE,
|
LotNo = CurInv.Barcode.LotNo,
|
ScanQty = CurInv.CurPkg.QTY, //批次数量
|
Unit = CurInv.ItemInfo.UNIT
|
};
|
|
}
|
catch (Exception ex)
|
{
|
action.CatchExceptionWithLog(ex, $"扫描物料[{input.SN}]复核异常");
|
}
|
|
return action;
|
|
}
|
|
/// <summary>
|
/// 拆分
|
/// </summary>
|
/// <param name="splitNum"></param>
|
/// <returns></returns>
|
public async Task<ApiAction<OutSplitSubmit>> SplitBarcodeRecord(string qty)
|
{
|
var action = new ApiAction<OutSplitSubmit>();
|
try
|
{
|
Logger.Interface.Info($"拆包 => [{CurInv.SN}]正在准备开始执行拆包操作......");
|
int splitNum = Convert.ToInt32(qty);
|
if (splitNum >= CurInv.CurPkg.QTY || splitNum <= 0)
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L($"拆批数量有误!");
|
return action;
|
}
|
Logger.Interface.Info($"拆包 => [{CurInv.SN}]当前数量[{CurInv.CurPkg.QTY}],实际数量[{splitNum}]");
|
|
//获取供应商信息
|
var vender = await Biz.Db.Queryable<BAS_SUPPLIER>().Where(t => t.SUPP_CODE == CurInv.Items[0].SUPP_CODE).FirstAsync();
|
|
//生成条码
|
var cutSerial = Convert.ToString(CurInv.Barcode.ReprintNo ?? 0, 2);
|
cutSerial = cutSerial == "0" ? "1" : cutSerial;
|
var orglSn = CurInv.SN.Split("_")[0];
|
|
var nSplitSn = $"{orglSn}_CA{Convert.ToString(Convert.ToInt32(cutSerial + "0", 2), 16).ToUpper()}";
|
var nRemainSn = $"{orglSn}_CB{Convert.ToString(Convert.ToInt32(cutSerial + "1", 2), 16).ToUpper()}";
|
|
if (Biz.Db.Queryable<WMS_ITEM>().Any(t => t.SN == nRemainSn))
|
{
|
//throw new UserFriendlyException(1011, "生成的拆批条码已存在!", vender != null ? vender.VenderSName : "");
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L($"生成的拆批条码已存在!供应商:{vender?.SUPP_NAME_CN}");
|
return action;
|
}
|
|
//#region 操作条码信息
|
|
//条码一
|
var nSplitBarcode1 = CurInv.Items[0];
|
var nSplitBarcode2 = CurInv.Items[0].Clone();
|
nSplitBarcode1.SN = nSplitSn;
|
//nSplitBarcode1.BarcodeStatus = (int)Domain.InvStorageInfoSides.BarcodeStatus.Outstock; //出库状态
|
nSplitBarcode1.QTY = splitNum;
|
nSplitBarcode1.TRANS_CODE = nameof(OutSplit);
|
if (!ReqNo.IsNullOrEmpty())
|
{
|
nSplitBarcode1.STATUS = WMS_ITEM.STATUSs.Sended.GetValue();
|
nSplitBarcode1.LOCATION_ID = "";
|
nSplitBarcode1.REGION_ID = "";
|
nSplitBarcode1.WH_ID = "";
|
nSplitBarcode1.SHELF_ID = "";
|
}
|
|
var nSplitPgk1 = CurInv.CurPkg;
|
var nSplitPgk2 = CurInv.CurPkg.Clone();
|
nSplitPgk1.SN = nSplitSn;
|
nSplitPgk1.QTY = splitNum;
|
if (!ReqNo.IsNullOrEmpty())
|
{
|
nSplitPgk1.LOCATION_ID = "";
|
nSplitPgk1.REGION_ID = "";
|
nSplitPgk1.WH_ID = "";
|
nSplitPgk1.SHELF_ID = "";
|
}
|
|
//条码二
|
nSplitBarcode2.SN = nRemainSn;
|
var currentQty = nSplitBarcode2.QTY;//原条码实际数量
|
nSplitBarcode2.QTY = nSplitBarcode2.QTY - splitNum; //拆分后剩下的数量
|
nSplitBarcode2.ID = Guid.NewGuid().ToString("N");
|
nSplitBarcode2.TRANS_CODE = nameof(OutSplit);
|
if (!ReqNo.IsNullOrEmpty())
|
{
|
nSplitBarcode2.STATUS = WMS_ITEM.STATUSs.InStore.GetValue();
|
}
|
nSplitPgk2.SN = nRemainSn;
|
nSplitPgk2.QTY = nSplitBarcode2.QTY;
|
nSplitPgk2.ID = Guid.NewGuid().ToString("N");
|
|
string msg = ReqNo.IsNullOrEmpty() ? $"手工拆分物料:原条码[{CurInv.SN},条码一[{nSplitBarcode1.SN}],条码二[{nSplitBarcode2.SN}]]" : $"自动拆分物料:单据[{ReqNo}],原条码[{CurInv.SN},发料条码[{nSplitBarcode1.SN}],需要上架条码[{nSplitBarcode2.SN}]]";
|
|
if (!ExceedTranId.IsNullOrEmpty())
|
{
|
var MaterialReqTrans = Biz.Db.Queryable<BIZ_ERP_PROD_OUT>().Where(t => t.BILLCODE == ReqNo).Any();
|
var OthReqTrans = Biz.Db.Queryable<BIZ_ERP_OTH_OUT>().Where(t => t.BILLCODE == ReqNo).Any();
|
var SaleReqTrans = Biz.Db.Queryable<BIZ_ERP_SALE_OUT>().Where(t => t.BILLCODE == ReqNo).Any();
|
var TfTrans = Biz.Db.Queryable<BIZ_WMS_TRANSFER>().Where(t => t.BILLCODE == ReqNo).Any();
|
ProductionMaterialReq trans = null;
|
OutWorkOrder owoTrans = null;
|
OutOther othTrans = null;
|
OutSale saleTrans = null;
|
OutTransfer tfTrans = null;
|
if (WMSContext.TransactionDic.ContainsKey(ExceedTranId))
|
{
|
trans = WMSContext.TransactionDic[ExceedTranId] as ProductionMaterialReq;
|
othTrans = WMSContext.TransactionDic[ExceedTranId] as OutOther;
|
saleTrans = WMSContext.TransactionDic[ExceedTranId] as OutSale;
|
tfTrans = WMSContext.TransactionDic[ExceedTranId] as OutTransfer;
|
//领料单发料或者工单发料
|
if (MaterialReqTrans)
|
{
|
if (trans == null)
|
{
|
owoTrans = WMSContext.TransactionDic[ExceedTranId] as OutWorkOrder;
|
if (!owoTrans.IsFinished)
|
{
|
lock (owoTrans.TransLock)
|
{
|
Logger.Interface.Info($"自动拆包 => 返回工单发料事务[{ExceedTranId}],开始确认发料并保存数据。");
|
var response = owoTrans.ConfirmExceed(new()
|
{
|
isExceed = true,
|
AuthOption = option
|
}).Result;
|
action.IsSuccessed = response.IsSuccessed;
|
action.LocaleMsg = response.IsSuccessed ? Biz.L(msg) : Biz.L(response.Message);
|
}
|
}
|
else
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L($"Transaction Error: 工单领料事务[ID:{ExceedTranId}]已经关闭,请重新打开工单领料功能");
|
}
|
}
|
else
|
{
|
if (!trans.IsFinished)
|
{
|
lock (trans.TransLock)
|
{
|
Logger.Interface.Info($"自动拆包 => 返回领料单发料事务[{ExceedTranId}],开始确认发料并保存数据。");
|
var response = trans.ConfirmExceed(new()
|
{
|
isExceed = true,
|
AuthOption = option
|
}).Result;
|
action.IsSuccessed = response.IsSuccessed;
|
action.LocaleMsg = response.IsSuccessed ? Biz.L(msg) : Biz.L(response.Message);
|
}
|
}
|
else
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L($"Transaction Error: 生产领料事务[ID:{ExceedTranId}]已经关闭,请重新打开生产领料功能");
|
}
|
}
|
}
|
//其他出库发料
|
if (OthReqTrans)
|
{
|
if (!othTrans.IsFinished)
|
{
|
lock (othTrans.TransLock)
|
{
|
Logger.Interface.Info($"自动拆包 => 返回其他出库发料事务[{ExceedTranId}],开始确认发料并保存数据。");
|
var response = othTrans.ConfirmExceed(new()
|
{
|
isExceed = "true",
|
AuthOption = option
|
}).Result;
|
action.IsSuccessed = response.IsSuccessed;
|
action.LocaleMsg = response.IsSuccessed ? Biz.L(msg) : Biz.L(response.Message);
|
}
|
}
|
else
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L($"Transaction Error: 其他出库事务[ID:{ExceedTranId}]已经关闭,请重新打开其他出库功能");
|
}
|
}
|
//销售出库发料
|
//if (SaleReqTrans)
|
//{
|
// if (!saleTrans.IsFinished)
|
// {
|
// lock (saleTrans.TransLock)
|
// {
|
// Logger.Interface.Info($"自动拆包 => 返回销售出库发料事务[{ExceedTranId}],开始确认发料并保存数据。");
|
// var response = saleTrans.ConfirmExceed(new()
|
// {
|
// isExceed = true,
|
// AuthOption = option
|
// }).Result;
|
// action.IsSuccessed = response.IsSuccessed;
|
// action.LocaleMsg = response.IsSuccessed ? Biz.L(msg) : Biz.L(response.Message);
|
// }
|
// }
|
// else
|
// {
|
// action.IsSuccessed = false;
|
// action.LocaleMsg = Biz.L($"Transaction Error: 销售出库事务[ID:{ExceedTranId}]已经关闭,请重新打开销售出库功能");
|
// }
|
//}
|
//调拨出库发料
|
if (TfTrans)
|
{
|
if (!tfTrans.IsFinished)
|
{
|
lock (tfTrans.TransLock)
|
{
|
Logger.Interface.Info($"自动拆包 => 返回调拨出库发料事务[{ExceedTranId}],开始确认发料并保存数据。");
|
var response = tfTrans.ConfirmExceed(new()
|
{
|
isExceed = "true",
|
AuthOption = option
|
}).Result;
|
action.IsSuccessed = response.IsSuccessed;
|
action.LocaleMsg = response.IsSuccessed ? Biz.L(msg) : Biz.L(response.Message);
|
}
|
}
|
else
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L($"Transaction Error: 调拨出库事务[ID:{ExceedTranId}]已经关闭,请重新打开调拨出库功能");
|
}
|
}
|
}
|
else
|
{
|
action.IsSuccessed = false;
|
action.LocaleMsg = Biz.L($"Transaction Error: 事务[ID:{ExceedTranId}]已经关闭,请重新打开功能");
|
}
|
action.LocaleMsg = action.IsSuccessed ? Biz.L(msg) : action.LocaleMsg;
|
}
|
|
if (action.IsSuccessed)
|
{
|
//保存数据库
|
var db = Business.Biz.Db;
|
var dbTran = db.UseTran(() =>
|
{//入库
|
db.Updateable(nSplitBarcode1, UserCode).ExecuteCommand();
|
db.Insertable(new WMS_ITEM_HIS(nSplitBarcode1, msg), UserCode).ExecuteCommand();
|
db.Insertable(nSplitBarcode2, UserCode).ExecuteCommand();
|
db.Insertable(new WMS_ITEM_HIS(nSplitBarcode2, msg), UserCode).ExecuteCommand();
|
db.Updateable(nSplitPgk1, UserCode).ExecuteCommand();
|
db.Insertable(nSplitPgk2, UserCode).ExecuteCommand();
|
});
|
if (!dbTran.IsSuccess)
|
{
|
Logger.Default.Fatal(dbTran.ErrorException, "Database transaction save exception");
|
this.Close(!dbTran.IsSuccess);
|
throw dbTran.ErrorException;
|
}
|
|
//通过工厂带出 MES api 和 agv api
|
MES_FACTORY _factory = db.Queryable<MES_FACTORY>()
|
.Where(x => x.FTY_CODE == FTY_CODE)
|
.First();
|
//发送到MES
|
if (Cache.SysParam["IsSend", "SendToMES"].PARAM_VALUE.ToString() == "Y" && !ReqNo.IsNullOrEmpty() && Biz.Db.Queryable<BIZ_ERP_PROD_OUT>().Where(x => x.BILLCODE == ReqNo).Any())
|
{
|
var dtl = Biz.Db.Queryable<BIZ_ERP_PROD_OUT_DTL>().Where(x => x.BILLCODE == ReqNo).First();
|
var sourcecode = dtl != null ? dtl.SOURCECODE : "";
|
var query = Biz.Db.Queryable<WMS_SCTRWO_TRANSFER>().Where(x => x.ORIGINAL_WORKORDER == sourcecode).First();
|
var sctrwo = query != null ? (query.TARGET_WORKORDER.IsNullOrEmpty() ? sourcecode : query.TARGET_WORKORDER) : sourcecode;
|
toMes = new ProductionPickToMes()
|
{
|
qrcode = WMS_ITEM_Biz.WmsItem.GetQRCode(nSplitBarcode1.SN),
|
wo = sctrwo, // nCurrentLines.First().SourceCode,
|
pkgid = nSplitBarcode1.SN,
|
mfrkp = CurInv.Barcode.OEMItemCode,
|
kpno = CurInv.ItemInfo.ITEM_CODE,
|
dc = CurInv.Barcode.ProdDateStr,
|
lc = CurInv.Barcode.LotNo,
|
qty = nSplitBarcode1.QTY.ToString(),
|
erpBillCode = ReqNo, //MES接口增加字段,返回备料完成的当前领料单号 2023/05/17 Ben Lin
|
taskid = ""
|
};
|
var mesApi = _factory != null ? _factory.MES_API : Cache.SysParam["apiUrl", "SendToMES"].PARAM_VALUE.ToString();
|
var res = HttpHelper.PostAsync(mesApi, JsonConvert.SerializeObject(toMes)).Result;
|
var _action = JsonConvert.DeserializeObject<ApiAction>(res.Message);
|
Logger.Interface.Info($"生产领料-自动拆分物料 =>拆分物料发料发送MES完成,单号:[{ReqNo}],MES传入Json:{JsonConvert.SerializeObject(toMes)},MES返回:{res.Message}");
|
}
|
}
|
|
action.Data = new OutSplitSubmit() {
|
nRemainSn = nRemainSn,
|
nSplitSn = nSplitSn,
|
SupplierCode = vender?.SUPP_CODE,
|
};
|
}
|
catch (Exception ex)
|
{
|
action.CatchExceptionWithLog(ex, $"系统异常");
|
}
|
return action;
|
}
|
|
private ApiAction Confirm<T>(T trans) {
|
ApiAction action = new ApiAction();
|
|
return action;
|
}
|
|
/// <summary>
|
/// 添加一个ApiAction的历史记录
|
/// </summary>
|
/// <param name="action"></param>
|
public override void AddHistory<T>(Microsoft.AspNetCore.Http.HttpRequest request, ApiAction<T> action)
|
{
|
var his = action.History();
|
//his.TraceDic.Add("CurReqType", CurReqType);
|
//his.TraceDic.Add("CurInv", CurInv);
|
//his.TraceDic.Add("req", req);
|
//his.TraceDic.Add("toMes", toMes);
|
//his.TraceDic.Add("CurPoolList", CurPoolList);
|
ActionHistoryList.Add($"{request.HttpContext.TraceIdentifier} at {action.Timestamp:yyyy/MM/dd HH:mm:ss.fff}: {request.Path}", his);
|
LastActionTime = DateTime.Now;
|
}
|
|
#endregion
|
|
public override bool Close(bool needSaveHistoryLog = false)
|
{
|
//needSaveHistoryLog = true;
|
//保存操作日志
|
|
this.IsFinished = true;
|
return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished;
|
}
|
|
}//endClass
|
}
|