using MES.Service.DB;
|
using MES.Service.Dto.webApi;
|
using MES.Service.Modes;
|
using System.Linq;
|
using MES.Service.util;
|
|
namespace MES.Service.service.BasicData;
|
|
/// <summary>
|
/// 送货单条码业务管理器(对应TBL_BARCODE_INFORMATION表操作)
|
/// </summary>
|
public class DeliveryBarcodeManager : Repository<BarcodeInformation>
|
{
|
/// <summary>
|
/// 单个送货单条码信息保存(支持新增/删除,按Type区分操作类型)
|
/// </summary>
|
/// <param name="barcodeDto">送货单条码DTO(含操作类型Type)</param>
|
/// <returns>操作是否成功</returns>
|
public bool Save(DeliveryBarcodeInfo barcodeDto)
|
{
|
if (barcodeDto == null)
|
throw new ArgumentNullException(nameof(barcodeDto), "条码DTO不能为空");
|
|
// DTO转实体(映射字段关系)
|
var barcodeEntity = ConvertDtoToEntity(barcodeDto);
|
|
try
|
{
|
// 按Type区分操作类型(0=新增,1=删除)
|
switch (barcodeDto.Type)
|
{
|
case "1":
|
return InsertBarcode(barcodeEntity);
|
case "2":
|
return DeleteBarcode(barcodeEntity.Id);
|
default:
|
throw new ArgumentOutOfRangeException( nameof(barcodeDto.Type), barcodeDto.Type, "条码操作类型错误:仅支持 0(新增)、1(删除)");
|
}
|
}
|
catch (Exception ex)
|
{
|
throw new ApplicationException($"单个条码操作失败(送货单号:{barcodeDto.DeliveryNo}):{ex.Message}", ex);
|
}
|
}
|
|
/// <summary>
|
/// 批量送货单条码信息保存(按Type分组处理,统一异常捕获)
|
/// </summary>
|
/// <param name="barcodeDtoList">送货单条码DTO列表</param>
|
/// <returns>批量操作是否全部成功</returns>
|
public bool SaveList(List<DeliveryBarcodeInfo> barcodeDtoList)
|
{
|
if (barcodeDtoList == null || !barcodeDtoList.Any())
|
{
|
throw new ArgumentException("批量操作的条码列表不能为空");
|
}
|
|
try
|
{
|
// 1. 创建强类型的实体与类型组合列表(解决dynamic转换问题)
|
var entityTypePairs = new List<EntityTypePair>();
|
foreach (var dto in barcodeDtoList)
|
{
|
entityTypePairs.Add(new EntityTypePair
|
{
|
Entity = ConvertDtoToEntity(dto),
|
Type = dto.Type
|
});
|
}
|
|
// 2. 按操作类型Type分组(使用强类型避免类型推断问题)
|
var typeGroupDict = entityTypePairs.GroupBy(pair => pair.Type).ToDictionary(group => group.Key,group => group.Select(pair => pair.Entity).ToList());
|
|
// 3. 存储各组操作结果
|
var groupResultList = new List<bool>();
|
|
foreach (var (type, entityGroup) in typeGroupDict)
|
{
|
switch (type)
|
{
|
case "1":
|
groupResultList.Add(InsertBarcodeBatch(entityGroup));
|
break;
|
case "2":
|
groupResultList.Add(DeleteBarcodeBatch(entityGroup.Select(e => e.Id).ToArray()));
|
break;
|
default:
|
throw new ArgumentOutOfRangeException(nameof(type),type,"批量操作中存在非法Type:仅支持 1(新增)、2(删除)");
|
}
|
}
|
|
// 4. 所有分组操作均成功才算批量成功
|
if (groupResultList.All(result => result))
|
{
|
return true;
|
}
|
|
throw new NotImplementedException("批量条码操作部分失败,具体请查看日志");
|
}
|
catch (Exception ex)
|
{
|
throw new ApplicationException($"批量条码操作失败(总条数:{barcodeDtoList.Count}):{ex.Message}", ex);
|
}
|
}
|
|
/// <summary>
|
/// 根据送货单号删除条码数据
|
/// </summary>
|
/// <param name="deliveryNo">送货单号(不能为空/空字符串)</param>
|
/// <returns>是否删除成功(true=至少删除1条,false=未找到对应数据)</returns>
|
public bool DeleteByDeliveryNo(string deliveryNo)
|
{
|
// 1. 校验参数:送货单号不能为空
|
if (string.IsNullOrWhiteSpace(deliveryNo))
|
{
|
throw new ArgumentException("送货单号 DeliveryNo 不能为空或空格", nameof(deliveryNo));
|
}
|
try
|
{
|
// 2. 执行删除:根据 DeliveryNo 匹配表中数据(对应实体的 DeliveryNo 字段)
|
int deletedCount = Db.Deleteable<BarcodeInformation>()
|
.Where(barcode => barcode.DeliveryNo == deliveryNo) // 表字段与送货单号匹配
|
.ExecuteCommand(); // 返回受影响的行数
|
|
// 3. 判断结果:至少删除1条则视为成功,否则抛出“未找到数据”异常
|
if (deletedCount > 0)
|
{
|
return true;
|
}
|
throw new KeyNotFoundException($"未找到送货单号为「{deliveryNo}」的条码数据,删除操作未执行");
|
}
|
catch (Exception ex)
|
{
|
// 4. 包装业务异常,补充上下文信息
|
throw new ApplicationException($"根据送货单号删除条码数据失败(DeliveryNo:{deliveryNo}):{ex.Message}", ex);
|
}
|
}
|
|
/// <summary>
|
/// 批量按送货单号删除条码数据(接收数组项列表)
|
/// </summary>
|
/// <param name="deliveryNoItems">包含DeliveryNo的对象列表</param>
|
/// <returns>批量删除结果</returns>
|
public BatchDeleteResult DeleteListByDeliveryNo(List<DeleteByDeliveryNoRequest> deliveryNoItems)
|
{
|
// 1. 参数校验与处理(从控制器移过来的逻辑)
|
if (deliveryNoItems == null || !deliveryNoItems.Any())
|
{
|
throw new ArgumentException("送货单号列表不能为空", nameof(deliveryNoItems));
|
}
|
// 提取并验证送货单号列表
|
var deliveryNoList = deliveryNoItems
|
.Select(item => item.DeliveryNo) // 从对象中提取DeliveryNo字段
|
.Where(no => !string.IsNullOrWhiteSpace(no)) // 过滤空值/空格
|
.Distinct() // 去重,避免重复删除
|
.ToList();
|
|
// 判断是否有有效单号
|
if (!deliveryNoList.Any())
|
{
|
throw new ArgumentException("请求中没有有效的送货单号(均为空或空格)");
|
}
|
try
|
{
|
// 2. 查询数据库中存在的送货单号
|
var existingNos = Db.Queryable<BarcodeInformation>().Where(barcode => deliveryNoList.Contains(barcode.DeliveryNo)).Select(barcode => barcode.DeliveryNo).Distinct().ToList();
|
|
// 3. 执行批量删除
|
int totalDeleted = Db.Deleteable<BarcodeInformation>().Where(barcode => deliveryNoList.Contains(barcode.DeliveryNo)).ExecuteCommand();
|
|
// 4. 返回结果
|
return new BatchDeleteResult
|
{
|
TotalRequested = deliveryNoList.Count,
|
TotalDeleted = totalDeleted,
|
DeletedNos = existingNos,
|
NotFoundNos = deliveryNoList.Except(existingNos).ToList()
|
};
|
}
|
catch (Exception ex)
|
{
|
throw new ApplicationException($"批量删除失败(共{deliveryNoList.Count}个单号):{ex.Message}",ex);
|
}
|
}
|
|
/// <summary>
|
/// 按送货单号+行内码联合删除条码数据
|
/// </summary>
|
/// <param name="deliveryNo">送货单号</param>
|
/// <param name="lineNo">送货单行内码</param>
|
/// <returns>是否删除成功(true=至少删除1条,false=未找到对应数据)</returns>
|
public bool DeleteByDeliveryItem(string deliveryNo, string lineNo)
|
{
|
// 1. 双参数校验:避免空值/空字符串
|
if (string.IsNullOrWhiteSpace(deliveryNo))
|
{
|
throw new ArgumentException("送货单号 DeliveryNo 不能为空或空格", nameof(deliveryNo));
|
}
|
if (string.IsNullOrWhiteSpace(lineNo))
|
{
|
throw new ArgumentException("送货单行内码 LineNo 不能为空或空格", nameof(lineNo));
|
}
|
|
try
|
{
|
// 2. 联合条件删除:匹配 DeliveryNo(送货单号)和 DnLines(行内码,实体字段对应表的 dnLines 列)
|
int deletedCount = Db.Deleteable<BarcodeInformation>().Where(barcode =>barcode.DeliveryNo == deliveryNo && barcode.DnLines == lineNo) // 匹配行内码(实体 DnLines 对应表 dnLines 字段)
|
.ExecuteCommand(); // 返回受影响的行数
|
|
// 3. 结果判断:有数据被删除则成功,否则抛“未找到数据”异常
|
if (deletedCount > 0)
|
{
|
return true;
|
}
|
throw new KeyNotFoundException($"未找到送货单号「{deliveryNo}」且行内码「{lineNo}」对应的条码数据,删除操作未执行");
|
}
|
catch (Exception ex)
|
{
|
// 4. 包装异常:补充联合条件上下文,便于定位问题
|
throw new ApplicationException($"按送货单号+行内码删除条码数据失败(DeliveryNo:{deliveryNo},LineNo:{lineNo}):{ex.Message}",ex);
|
}
|
}
|
|
/// <summary>
|
/// 批量按送货单号+行内码删除条码数据
|
/// </summary>
|
/// <param name="deliveryItems">包含DeliveryNo和LineNo的对象列表</param>
|
/// <returns>批量删除结果</returns>
|
public BatchDeleteResult DeleteListByDeliveryItem(List<DeleteByDeliveryItemRequest> deliveryItems)
|
{
|
// 1. 参数校验与处理
|
if (deliveryItems == null || !deliveryItems.Any())
|
{
|
throw new ArgumentException("送货单行列表不能为空", nameof(deliveryItems));
|
}
|
// 提取并验证送货单号+行内码组合
|
var validItems = deliveryItems.Where(item =>!string.IsNullOrWhiteSpace(item.DeliveryNo) &&!string.IsNullOrWhiteSpace(item.LineNo))
|
.Select(item => new
|
{
|
DeliveryNo = item.DeliveryNo,
|
LineNo = item.LineNo
|
}).Distinct().ToList();
|
|
if (!validItems.Any())
|
{
|
throw new ArgumentException("请求中没有有效的效的送货单行数据(均为空或空格)");
|
}
|
try
|
{
|
// 2. 执行批量删除(按DeliveryNo+LineNo组合条件)
|
int totalDeleted = 0;
|
var deletedItems = new List<string>();
|
var notFoundItems = new List<string>();
|
|
// 遍历每个组合执行删除(或使用批量条件删除)
|
foreach (var item in validItems)
|
{
|
// 检查当前组合是否存在
|
var exists = Db.Queryable<BarcodeInformation>().Any(b => b.DeliveryNo == item.DeliveryNo && b.DnLines == item.LineNo);
|
|
if (exists)
|
{
|
// 执行删除
|
var deleted = Db.Deleteable<BarcodeInformation>().Where(b => b.DeliveryNo == item.DeliveryNo && b.DnLines == item.LineNo).ExecuteCommand();
|
totalDeleted += deleted;
|
deletedItems.Add($"{item.DeliveryNo}_{item.LineNo}");
|
}
|
else
|
{
|
notFoundItems.Add($"{item.DeliveryNo}_{item.LineNo}");
|
}
|
}
|
|
// 3. 返回结果
|
return new BatchDeleteResult
|
{
|
TotalRequested = validItems.Count,
|
TotalDeleted = totalDeleted,
|
DeletedNos = deletedItems, // 存储格式:"DeliveryNo_LineNo"
|
NotFoundNos = notFoundItems // 存储格式:"DeliveryNo_LineNo"
|
};
|
}
|
catch (Exception ex)
|
{
|
throw new ApplicationException(
|
$"批量删除送货单行失败(共{validItems.Count}条):{ex.Message}",
|
ex);
|
}
|
}
|
|
#region 私有辅助方法和内部类
|
|
/// <summary>
|
/// 内部辅助类:用于关联实体和操作类型(解决dynamic类型转换问题)
|
/// </summary>
|
private class EntityTypePair
|
{
|
public BarcodeInformation Entity { get; set; }
|
public string Type { get; set; }
|
}
|
|
/// <summary>
|
/// DTO转实体:映射DeliveryBarcodeInfo到BarcodeInformation字段
|
/// </summary>
|
private BarcodeInformation ConvertDtoToEntity(DeliveryBarcodeInfo dto)
|
{
|
var entityId = dto.Type == "1" ? Guid.NewGuid() : (string.IsNullOrEmpty(dto.SmallBarcode) ? Guid.Empty : Guid.NewGuid());
|
|
return new BarcodeInformation
|
{
|
Id = entityId,
|
ProductCode = dto.ProductCode,
|
SmallBarcode = dto.SmallBarcode,
|
OuterBarcode = dto.OuterBarcode,
|
IncludeQty = dto.IncludeQty.HasValue ? Convert.ToDecimal(dto.IncludeQty) : 0,
|
DeliveryNo = dto.DeliveryNo,
|
DnLines = dto.LineNo,
|
PackLevel = dto.BarcodeType,
|
CreateTime = dto.Type == "1" ? DateTime.Now : (DateTime?)null,
|
UpdateTime = DateTime.Now,
|
// 扩展字段赋默认值
|
BigBarcode = null,
|
SmallPackageLength = null,
|
SmallPackageWidth = null,
|
SmallPackageHeight = null,
|
BigPackageLength = null,
|
BigPackageWidth = null,
|
BigPackageHeight = null,
|
OuterPackageLength = null,
|
OuterPackageWidth = null,
|
OuterPackageHeight = null,
|
SmallPackageSn = null,
|
BigPackageSn = null,
|
OutPackageSn = null,
|
DynamicData = null,
|
PoErpNo = null,
|
PoLineNo = null,
|
InnerVendorCode = null,
|
Customize1 = null,
|
SynchronousDate = null,
|
Customize2 = null,
|
Customize3 = null
|
};
|
}
|
|
/// <summary>
|
/// 单个条码新增
|
/// </summary>
|
private bool InsertBarcode(BarcodeInformation entity)
|
{
|
// 检查条码是否已存在
|
if (IsBarcodeExists(entity))
|
{
|
throw new InvalidOperationException($"条码已存在,无法重复插入:SmallBarcode={entity.SmallBarcode}, OuterBarcode={entity.OuterBarcode}");
|
}
|
|
var isInsertSuccess = base.Insert(entity);
|
return isInsertSuccess ? true : throw new NotImplementedException("条码新增失败:数据库插入操作未执行成功");
|
}
|
/// <summary>
|
/// 单个条码删除(按主键Id)
|
/// </summary>
|
private bool DeleteBarcode(Guid id)
|
{
|
if (id == Guid.Empty)
|
{
|
throw new ArgumentException("删除操作的条码Id不能为空");
|
}
|
var deleteRowCount = Db.Deleteable<BarcodeInformation>().Where(entity => entity.Id == id).ExecuteCommand();
|
|
return deleteRowCount > 0 ? true : throw new NotImplementedException($"条码删除失败:未找到Id为「{id}」的条码记录");
|
}
|
|
/// <summary>
|
/// 批量条码新增
|
/// </summary>
|
private bool InsertBarcodeBatch(List<BarcodeInformation> entityList)
|
{
|
// 检查批量条码中是否有重复
|
var duplicateBarcodes = new List<string>();
|
foreach (var entity in entityList)
|
{
|
if (IsBarcodeExists(entity))
|
{
|
duplicateBarcodes.Add($"SmallBarcode={entity.SmallBarcode}, OuterBarcode={entity.OuterBarcode}");
|
}
|
}
|
|
if (duplicateBarcodes.Any())
|
{
|
throw new InvalidOperationException($"发现重复条码,无法批量插入:{string.Join("; ", duplicateBarcodes)}");
|
}
|
|
var isBatchInsertSuccess = base.InsertRange(entityList);
|
return isBatchInsertSuccess ? true : throw new NotImplementedException($"批量条码新增失败:共{entityList.Count}条记录");
|
}
|
|
/// <summary>
|
/// 批量条码删除(按主键Id数组)
|
/// </summary>
|
private bool DeleteBarcodeBatch(Guid[] ids)
|
{
|
if (ids == null || ids.Length == 0)
|
{
|
throw new ArgumentException("批量删除的条码Id数组不能为空");
|
}
|
var deleteRowCount = Db.Deleteable<BarcodeInformation>().Where(entity => ids.Contains(entity.Id)).ExecuteCommand();
|
|
return deleteRowCount > 0 ? true : throw new NotImplementedException($"批量条码删除失败:共{ids.Length}个Id");
|
}
|
|
/// <summary>
|
/// 检查条码是否已存在
|
/// </summary>
|
/// <param name="entity">条码实体</param>
|
/// <returns>true=已存在,false=不存在</returns>
|
private bool IsBarcodeExists(BarcodeInformation entity)
|
{
|
// 根据SmallBarcode或OuterBarcode检查是否存在重复条码
|
return Db.Queryable<BarcodeInformation>()
|
.Any(x => (!string.IsNullOrEmpty(entity.SmallBarcode) && x.SmallBarcode == entity.SmallBarcode) ||
|
(!string.IsNullOrEmpty(entity.OuterBarcode) && x.OuterBarcode == entity.OuterBarcode));
|
}
|
|
#endregion
|
}
|