| | |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | |
| | | namespace MES.Service.service; |
| | | |
| | | /// <summary> |
| | | /// 收料单数据管理类(处理ERP收料单数据同步到MES收料单表) |
| | | /// 关联主表:MesInvItemArn,明细表:MesInvItemArnDetail |
| | | /// 关联ERP DTO:ErpSltz(聚合类)、ErpSltza(ERP主表)、ErpSltzBList(ERP明细) |
| | | /// </summary> |
| | | public class MesInvItemArnManager : Repository<MesInvItemArn> |
| | | namespace MES.Service.service |
| | | { |
| | | /// <summary> |
| | | /// 批量保存收料单(主表+明细)- 事务保证批量操作一致性 |
| | | /// 收料单数据管理类(处理ERP收料单数据同步到MES收料单表) |
| | | /// 关联主表:MesInvItemArn(MES收料单主表) |
| | | /// 关联明细表:MesInvItemArnDetail(MES收料单明细表) |
| | | /// 关联ERP DTO:ErpSltz(聚合类,含主表+明细)、ErpSltza(ERP收料单主表)、ErpSltzBList(ERP收料单明细) |
| | | /// </summary> |
| | | /// <param name="erpSltzList">ERP收料单列表(含主表+明细)</param> |
| | | /// <returns>全部成功返回true,否则false</returns> |
| | | public bool SaveList(List<ErpSltz> erpSltzList) |
| | | public class MesInvItemArnManager : Repository<MesInvItemArn> |
| | | { |
| | | if (erpSltzList == null || !erpSltzList.Any()) |
| | | throw new ArgumentNullException(nameof(erpSltzList), "待保存的收料单列表不能为空"); |
| | | |
| | | // 修复:用事务包裹批量操作,确保数据一致性 |
| | | return UseTransaction(db => |
| | | /// <summary> |
| | | /// 批量保存收料单(主表+明细)- 事务保证批量操作一致性 |
| | | /// 单条失败则整体回滚 |
| | | /// </summary> |
| | | public bool SaveList(List<ErpSltz> erpSltzList) |
| | | { |
| | | foreach (var erpSltz in erpSltzList) |
| | | if (erpSltzList == null || !erpSltzList.Any()) |
| | | throw new ArgumentNullException(nameof(erpSltzList), "待保存的收料单列表不能为空"); |
| | | |
| | | return UseTransaction(db => |
| | | { |
| | | // 修复:调用事务内的Save方法,传入db实例 |
| | | if (!Save(db, erpSltz)) |
| | | foreach (var erpSltz in erpSltzList) |
| | | { |
| | | return 0; // 单条失败,事务回滚 |
| | | if (!SaveInTransaction(db, erpSltz)) |
| | | return 0; // 触发回滚 |
| | | } |
| | | } |
| | | return 1; // 全部成功 |
| | | }) > 0; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 单条保存收料单(主表+明细)- 事务内调用(修正访问修饰符,确保事务内可用) |
| | | /// </summary> |
| | | /// <param name="db">事务内的SqlSugar实例</param> |
| | | /// <param name="erpSltz">ERP收料单(含主表+明细)</param> |
| | | /// <returns>单条处理成功返回true</returns> |
| | | 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<ErpSltzBList>(); |
| | | |
| | | // 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-删除)"); |
| | | return 1; // 提交 |
| | | }) > 0; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 单条保存收料单(主表+明细)- 对外公开接口(供控制器调用) |
| | | /// </summary> |
| | | /// <param name="erpSltz">ERP收料单数据(含主表+明细)</param> |
| | | /// <returns>保存成功返回true</returns> |
| | | 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 => |
| | | /// <summary> |
| | | /// 对外单条保存(内部自动事务) |
| | | /// </summary> |
| | | public bool Save(ErpSltz erpSltz) |
| | | { |
| | | return Save(db, erpSltz) ? 1 : 0; |
| | | }) > 0; |
| | | } |
| | | if (erpSltz == null) throw new ArgumentNullException(nameof(erpSltz), "收料单数据不能为空"); |
| | | if (erpSltz.ErpSltza == null) throw new ArgumentNullException(nameof(erpSltz.ErpSltza), "收料单主表数据不能为空"); |
| | | |
| | | /// <summary> |
| | | /// 提前获取或生成MES主表ID(修复:用事务内db查询) |
| | | /// </summary> |
| | | private Guid GetOrCreateMainId(SqlSugarScope db, ErpSltza erpMain) |
| | | { |
| | | if (string.IsNullOrEmpty(erpMain.billNo)) |
| | | throw new ArgumentException("ERP收料单单据号不能为空,无法确定主表唯一性", nameof(erpMain.billNo)); |
| | | return UseTransaction(db => SaveInTransaction(db, erpSltz) ? 1 : 0) > 0; |
| | | } |
| | | |
| | | // 修复:用事务内的db查询,而非Context |
| | | var existingMain = db.Queryable<MesInvItemArn>() |
| | | .Where(m => m.BillNo == erpMain.billNo) |
| | | .First(); |
| | | |
| | | return existingMain != null |
| | | ? existingMain.Id |
| | | : Guid.NewGuid(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 处理收料单新增/更新(主表+明细) |
| | | /// </summary> |
| | | private bool HandleSaveOrUpdate(SqlSugarScope db, MesInvItemArn mesMain, List<MesInvItemArnDetail> mesDetails, Guid mainId) |
| | | { |
| | | mesMain.Id = mainId; |
| | | bool isMainExist = db.Queryable<MesInvItemArn>().Where(m => m.Id == mainId).Any(); |
| | | int mainOperateResult; |
| | | |
| | | if (isMainExist) |
| | | /// <summary> |
| | | /// 事务内单条保存 |
| | | /// </summary> |
| | | private bool SaveInTransaction(SqlSugarScope db, ErpSltz erpSltz) |
| | | { |
| | | mainOperateResult = db.Updateable(mesMain) |
| | | .IgnoreColumns(m => new { m.CreateDate }) |
| | | if (erpSltz == null) throw new ArgumentNullException(nameof(erpSltz), "收料单数据不能为空"); |
| | | if (erpSltz.ErpSltza == null) throw new ArgumentNullException(nameof(erpSltz.ErpSltza), "收料单主表数据不能为空"); |
| | | |
| | | var erpMain = erpSltz.ErpSltza; |
| | | var erpDetails = erpSltz.ErpSltzBList ?? new List<ErpSltzBList>(); |
| | | |
| | | // 通过 ERP 单号确定/生成主表ID |
| | | Guid mainId = GetOrCreateMainId(db, erpMain); |
| | | |
| | | // 映射 |
| | | var mesMain = MapErpMainToMesMain(erpMain, mainId,db); |
| | | var mesDetails = MapErpDetailsToMesDetails(db, erpDetails, mainId); |
| | | |
| | | // 类型:1 新增,2 更新,3 删除 |
| | | var type = TrimOrNull(erpMain.TYPE); |
| | | return type switch |
| | | { |
| | | "1" or "2" => HandleSaveOrUpdate(db, mesMain, mesDetails, mainId), |
| | | "3" => HandleDelete(db, mainId), |
| | | _ => throw new NotImplementedException($"未实现的收料单操作类型:{erpMain.TYPE}(支持:1-新增,2-更新,3-删除)") |
| | | }; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取或生成主表ID(按 ERP DeliveryNo 唯一) |
| | | /// </summary> |
| | | private Guid GetOrCreateMainId(SqlSugarScope db, ErpSltza erpMain) |
| | | { |
| | | var billNo = TrimOrNull(erpMain.DeliveryNo) |
| | | ?? throw new ArgumentException("ERP收料单单据号(DeliveryNo)不能为空,无法确定主表唯一性", |
| | | nameof(erpMain.DeliveryNo)); |
| | | |
| | | // SqlSugar: 用 First(),无数据返回 null |
| | | var existingMain = db.Queryable<MesInvItemArn>() |
| | | .Where(m => m.BillNo == billNo) |
| | | .First(); |
| | | |
| | | return existingMain?.Id ?? Guid.NewGuid(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 新增/更新(主表+明细:先删旧明细再插新) |
| | | /// </summary> |
| | | private bool HandleSaveOrUpdate(SqlSugarScope db, MesInvItemArn mesMain, List<MesInvItemArnDetail> mesDetails, |
| | | Guid mainId) |
| | | { |
| | | mesMain.Id = mainId; |
| | | |
| | | bool isMainExist = db.Queryable<MesInvItemArn>() |
| | | .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 deleteOldDetailsResult = db.Deleteable<MesInvItemArnDetail>() |
| | | .Where(d => d.Mid == mainId) |
| | | .ExecuteCommand(); |
| | | |
| | | int insertNewDetailsResult = mesDetails.Count > 0 |
| | | ? db.Insertable(mesDetails).ExecuteCommand() |
| | | : 1; |
| | | |
| | | return mainOperateResult > 0 && deleteOldDetailsResult >= 0 && insertNewDetailsResult > 0; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 删除(先删明细再删主表) |
| | | /// </summary> |
| | | private bool HandleDelete(SqlSugarScope db, Guid mainId) |
| | | { |
| | | db.Deleteable<MesInvItemArnDetail>() |
| | | .Where(d => d.Mid == mainId) |
| | | .ExecuteCommand(); |
| | | |
| | | int deleteMainResult = db.Deleteable<MesInvItemArn>() |
| | | .Where(m => m.Id == mainId) |
| | | .ExecuteCommand(); |
| | | } |
| | | else |
| | | { |
| | | mesMain.CreateDate = DateTime.Now; |
| | | mainOperateResult = db.Insertable(mesMain).ExecuteCommand(); |
| | | |
| | | return deleteMainResult >= 0; |
| | | } |
| | | |
| | | // 处理明细 |
| | | int deleteOldDetailResult = db.Deleteable<MesInvItemArnDetail>() |
| | | .Where(d => d.Mid == mainId) |
| | | .ExecuteCommand(); |
| | | |
| | | int insertNewDetailResult = mesDetails.Count > 0 |
| | | ? db.Insertable(mesDetails).ExecuteCommand() |
| | | : 1; |
| | | |
| | | return mainOperateResult > 0 && (deleteOldDetailResult >= 0 && insertNewDetailResult > 0); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 处理收料单删除(主表+明细) |
| | | /// </summary> |
| | | private bool HandleDelete(SqlSugarScope db, MesInvItemArn mesMain, List<MesInvItemArnDetail> mesDetails, Guid mainId) |
| | | { |
| | | db.Deleteable<MesInvItemArnDetail>().Where(d => d.Mid == mainId).ExecuteCommand(); |
| | | int mainDeleteResult = db.Deleteable<MesInvItemArn>().Where(m => m.Id == mainId).ExecuteCommand(); |
| | | return mainDeleteResult >= 0; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ERP主表映射到MES主表(修复:取消关键字段注释,修正FType逻辑) |
| | | /// </summary> |
| | | 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)) |
| | | /// <summary> |
| | | /// ERP 主表 -> MES 主表 |
| | | /// </summary> |
| | | private MesInvItemArn MapErpMainToMesMain(ErpSltza erpMain, Guid mainId, SqlSugarScope db) |
| | | { |
| | | 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 // 初始未审核 |
| | | }; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ERP明细映射到MES明细(修复:取消关键字段注释,修正EbelnK3id转换) |
| | | /// </summary> |
| | | private List<MesInvItemArnDetail> MapErpSltzBListToMesInvItemArnDetail(List<ErpSltzBList> 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 |
| | | var billNo = TrimOrNull(erpMain.DeliveryNo) |
| | | ?? throw new ArgumentException("收料单单据号不能为空"); |
| | | // 获取供应商编号并查询对应的ID |
| | | string suppNo = TrimOrNull(erpMain.SupplierId); |
| | | decimal ? suppId = null; |
| | | if (!string.IsNullOrEmpty(suppNo)) |
| | | { |
| | | // 修复:取消关键字段注释,补充赋值 |
| | | // 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() // 收货仓库编号 |
| | | // 从数据库查询供应商ID(SuppNo唯一) |
| | | suppId = db.Queryable<MesSupplier>() |
| | | .Where(s => s.SuppNo == suppNo) |
| | | .Select(s => s.Id) |
| | | .First(); |
| | | |
| | | // 可选:如果需要严格验证供应商存在性,取消下面注释 |
| | | if (suppId == null) |
| | | { |
| | | throw new KeyNotFoundException($"未找到编号为【{suppNo}】的供应商信息"); |
| | | } |
| | | } |
| | | // 是否 SRM |
| | | var isSrm = ToInt(erpMain.F_ZJXF_sfgx, 0); |
| | | |
| | | // 是否委外:ERP的 fType 为 "1"/"true" 视为委外 |
| | | var fTypeStr = TrimOrNull(erpMain.fType); |
| | | bool isOutsourcing = fTypeStr is not null && |
| | | (fTypeStr == "1" || fTypeStr.Equals("true", StringComparison.OrdinalIgnoreCase)); |
| | | |
| | | return new MesInvItemArn |
| | | { |
| | | Id = mainId, |
| | | BillNo = billNo, |
| | | SuppId = suppId.ToString(), |
| | | CreateDate = ToDate(erpMain.FDate), // null 表示未知 |
| | | Remark = TrimOrNull(erpMain.Remark), |
| | | IsSrm = isSrm, |
| | | EbelnK3id = TrimOrNull(erpMain.erpId), |
| | | CreateBy = TrimOrNull(erpMain.createBy) ?? "SYSTEM", |
| | | FType = isOutsourcing, |
| | | ReceiveOrgId = TrimOrNull(erpMain.ReceiveOrgId) |
| | | }; |
| | | }).ToList(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 按单据号查询MES收料单(主表+明细) |
| | | /// </summary> |
| | | public (MesInvItemArn main, List<MesInvItemArnDetail> details) GetByBillNo(string billNo) |
| | | { |
| | | if (string.IsNullOrEmpty(billNo)) |
| | | throw new ArgumentNullException(nameof(billNo), "查询条件单据号不能为空"); |
| | | /// <summary> |
| | | /// ERP 明细 -> MES 明细 |
| | | /// 核心:通过 ERP ProductCode 匹配 mes_items.item_no 获取 item_id |
| | | /// </summary> |
| | | private List<MesInvItemArnDetail> MapErpDetailsToMesDetails(SqlSugarScope db, List<ErpSltzBList> erpDetails, |
| | | Guid mainId) |
| | | { |
| | | var productCodes = erpDetails |
| | | .Where(d => !string.IsNullOrWhiteSpace(d.ProductCode)) |
| | | .Select(d => d.ProductCode.Trim()) |
| | | .Distinct() |
| | | .ToList(); |
| | | |
| | | var main = Context.Queryable<MesInvItemArn>() |
| | | .Where(m => m.BillNo == billNo) |
| | | .First(); |
| | | // 先 ToList 再 ToDictionary,避免直接对 ISugarQueryable 调用拓展方法失败 |
| | | var itemPairs = db.Queryable<MesItems>() |
| | | .Where(item => productCodes.Contains(item.ItemNo)) |
| | | .Select(item => new { item.ItemNo, item.Id }) |
| | | .ToList(); |
| | | |
| | | var details = main != null |
| | | ? Context.Queryable<MesInvItemArnDetail>() |
| | | .Where(d => d.Mid == main.Id) |
| | | .ToList() |
| | | : new List<MesInvItemArnDetail>(); |
| | | var itemMap = itemPairs.ToDictionary(k => k.ItemNo, v => v.Id); |
| | | |
| | | return (main, details); |
| | | var list = new List<MesInvItemArnDetail>(erpDetails.Count); |
| | | |
| | | foreach (var erpDetail in erpDetails) |
| | | { |
| | | var lineNo = ToInt(erpDetail.LineNo); |
| | | var productCode = TrimOrNull(erpDetail.ProductCode); |
| | | |
| | | if (productCode == null) |
| | | throw new ArgumentNullException(nameof(erpDetail.ProductCode), |
| | | $"ERP收料单明细【行:{lineNo}】的物料编码(ProductCode)不能为空,无法生成明细"); |
| | | |
| | | if (!itemMap.TryGetValue(productCode, out var itemId)) |
| | | throw new KeyNotFoundException( |
| | | $"ERP收料单明细【行:{lineNo}】的物料编码【{productCode}】在 MES.mes_items 中未找到匹配的 item_no"); |
| | | |
| | | var detail = new MesInvItemArnDetail |
| | | { |
| | | DeliveryLineID = lineNo, |
| | | Eid = ToInt(erpDetail.ErpId), |
| | | Mid = mainId, |
| | | Ebeln = TrimOrNull(erpDetail.FBillNo), |
| | | ItemId = ToInt(itemId), |
| | | EbelnQty = ToDecimal(erpDetail.PurchaseQty), |
| | | SubQty = ToDecimal(erpDetail.DeliveryQty), |
| | | Quantity = ToDecimal(erpDetail.IncludeQty), |
| | | PurchaseUnit = TrimOrNull(erpDetail.PurchaseUnit), |
| | | InventoryUnit = TrimOrNull(erpDetail.InventoryUnit), |
| | | Memo = TrimOrNull(erpDetail.Remark), |
| | | EbelnK3id = ToInt(erpDetail.FSrcBillNo), |
| | | LineK3id = ToInt(erpDetail.FSrcBillLine), |
| | | SalesOrderId = TrimOrNull(erpDetail.SalesOrderId), |
| | | MtoNo = TrimOrNull(erpDetail.FMtoNo), |
| | | Lot = TrimOrNull(erpDetail.FLot), |
| | | UrgentFlag = ToBool(erpDetail.urgentFlag), |
| | | DepotId = ToInt(erpDetail.DepotId) |
| | | }; |
| | | |
| | | list.Add(detail); |
| | | } |
| | | |
| | | return list; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 按单据号查询(主+明细) |
| | | /// </summary> |
| | | public (MesInvItemArn main, List<MesInvItemArnDetail> details) GetByBillNo(string billNo) |
| | | { |
| | | if (string.IsNullOrWhiteSpace(billNo)) |
| | | throw new ArgumentNullException(nameof(billNo), "查询条件单据号不能为空"); |
| | | |
| | | var no = billNo.Trim(); |
| | | |
| | | // SqlSugar: First() |
| | | var main = Context.Queryable<MesInvItemArn>() |
| | | .Where(m => m.BillNo == no) |
| | | .First(); |
| | | |
| | | var details = main != null |
| | | ? Context.Queryable<MesInvItemArnDetail>().Where(d => d.Mid == main.Id).ToList() |
| | | : new List<MesInvItemArnDetail>(); |
| | | |
| | | return (main, details); |
| | | } |
| | | |
| | | #region 安全转换/工具方法 |
| | | |
| | | private static string TrimOrNull(string s) => |
| | | string.IsNullOrWhiteSpace(s) ? null : s.Trim(); |
| | | |
| | | private static int ToInt(object value, int @default = 0) |
| | | { |
| | | switch (value) |
| | | { |
| | | case null: return @default; |
| | | case int i: return i; |
| | | case long l: return unchecked((int)l); |
| | | case short sh: return sh; |
| | | case byte b: return b; |
| | | case decimal dm: return (int)dm; |
| | | case double db: return (int)db; |
| | | case float f: return (int)f; |
| | | case string s when int.TryParse(s, out var n): return n; |
| | | default: return @default; |
| | | } |
| | | } |
| | | |
| | | private static decimal ToDecimal(object value, decimal @default = 0m) |
| | | { |
| | | switch (value) |
| | | { |
| | | case null: return @default; |
| | | case decimal dm: return dm; |
| | | case double db: return (decimal)db; |
| | | case float f: return (decimal)f; |
| | | case int i: return i; |
| | | case long l: return l; |
| | | case string s when decimal.TryParse(s, out var n): return n; |
| | | default: return @default; |
| | | } |
| | | } |
| | | |
| | | private static bool ToBool(object value, bool @default = false) |
| | | { |
| | | switch (value) |
| | | { |
| | | case null: return @default; |
| | | case bool b: return b; |
| | | case int i: return i != 0; |
| | | case long l: return l != 0; |
| | | case string s: |
| | | var t = s.Trim().ToLowerInvariant(); |
| | | return t switch |
| | | { |
| | | "1" => true, |
| | | "0" => false, |
| | | "y" => true, |
| | | "n" => false, |
| | | "true" => true, |
| | | "false" => false, |
| | | _ => @default |
| | | }; |
| | | default: return @default; |
| | | } |
| | | } |
| | | |
| | | private static DateTime? ToDate(object value) |
| | | { |
| | | switch (value) |
| | | { |
| | | case null: return null; |
| | | case DateTime dt: return dt; |
| | | case string s when DateTime.TryParse(s, out var d): return d; |
| | | default: return null; |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | } |
| | | } |