using MES.Service.DB; using MES.Service.Dto.webApi; using MES.Service.Modes; using MES.Service.util; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; namespace MES.Service.service; /// /// 收料单数据管理类(处理ERP收料单数据同步到MES收料单表) /// 关联主表:MesInvItemArn,明细表:MesInvItemArnDetail /// 关联ERP DTO:ErpSltz(聚合类)、ErpSltza(ERP主表)、ErpSltzBList(ERP明细) /// public class MesInvItemArnManager : Repository { /// /// 批量保存收料单(主表+明细)- 事务保证批量操作一致性 /// /// ERP收料单列表(含主表+明细) /// 全部成功返回true,否则false public bool SaveList(List erpSltzList) { if (erpSltzList == null || !erpSltzList.Any()) throw new ArgumentNullException(nameof(erpSltzList), "待保存的收料单列表不能为空"); // 修复:用事务包裹批量操作,确保数据一致性 return UseTransaction(db => { foreach (var erpSltz in erpSltzList) { // 修复:调用事务内的Save方法,传入db实例 if (!Save(db, erpSltz)) { return 0; // 单条失败,事务回滚 } } return 1; // 全部成功 }) > 0; } /// /// 单条保存收料单(主表+明细)- 事务内调用(修正访问修饰符,确保事务内可用) /// /// 事务内的SqlSugar实例 /// ERP收料单(含主表+明细) /// 单条处理成功返回true private bool Save(SqlSugarScope db, ErpSltz erpSltz) { // 1. 参数校验 if (erpSltz == null) throw new ArgumentNullException(nameof(erpSltz), "收料单数据不能为空"); if (erpSltz.ErpSltza == null) throw new ArgumentNullException(nameof(erpSltz.ErpSltza), "收料单主表数据不能为空"); // 2. 提取ERP主表和明细数据 var erpMain = erpSltz.ErpSltza; var erpDetails = erpSltz.ErpSltzBList ?? new List(); // 3. 修复:用事务内的db查询,确保数据一致性 Guid mainId = GetOrCreateMainId(db, erpMain); // 4. 映射ERP数据到MES实体(修复字段注释,补充关键属性) var mesMain = MapErpSltzaToMesInvItemArn(erpMain, mainId); var mesDetails = MapErpSltzBListToMesInvItemArnDetail(erpDetails, mainId); // 5. 根据操作类型处理数据 switch (erpMain.TYPE?.Trim()) { case "1": // 新增 case "2": // 更新 return HandleSaveOrUpdate(db, mesMain, mesDetails, mainId); case "3": // 删除 return HandleDelete(db, mesMain, mesDetails, mainId); default: throw new NotImplementedException($"未实现的收料单操作类型:{erpMain.TYPE}(支持类型:1-新增,2-更新,3-删除)"); } } /// /// 单条保存收料单(主表+明细)- 对外公开接口(供控制器调用) /// /// ERP收料单数据(含主表+明细) /// 保存成功返回true public bool Save(ErpSltz erpSltz) { if (erpSltz == null) throw new ArgumentNullException(nameof(erpSltz), "收料单数据不能为空"); if (erpSltz.ErpSltza == null) throw new ArgumentNullException(nameof(erpSltz.ErpSltza), "收料单主表数据不能为空"); // 事务内处理主从表保存 return UseTransaction(db => { return Save(db, erpSltz) ? 1 : 0; }) > 0; } /// /// 提前获取或生成MES主表ID(修复:用事务内db查询) /// private Guid GetOrCreateMainId(SqlSugarScope db, ErpSltza erpMain) { if (string.IsNullOrEmpty(erpMain.billNo)) throw new ArgumentException("ERP收料单单据号不能为空,无法确定主表唯一性", nameof(erpMain.billNo)); // 修复:用事务内的db查询,而非Context var existingMain = db.Queryable() .Where(m => m.BillNo == erpMain.billNo) .First(); return existingMain != null ? existingMain.Id : Guid.NewGuid(); } /// /// 处理收料单新增/更新(主表+明细) /// private bool HandleSaveOrUpdate(SqlSugarScope db, MesInvItemArn mesMain, List mesDetails, Guid mainId) { mesMain.Id = mainId; bool isMainExist = db.Queryable().Where(m => m.Id == mainId).Any(); int mainOperateResult; if (isMainExist) { mainOperateResult = db.Updateable(mesMain) .IgnoreColumns(m => new { m.CreateDate }) .Where(m => m.Id == mainId) .ExecuteCommand(); } else { mesMain.CreateDate = DateTime.Now; mainOperateResult = db.Insertable(mesMain).ExecuteCommand(); } // 处理明细 int deleteOldDetailResult = db.Deleteable() .Where(d => d.Mid == mainId) .ExecuteCommand(); int insertNewDetailResult = mesDetails.Count > 0 ? db.Insertable(mesDetails).ExecuteCommand() : 1; return mainOperateResult > 0 && (deleteOldDetailResult >= 0 && insertNewDetailResult > 0); } /// /// 处理收料单删除(主表+明细) /// private bool HandleDelete(SqlSugarScope db, MesInvItemArn mesMain, List mesDetails, Guid mainId) { db.Deleteable().Where(d => d.Mid == mainId).ExecuteCommand(); int mainDeleteResult = db.Deleteable().Where(m => m.Id == mainId).ExecuteCommand(); return mainDeleteResult >= 0; } /// /// ERP主表映射到MES主表(修复:取消关键字段注释,修正FType逻辑) /// private MesInvItemArn MapErpSltzaToMesInvItemArn(ErpSltza erpMain, Guid mainId) { // 单据日期转换 DateTime.TryParse(erpMain.FDate, out DateTime parsedDate); // 是否SRM转换(0-否,1-是) int.TryParse(erpMain.F_ZJXF_sfgx, out int isSrm); // 供应商ID转换(字符串直接赋值,匹配MES字段类型) string suppId = string.IsNullOrEmpty(erpMain.SupplierId) ? null : erpMain.SupplierId.Trim(); // 修复:“是否委外”逻辑(假设ERP的fType是“1”=是,“0”=否,或bool字符串) bool isOutsourcing = false; if (!string.IsNullOrEmpty(erpMain.fType)) { isOutsourcing = erpMain.fType.Trim() == "1" || erpMain.fType.Trim().Equals("true", StringComparison.OrdinalIgnoreCase); } return new MesInvItemArn { // 修复:取消关键字段注释,补充赋值 Id = mainId, BillNo = erpMain.billNo?.Trim() ?? throw new ArgumentException("收料单单据号不能为空"), SuppId = suppId, CreateDate = parsedDate == DateTime.MinValue ? null : (DateTime?)parsedDate, Remark = erpMain.Remark?.Trim(), IsSrm = isSrm, EbelnK3id = erpMain.erpId?.Trim(), // ERP主表ID(对应ebeln_k3id) CreateBy = erpMain.createBy?.Trim() ?? "SYSTEM", // 默认为系统 FType = isOutsourcing, // 修复:正确的是否委外逻辑 ReceiveOrgId = erpMain.ReceiveOrgId?.Trim(), // LastUpdateUser = erpMain.FCreatorId?.Trim() ?? "SYSTEM", // LastUpdateTime = DateTime.Now, // IsOut = false, // 初始未出库 // Status = false // 初始未审核 }; } /// /// ERP明细映射到MES明细(修复:取消关键字段注释,修正EbelnK3id转换) /// private List MapErpSltzBListToMesInvItemArnDetail(List erpDetails, Guid mainId) { return erpDetails.Select(erpDetail => { // 数值类型安全转换 int.TryParse(erpDetail.LineNo, out int lineNo); // 明细主键 int.TryParse(erpDetail.ProductCode, out int itemId); // 物料编码 decimal.TryParse(erpDetail.PurchaseQty, out decimal purchaseQty); // 采购订单数量 decimal.TryParse(erpDetail.DeliveryQty, out decimal deliveryQty); // 本次应收数量 decimal.TryParse(erpDetail.IncludeQty, out decimal includeQty); // 本次实收数量 // 修复:用采购单ID字段(ebeln_k3id)转int,而非源单单号 int.TryParse(erpDetail.FSrcBillNo, out int ebelnK3id); int.TryParse(erpDetail.FSrcBillLine, out int lineK3id); // 采购单行ID bool.TryParse(erpDetail.urgentFlag, out bool urgentFlag); // 急料标识 return new MesInvItemArnDetail { // 修复:取消关键字段注释,补充赋值 // LineNo = lineNo, // 明细主键(必须赋值) Mid = mainId, // 外键(关联主表ID,必须赋值) Ebeln = erpDetail.FBillNo?.Trim(), // 采购单号 ItemId = itemId, EbelnQty = purchaseQty, SubQty = deliveryQty, Quantity = includeQty, // PurchaseUnit = erpDetail.PurchaseUnit?.Trim(), // 采购单位(补充赋值) // InventoryUnit = erpDetail.InventoryUnit?.Trim(), // 库存单位(补充赋值) Memo = erpDetail.Remark?.Trim(), EbelnK3id = ebelnK3id, // 修复:正确的采购单ID转换 LineK3id = lineK3id, // SalesOrderId = erpDetail.SalesOrderId?.Trim(), // 销售订单号(补充赋值) // FMtoNo = erpDetail.FMtoNo?.Trim(), // 计划跟踪号(补充赋值) // FLot = erpDetail.FLot?.Trim(), // 批号(补充赋值) UrgentFlag = urgentFlag //FStockId = erpDetail.DepotId?.Trim() // 收货仓库编号 }; }).ToList(); } /// /// 按单据号查询MES收料单(主表+明细) /// public (MesInvItemArn main, List details) GetByBillNo(string billNo) { if (string.IsNullOrEmpty(billNo)) throw new ArgumentNullException(nameof(billNo), "查询条件单据号不能为空"); var main = Context.Queryable() .Where(m => m.BillNo == billNo) .First(); var details = main != null ? Context.Queryable() .Where(d => d.Mid == main.Id) .ToList() : new List(); return (main, details); } }