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; /// /// 送货单条码业务管理器(对应TBL_BARCODE_INFORMATION表操作) /// public class DeliveryBarcodeManager : Repository { /// /// 单个送货单条码信息保存(支持新增/删除,按Type区分操作类型) /// /// 送货单条码DTO(含操作类型Type) /// 操作是否成功 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); } } /// /// 批量送货单条码信息保存(按Type分组处理,统一异常捕获) /// /// 送货单条码DTO列表 /// 批量操作是否全部成功 public bool SaveList(List barcodeDtoList) { if (barcodeDtoList == null || !barcodeDtoList.Any()) { throw new ArgumentException("批量操作的条码列表不能为空"); } try { // 1. 创建强类型的实体与类型组合列表(解决dynamic转换问题) var entityTypePairs = new List(); 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(); 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); } } /// /// 根据送货单号删除条码数据 /// /// 送货单号(不能为空/空字符串) /// 是否删除成功(true=至少删除1条,false=未找到对应数据) public bool DeleteByDeliveryNo(string deliveryNo) { // 1. 校验参数:送货单号不能为空 if (string.IsNullOrWhiteSpace(deliveryNo)) { throw new ArgumentException("送货单号 DeliveryNo 不能为空或空格", nameof(deliveryNo)); } try { // 2. 执行删除:根据 DeliveryNo 匹配表中数据(对应实体的 DeliveryNo 字段) int deletedCount = Db.Deleteable() .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); } } /// /// 批量按送货单号删除条码数据(接收数组项列表) /// /// 包含DeliveryNo的对象列表 /// 批量删除结果 public BatchDeleteResult DeleteListByDeliveryNo(List 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().Where(barcode => deliveryNoList.Contains(barcode.DeliveryNo)).Select(barcode => barcode.DeliveryNo).Distinct().ToList(); // 3. 执行批量删除 int totalDeleted = Db.Deleteable().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); } } /// /// 按送货单号+行内码联合删除条码数据 /// /// 送货单号 /// 送货单行内码 /// 是否删除成功(true=至少删除1条,false=未找到对应数据) 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().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); } } /// /// 批量按送货单号+行内码删除条码数据 /// /// 包含DeliveryNo和LineNo的对象列表 /// 批量删除结果 public BatchDeleteResult DeleteListByDeliveryItem(List 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(); var notFoundItems = new List(); // 遍历每个组合执行删除(或使用批量条件删除) foreach (var item in validItems) { // 检查当前组合是否存在 var exists = Db.Queryable().Any(b => b.DeliveryNo == item.DeliveryNo && b.DnLines == item.LineNo); if (exists) { // 执行删除 var deleted = Db.Deleteable().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 私有辅助方法和内部类 /// /// 内部辅助类:用于关联实体和操作类型(解决dynamic类型转换问题) /// private class EntityTypePair { public BarcodeInformation Entity { get; set; } public string Type { get; set; } } /// /// DTO转实体:映射DeliveryBarcodeInfo到BarcodeInformation字段 /// 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 }; } /// /// 单个条码新增 /// 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("条码新增失败:数据库插入操作未执行成功"); } /// /// 单个条码删除(按主键Id) /// private bool DeleteBarcode(Guid id) { if (id == Guid.Empty) { throw new ArgumentException("删除操作的条码Id不能为空"); } var deleteRowCount = Db.Deleteable().Where(entity => entity.Id == id).ExecuteCommand(); return deleteRowCount > 0 ? true : throw new NotImplementedException($"条码删除失败:未找到Id为「{id}」的条码记录"); } /// /// 批量条码新增 /// private bool InsertBarcodeBatch(List entityList) { // 检查批量条码中是否有重复 var duplicateBarcodes = new List(); 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}条记录"); } /// /// 批量条码删除(按主键Id数组) /// private bool DeleteBarcodeBatch(Guid[] ids) { if (ids == null || ids.Length == 0) { throw new ArgumentException("批量删除的条码Id数组不能为空"); } var deleteRowCount = Db.Deleteable().Where(entity => ids.Contains(entity.Id)).ExecuteCommand(); return deleteRowCount > 0 ? true : throw new NotImplementedException($"批量条码删除失败:共{ids.Length}个Id"); } /// /// 检查条码是否已存在 /// /// 条码实体 /// true=已存在,false=不存在 private bool IsBarcodeExists(BarcodeInformation entity) { // 根据SmallBarcode或OuterBarcode检查是否存在重复条码 return Db.Queryable() .Any(x => (!string.IsNullOrEmpty(entity.SmallBarcode) && x.SmallBarcode == entity.SmallBarcode) || (!string.IsNullOrEmpty(entity.OuterBarcode) && x.OuterBarcode == entity.OuterBarcode)); } #endregion }