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;
|
|
public class MesCgthSqManager : Repository<MesCgthSq>
|
{
|
/// <summary>
|
/// 批量保存采购退货单(主表+明细)
|
/// </summary>
|
public bool SaveList(List<ErpCgth> erpCgthList)
|
{
|
if (erpCgthList == null || !erpCgthList.Any())
|
throw new ArgumentNullException(nameof(erpCgthList), "待保存的退货单列表不能为空");
|
|
// 逐条处理,全部成功才返回true(事务内批量处理更优,此处保持原有逻辑)
|
var result = erpCgthList.Select(Save).ToList();
|
return result.All(b => b);
|
}
|
|
/// <summary>
|
/// 保存采购退货单(主表+明细)
|
/// </summary>
|
public bool Save(ErpCgth erpCgth)
|
{
|
if (erpCgth == null)
|
throw new ArgumentNullException(nameof(erpCgth), "退货单数据不能为空");
|
if (erpCgth.ErpCgtha == null)
|
throw new ArgumentNullException(nameof(erpCgth.ErpCgtha), "退货单主表数据不能为空");
|
|
// 提取主表和明细表DTO
|
var erpMain = erpCgth.ErpCgtha;
|
var erpDetails = erpCgth.ErpCgthBList ?? new List<ErpCgthBList>(); // 避免明细为null
|
|
// 步骤1:映射主表基础数据(暂不处理Id)
|
var mesMain = MapErpCgthaToMesCgthSq(erpMain);
|
|
// 步骤2:提前确定主表Id(核心修正:在映射明细表前获取/生成Id)
|
Guid mainId = GetOrCreateMainId(mesMain);
|
|
// 步骤3:用确定的mainId映射明细表(确保Mid=mainId)
|
var mesDetails = MapErpCgthBToMesCgthSqDetail(erpDetails, mainId);
|
|
// 步骤4:事务内处理主从表保存
|
return UseTransaction(db =>
|
{
|
switch (erpMain.TYPE)
|
{
|
case "1": // 新增
|
case "2": // 更新
|
case "4": // 其他新增/更新类型
|
case "5": // 提交
|
return SaveOrUpdateData(db, mesMain, mesDetails, mainId) ? 1 : 0;
|
case "3": // 删除
|
case "6": // 撤销
|
return DeleteData(db, mesMain, mesDetails, mainId) ? 1 : 0;
|
default:
|
throw new NotImplementedException($"未实现的操作类型:{erpMain.TYPE}");
|
}
|
}) > 0;
|
}
|
|
/// <summary>
|
/// 提前获取或生成主表Id(确保在映射明细表前确定)
|
/// </summary>
|
private Guid GetOrCreateMainId(MesCgthSq mesMain)
|
{
|
// 优先通过单据号查询已有主表(更新场景)
|
var existingMain = Context.Queryable<MesCgthSq>()
|
.Where(m => m.BillNo == mesMain.BillNo)
|
.First();
|
|
if (existingMain != null)
|
{
|
// 已存在:返回数据库中的Id
|
return existingMain.Id;
|
}
|
else
|
{
|
// 不存在:生成新Id(新增场景)
|
return Guid.NewGuid();
|
}
|
}
|
|
/// <summary>
|
/// 新增或更新数据(主表+明细)
|
/// </summary>
|
private bool SaveOrUpdateData(SqlSugarScope db, MesCgthSq mesMain, List<MesCgthSqDetail> mesDetails, Guid mainId)
|
{
|
// 绑定主表Id(使用提前确定的mainId)
|
mesMain.Id = mainId;
|
|
// 处理主表:新增或更新
|
bool isExist = db.Queryable<MesCgthSq>().Where(m => m.BillNo == mesMain.BillNo).Any();
|
int mainResult;
|
|
if (isExist)
|
{
|
// 更新:按Id匹配(避免单据号重复导致错误)
|
mainResult = db.Updateable(mesMain)
|
.IgnoreColumns(m => new { m.CreateDate }) // 不更新创建时间
|
.Where(m => m.Id == mainId)
|
.ExecuteCommand();
|
}
|
else
|
{
|
// 新增:使用提前生成的Id
|
mainResult = db.Insertable(mesMain).ExecuteCommand();
|
}
|
|
// 处理明细表:先删旧数据,再插新数据(确保数据同步)
|
// 1. 删除当前主表关联的旧明细
|
int deleteOldDetailResult = db.Deleteable<MesCgthSqDetail>()
|
.Where(d => d.Mid == mainId)
|
.ExecuteCommand();
|
|
// 2. 插入新明细(Mid已=mainId)
|
int insertDetailResult = mesDetails.Count > 0
|
? db.Insertable(mesDetails).ExecuteCommand()
|
: 1; // 无明细时视为成功
|
|
// 校验结果(主表必须成功,明细删除/插入至少有一个成功)
|
return mainResult > 0 && (deleteOldDetailResult >= 0 && insertDetailResult > 0);
|
}
|
|
/// <summary>
|
/// 删除数据(主表+明细)
|
/// </summary>
|
private bool DeleteData(SqlSugarScope db, MesCgthSq mesMain, List<MesCgthSqDetail> mesDetails, Guid mainId)
|
{
|
// 1. 删除明细(按主表Id删除)
|
int detailResult = db.Deleteable<MesCgthSqDetail>()
|
.Where(d => d.Mid == mainId)
|
.ExecuteCommand();
|
|
// 2. 删除主表(按Id删除)
|
int mainResult = db.Deleteable<MesCgthSq>()
|
.Where(m => m.Id == mainId)
|
.ExecuteCommand();
|
|
// 允许明细原本不存在(detailResult=0),但主表必须删除成功
|
return mainResult > 0;
|
}
|
|
/// <summary>
|
/// 主表映射(仅处理基础字段,Id由GetOrCreateMainId确定)
|
/// </summary>
|
private MesCgthSq MapErpCgthaToMesCgthSq(ErpCgtha erpMain)
|
{
|
return new MesCgthSq
|
{
|
// Id暂不赋值(由GetOrCreateMainId后续确定)
|
ErpId = erpMain.ERPID, // ERP主表ID
|
BillNo = erpMain.billNo ?? throw new ArgumentNullException(nameof(erpMain.billNo), "单据编号不能为空"),
|
Type = erpMain.TYPE,
|
FDate = erpMain.FDate,
|
FDocumentStatus = erpMain.FDocumentStatus,
|
FSupplierId = erpMain.FSupplierID,
|
FBillTypeId = erpMain.FBillTypeID,
|
FBusinessType = erpMain.FBusinessType,
|
ReturnType = erpMain.FMRTYPE,
|
ReturnMethod = erpMain.FMRMODE,
|
CreateBy = erpMain.FCreatorId,
|
FPurchaseOrgId = erpMain.FPurchaseOrgId,
|
ThOrgId = erpMain.FStockOrgId,
|
FRequireOrgId = erpMain.FRequireOrgId,
|
FMRDeptId = erpMain.FMRDeptId,
|
FStockerId = erpMain.FSTOCKERID,
|
FPurchaserId = erpMain.FPURCHASERID,
|
FMRReason = erpMain.FMRREASON,
|
FPurchaseDeptId = erpMain.FPURCHASEDEPTID,
|
FPurchaserGroupId = erpMain.FPURCHASERGROUPID,
|
FACCTYPE = erpMain.FACCTYPE,
|
FCreateDate = erpMain.FCreateDate,
|
FWPVTINTEGERL6W = erpMain.F_WPVT_INTEGER_L6W,
|
|
// 供应商ID(安全转换)
|
SuppId = !string.IsNullOrEmpty(erpMain.FSupplierID)
|
&& int.TryParse(erpMain.FSupplierID, out int suppId)
|
? suppId
|
: null,
|
|
// 系统字段(创建时间仅新增时赋值,更新时不覆盖)
|
CreateDate = DateTime.Now,
|
LastUpdateTime = DateTime.Now
|
};
|
}
|
|
/// <summary>
|
/// 明细表映射(使用提前确定的mainId作为Mid)
|
/// </summary>
|
private List<MesCgthSqDetail> MapErpCgthBToMesCgthSqDetail(List<ErpCgthBList> erpDetails, Guid mainId)
|
{
|
return erpDetails.Select(erpDetail => new MesCgthSqDetail
|
{
|
Mid = mainId, // 直接使用提前确定的mainId(确保非全零)
|
|
// ERP明细ID(安全转换)
|
ErpId = !string.IsNullOrEmpty(erpDetail.ERPID)
|
&& int.TryParse(erpDetail.ERPID, out int erpId)
|
? erpId
|
: null,
|
|
// 外部系统ID(安全转换)
|
Eid = !string.IsNullOrEmpty(erpDetail.EID)
|
&& int.TryParse(erpDetail.EID, out int eid)
|
? eid
|
: null,
|
|
FsrcBillNo = erpDetail.FSRCBillNo,
|
FsrcBillTypeId = erpDetail.FSRCBillTypeId,
|
|
// 物料ID(安全转换)
|
ItemId = !string.IsNullOrEmpty(erpDetail.FMATERIALID)
|
&& int.TryParse(erpDetail.FMATERIALID, out int itemId)
|
? itemId
|
: null,
|
|
FUnitId = erpDetail.FUnitID,
|
|
// 仓库ID(安全转换)
|
DepotId = !string.IsNullOrEmpty(erpDetail.FSTOCKID)
|
&& long.TryParse(erpDetail.FSTOCKID, out long depotId)
|
? depotId
|
: null,
|
|
FstockLocId = erpDetail.FSTOCKLOCID,
|
FLot = erpDetail.FLot,
|
SqNum = erpDetail.FRMREALQTY, // 假设FRMREALQTY是数值类型(如decimal)
|
Remark = erpDetail.FNOTE,
|
FMtoNo = erpDetail.FMtoNo,
|
IsFinish = false // 初始未完成
|
}).ToList();
|
}
|
}
|