using AutoMapper; using SqlSugar; using System.Dynamic; using System.Text.RegularExpressions; using System.Threading.Tasks; using WIDESEA_Common.CommonEnum; using WIDESEA_Common.LocationEnum; using WIDESEA_Common.OrderEnum; using WIDESEA_Common.StockEnum; using WIDESEA_Core; using WIDESEA_Core.BaseRepository; using WIDESEA_Core.BaseServices; using WIDESEA_Core.CodeConfigEnum; using WIDESEA_Core.DB; using WIDESEA_Core.Enums; using WIDESEA_Core.Helper; using WIDESEA_Core.Seed; using WIDESEA_Core.Utilities; using WIDESEA_DTO.Base; using WIDESEA_DTO.Inbound; using WIDESEA_IBasicService; using WIDESEA_IInboundService; using WIDESEA_IRecordService; using WIDESEA_IStockService; using WIDESEA_Model.Models; using WIDESEA_Model.Models.Basic; namespace WIDESEA_InboundService { public class InboundOrderService : ServiceBase>, IInboundOrderService { private readonly IMapper _mapper; private readonly IUnitOfWorkManage _unitOfWorkManage; private readonly IRepository _taskRepository; private IStockService _stockService; private readonly IMaterialUnitService _materialUnitService; private readonly IMaterielInfoService _materielInfoService; private readonly IInboundOrderDetailService _inboundOrderDetailService; private readonly IRepository _inboundOrderDetailRepository; private readonly IRepository _stockDetailRepository; private readonly IRepository _inboundOrderRepository; private readonly IRepository _warehouseAreaRepository; private readonly IRepository _locationTypeRepository; private readonly IRepository _stockRepository; private readonly IRepository _locationInfoRepository; private readonly IBasicService _basicService; public IRepository Repository => BaseDal; public InboundOrderService(IRepository BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository inboundOrderDetailRepository, IRepository taskRepository, IStockService stockService, IInboundOrderDetailService inboundOrderDetailService, IMaterialUnitService materialUnitService, IRepository stockDetailRepository, IRepository inboundOrderRepository, IRepository warehouseAreaRepository, IRepository stockRepository, IRepository locationTypeRepository, IMaterielInfoService materielInfoService, IBasicService basicService, IRepository locationInfoRepository) : base(BaseDal) { _mapper = mapper; _unitOfWorkManage = unitOfWorkManage; _inboundOrderDetailRepository = inboundOrderDetailRepository; _taskRepository = taskRepository; _stockService = stockService; _inboundOrderDetailService = inboundOrderDetailService; _materialUnitService = materialUnitService; _stockDetailRepository = stockDetailRepository; _inboundOrderRepository = inboundOrderRepository; _warehouseAreaRepository = warehouseAreaRepository; _stockRepository = stockRepository; _locationTypeRepository = locationTypeRepository; _materielInfoService = materielInfoService; _basicService = basicService; _locationInfoRepository = locationInfoRepository; } public async Task ReceiveInboundOrder(List models, int operateType) { try { return operateType switch { 1 => await AddInboundOrder(models), 2 => await UpdateInboundOrder(models), 3 => DeleteInboundOrder(models), _ => WebResponseContent.Instance.OK(), }; } catch (Exception ex) { return WebResponseContent.Instance.Error(ex.Message); } } public async Task AddInboundOrder(List models) { try { foreach (var model in models) { if (BaseDal.QueryFirst(x => x.UpperOrderNo == model.UpperOrderNo) != null) { return WebResponseContent.Instance.Error($"{model.UpperOrderNo}入库单号重复"); } } foreach (var model in models) { var materielCodes = model.Details.Select(x => x.MaterielCode).Distinct().ToList(); var materielInfos = _materielInfoService.Db.Queryable().Where(x => materielCodes.Contains(x.MaterielCode)).ToList(); foreach (var item in model.Details) { //var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync(item.MaterielCode, item.BarcodeQty); UnitConvertResultDTO totalResult = _basicService.UnitQuantityConvert(item.MaterielCode, item.Unit, item.BarcodeUnit, item.OrderQuantity); item.Unit = totalResult.ToUnit; item.OrderQuantity = totalResult.ToQuantity; if (materielInfos.Any()) { item.MaterielName = materielInfos.FirstOrDefault(x => x.MaterielCode == item.MaterielCode)?.MaterielName ?? ""; } } if (model.OrderType != InOrderTypeEnum.AllocatInbound.ObjToInt()) { model.InboundOrderNo = CreateCodeByRule(nameof(RuleCodeEnum.InboundOrderRule)); } Db.InsertNav(model).Include(x => x.Details).ExecuteCommand(); } return WebResponseContent.Instance.OK(); } catch (Exception ex) { return WebResponseContent.Instance.Error(ex.Message); } } public async Task UpdateInboundOrder(List models) { try { foreach (var model in models) { Dt_InboundOrder inboundOrder = Db.Queryable().Where(x => x.UpperOrderNo == model.UpperOrderNo).Includes(x => x.Details).First(); if (inboundOrder == null) { return WebResponseContent.Instance.Error($"未找到入库单信息"); } if (inboundOrder.Details == null || inboundOrder.Details.Count == 0) { return WebResponseContent.Instance.Error($"未找到入库单明细信息"); } if (inboundOrder.OrderStatus != InOrderStatusEnum.未开始.ObjToInt()) { return WebResponseContent.Instance.Error($"该订单状态不允许修改"); } List inboundOrderDetails = new List(); List updateInboundOrderDetails = new List(); List detailIds = new List(); var materielCodes = model.Details.Select(x => x.MaterielCode).Distinct().ToList(); var materielInfos = _materielInfoService.Db.Queryable().Where(x => materielCodes.Contains(x.MaterielCode)).ToList(); foreach (var item in model.Details) { if (!string.IsNullOrEmpty(item.Barcode)) { Dt_InboundOrderDetail? inboundOrderDetail = inboundOrder.Details.FirstOrDefault(x => x.Barcode == item.Barcode); if (inboundOrderDetail == null) { inboundOrderDetail = new Dt_InboundOrderDetail() { OrderId = inboundOrder.Id, lineNo = item.lineNo, MaterielCode = item.MaterielCode, SupplyCode = item.SupplyCode, BatchNo = item.BatchNo, Unit = item.Unit, WarehouseCode = item.WarehouseCode, Barcode = item.Barcode, OutBoxbarcodes = item.OutBoxbarcodes, BarcodeUnit = item.BarcodeUnit, BarcodeQty = item.BarcodeQty, OrderQuantity = item.OrderQuantity }; var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync(item.MaterielCode, item.BarcodeQty); inboundOrderDetail.Unit = purchaseToStockResult.Unit; inboundOrderDetail.OrderQuantity = purchaseToStockResult.Quantity; if (materielInfos.Any()) { inboundOrderDetail.MaterielName = materielInfos.FirstOrDefault(x => x.MaterielCode == item.MaterielCode)?.MaterielName ?? ""; } inboundOrderDetails.Add(inboundOrderDetail); } else { if (materielInfos.Any()) { inboundOrderDetail.MaterielName = materielInfos.FirstOrDefault(x => x.MaterielCode == item.MaterielCode)?.MaterielName ?? ""; } inboundOrderDetail.lineNo = item.lineNo; inboundOrderDetail.MaterielCode = item.MaterielCode; inboundOrderDetail.SupplyCode = item.SupplyCode; inboundOrderDetail.BatchNo = item.BatchNo; inboundOrderDetail.Unit = item.Unit; inboundOrderDetail.WarehouseCode = item.WarehouseCode; inboundOrderDetail.Barcode = item.Barcode; inboundOrderDetail.OutBoxbarcodes = item.OutBoxbarcodes; inboundOrderDetail.BarcodeUnit = item.BarcodeUnit; inboundOrderDetail.BarcodeQty = item.BarcodeQty; inboundOrderDetail.OrderQuantity = item.OrderQuantity; var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync(item.MaterielCode, item.BarcodeQty); inboundOrderDetail.Unit = purchaseToStockResult.Unit; inboundOrderDetail.OrderQuantity = purchaseToStockResult.Quantity; updateInboundOrderDetails.Add(inboundOrderDetail); detailIds.Add(inboundOrderDetail.Id); } } } inboundOrder.UpperOrderNo = model.UpperOrderNo; inboundOrder.BusinessType = model.BusinessType; inboundOrder.IsBatch = model.IsBatch; inboundOrder.FactoryArea = model.FactoryArea; List deletePurchaseOrderDetails = inboundOrder.Details.Where(x => !detailIds.Contains(x.Id)).ToList(); _unitOfWorkManage.BeginTran(); foreach (var item in deletePurchaseOrderDetails) { _inboundOrderDetailRepository.DeleteData(item); //_inboundOrderDetailRepository.DeleteAndMoveIntoHty(item, OperateTypeEnum.自动删除); } _inboundOrderDetailRepository.UpdateData(updateInboundOrderDetails); _inboundOrderDetailRepository.AddData(inboundOrderDetails); BaseDal.UpdateData(inboundOrder); _unitOfWorkManage.CommitTran(); } return WebResponseContent.Instance.OK(); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } public WebResponseContent DeleteInboundOrder(List models) { try { foreach (var model in models) { Dt_InboundOrder inboundOrder = Db.Queryable().Where(x => x.UpperOrderNo == model.UpperOrderNo).Includes(x => x.Details).First(); if (inboundOrder == null) { return WebResponseContent.Instance.Error($"未找到入库单信息"); } if (inboundOrder.Details == null || inboundOrder.Details.Count == 0) { return WebResponseContent.Instance.Error($"未找到入库单明细信息"); } if (inboundOrder.OrderStatus != InOrderStatusEnum.未开始.ObjToInt()) { return WebResponseContent.Instance.Error($"该订单状态不允许删除"); } //Db.DeleteNav(inboundOrder).Include(x => x.Details).ExecuteCommand(); _unitOfWorkManage.BeginTran(); //BaseDal.DeleteAndMoveIntoHty(inboundOrder, OperateTypeEnum.自动删除); foreach (var item in inboundOrder.Details) { _inboundOrderDetailRepository.DeleteData(item); //_inboundOrderDetailRepository.DeleteAndMoveIntoHty(item, OperateTypeEnum.自动删除); } BaseDal.DeleteData(inboundOrder); _unitOfWorkManage.CommitTran(); } return WebResponseContent.Instance.OK(); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } static object lock_code = new object(); public string CreateCodeByRule(string ruleCode) { lock (lock_code) { string code = string.Empty; DateTime dateTime = DateTime.Now; DateTime now = DateTime.Now; try { if (string.IsNullOrEmpty(ruleCode)) throw new ArgumentNullException(nameof(ruleCode)); SqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig { IsAutoCloseConnection = true, DbType = DbType.SqlServer, ConnectionString = DBContext.ConnectionString }); Dt_CodeRuleConfig codeRuleConfig = sugarClient.Queryable().Where(x => x.RuleCode == ruleCode).First(); if (codeRuleConfig == null) throw new ArgumentNullException(nameof(codeRuleConfig)); if (codeRuleConfig.ModifyDate != null) { dateTime = Convert.ToDateTime(codeRuleConfig.ModifyDate); } else { dateTime = Convert.ToDateTime(codeRuleConfig.CreateDate); } if (now.Year == dateTime.Year && now.Month == dateTime.Month && now.Day == dateTime.Day) { now = dateTime; codeRuleConfig.CurrentVal = Convert.ToInt32(codeRuleConfig.CurrentVal) + 1; } else { codeRuleConfig.CurrentVal = 1; } codeRuleConfig.ModifyDate = DateTime.Now; code = codeRuleConfig.StartStr + codeRuleConfig.Format; code = code.Replace($"[{CodeFormatTypeEnum.YYYY}]", now.Year.ToString().PadLeft(4, '0')); code = code.Replace($"[{CodeFormatTypeEnum.MM}]", now.Month.ToString().PadLeft(2, '0')); code = code.Replace($"[{CodeFormatTypeEnum.DD}]", now.Day.ToString().PadLeft(2, '0')); code = code.Replace($"[{CodeFormatTypeEnum.ST}]", codeRuleConfig.StartStr?.ToString() ?? ""); code = code.Replace($"[{CodeFormatTypeEnum.NUM}]", codeRuleConfig.CurrentVal.ToString().PadLeft(codeRuleConfig.Length, '0')); Dictionary keyValuePairs = new Dictionary() { { nameof(codeRuleConfig.CurrentVal), codeRuleConfig.CurrentVal }, { nameof(codeRuleConfig.Id), codeRuleConfig.Id }, { nameof(codeRuleConfig.ModifyDate), DateTime.Now } }; sugarClient.Updateable(keyValuePairs).AS(MainDb.CodeRuleConfig).WhereColumns(nameof(codeRuleConfig.Id)).ExecuteCommand(); sugarClient.Updateable(codeRuleConfig); } catch (Exception ex) { } return code; } } /// /// 根据入库单号获取入库单(含明细) /// /// /// public Dt_InboundOrder GetInboundOrder(string inboundOrderNo) { return BaseDal.Db.Queryable().Includes(x => x.Details).First(x => x.InboundOrderNo == inboundOrderNo); ; } public WebResponseContent BarcodeMaterielGroup(BarcodeMaterielGroupDTO materielGroupDTO) { WebResponseContent content = new WebResponseContent(); try { (bool, string, object?) result2 = ModelValidate.ValidateModelData(materielGroupDTO); if (!result2.Item1) return content = WebResponseContent.Instance.Error(result2.Item2); // materielGroupDTO.WarehouseCode var code = _warehouseAreaRepository.Db.Queryable().Where(x => x.Code == materielGroupDTO.WarehouseType).Select(x => x.Code).First(); if (string.IsNullOrEmpty(code)) { return content = WebResponseContent.Instance.Error($"仓库中没有该{materielGroupDTO.WarehouseType}编号。"); } Dt_InboundOrder inboundOrder = GetInboundOrder(materielGroupDTO.OrderNo); var dbinboundOrderDetails = _inboundOrderDetailService.GetByBarcode(materielGroupDTO.Barcodes); if (dbinboundOrderDetails != null && !dbinboundOrderDetails.Any()) { return content = WebResponseContent.Instance.Error($"单据中没有该{materielGroupDTO.Barcodes}条码数据。"); } List materielCodes = dbinboundOrderDetails.GroupBy(x => x.Barcode).Select(x => x.Key).ToList(); Dt_StockInfo? stockInfo = _stockService.StockInfoService.GetStockByPalletCode(materielGroupDTO.PalletCode); (bool, string, object?) result = CheckMaterielGroupParam(materielGroupDTO, materielCodes, inboundOrder, stockInfo); if (!result.Item1) return content = WebResponseContent.Instance.Error(result.Item2); if (stockInfo == null) { stockInfo = new Dt_StockInfo() { PalletType = (int)PalletTypeEnum.None, LocationType = materielGroupDTO.locationType.ObjToInt() }; stockInfo.Details = new List(); } foreach (var item in dbinboundOrderDetails) { stockInfo.Details.Add(new Dt_StockInfoDetail { StockId = stockInfo == null ? 0 : stockInfo.Id, Barcode = item.Barcode, MaterielCode = item.MaterielCode, BatchNo = item.BatchNo, Unit = item.Unit, InboundOrderRowNo = item.lineNo, SupplyCode = item.SupplyCode, WarehouseCode = materielGroupDTO.WarehouseType, StockQuantity = item.OrderQuantity, BarcodeQty = item.BarcodeQty, BarcodeUnit = item.BarcodeUnit, FactoryArea = inboundOrder.FactoryArea, Status = 0, OrderNo = inboundOrder.InboundOrderNo, BusinessType = inboundOrder.BusinessType, }); item.ReceiptQuantity = item.BarcodeQty; item.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt(); item.WarehouseCode = materielGroupDTO.WarehouseType; } if (stockInfo.Id == 0) { stockInfo.PalletCode = materielGroupDTO.PalletCode; stockInfo.StockStatus = StockStatusEmun.组盘暂存.ObjToInt(); } stockInfo.PalletType = (int)PalletTypeEnum.None; List updateDetailIds = dbinboundOrderDetails.Select(x => x.Id).ToList(); if (inboundOrder.OrderStatus == InOrderStatusEnum.未开始.ObjToInt()) { inboundOrder.OrderStatus = InOrderStatusEnum.入库中.ObjToInt(); } inboundOrder.Operator = App.User.UserName; content = MaterielGroupUpdateData(inboundOrder, dbinboundOrderDetails, stockInfo); if (content.Status) { return WebResponseContent.Instance.OK("", stockInfo.Details); } else { content = WebResponseContent.Instance.Error(content.Message); } } catch (Exception ex) { content = WebResponseContent.Instance.Error(ex.Message); } finally { } return content; } public WebResponseContent EmptyMaterielGroup(EmptyBarcodeMaterielGroupDTO materielGroupDTO) { WebResponseContent content = new WebResponseContent(); try { (bool, string, object?) result2 = ModelValidate.ValidateModelData(materielGroupDTO); if (!result2.Item1) return content = WebResponseContent.Instance.Error(result2.Item2); bool code = _locationTypeRepository.Db.Queryable().Where(x => x.LocationType == materielGroupDTO.WarehouseCode).Any(); bool statu = _locationInfoRepository.Db.Queryable().Where(x => x.LocationType == materielGroupDTO.WarehouseCode && x.LocationStatus == (int)LocationStatusEnum.Free).Any(); if (!statu) { return content = WebResponseContent.Instance.Error($"该区域无货位可分配"); } if (!code) { return content = WebResponseContent.Instance.Error($"区域中没有该{materielGroupDTO.WarehouseCode}编号。"); } if (_stockRepository.QueryFirst(x => x.PalletCode == materielGroupDTO.PalletCode) != null) { return WebResponseContent.Instance.Error("该托盘已经组过盘"); } Dt_StockInfo? stockInfo = _stockService.StockInfoService.GetStockByPalletCode(materielGroupDTO.PalletCode); if (stockInfo != null && !string.IsNullOrEmpty(stockInfo.LocationCode) && stockInfo.StockStatus != StockStatusEmun.组盘暂存.ObjToInt()) { return WebResponseContent.Instance.Error("已上架的托盘不能再次组盘"); } if (_taskRepository.QueryFirst(x => x.PalletCode == materielGroupDTO.PalletCode) != null) { return WebResponseContent.Instance.Error("该托盘号已有任务"); } try { if (stockInfo == null) { stockInfo = new Dt_StockInfo() { PalletType = PalletTypeEnum.Empty.ObjToInt(), StockStatus = StockStatusEmun.组盘暂存.ObjToInt(), PalletCode = materielGroupDTO.PalletCode, LocationType = materielGroupDTO.WarehouseCode.ObjToInt() }; stockInfo.Details = new List(); } else { stockInfo.PalletType = PalletTypeEnum.Empty.ObjToInt(); stockInfo.StockStatus = StockStatusEmun.组盘暂存.ObjToInt(); stockInfo.LocationType = materielGroupDTO.WarehouseCode.ObjToInt(); } _unitOfWorkManage.BeginTran(); _stockService.StockInfoService.AddMaterielGroup(stockInfo); _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK(); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } catch (Exception ex) { content = WebResponseContent.Instance.Error(ex.Message); } finally { } return content; } /// /// 验证组盘数据 /// /// 物料组盘DTO /// 扫码序列号 /// 物料信息 /// 物料编号 /// 入库单据 /// 组盘信息 /// public (bool, string, object?) CheckMaterielGroupParam(BarcodeMaterielGroupDTO materielGroupDTO, List barcodeCodes, Dt_InboundOrder inboundOrder, Dt_StockInfo stockInfo) { (bool, string, object?) result = ModelValidate.ValidateModelData(materielGroupDTO); if (!result.Item1) return result; if (_taskRepository.QueryFirst(x => x.PalletCode == materielGroupDTO.PalletCode) != null) { return (false, "该托盘号已有任务", materielGroupDTO); } if (stockInfo != null && !string.IsNullOrEmpty(stockInfo.LocationCode) && stockInfo.StockStatus != StockStatusEmun.组盘暂存.ObjToInt()) { return (false, "已上架的托盘不能再次组盘", materielGroupDTO); } if (_stockService.StockInfoDetailService.ExistBarcodes(barcodeCodes)) { return (false, $"{barcodeCodes[0]} 条码在库存中已存在", materielGroupDTO); } //if (materielInfos.Count != materielCodes.Count) //{ // return (false, "有物料信息未录入,请录入物料信息", materielGroupDTO); //} if (inboundOrder == null) { return (false, "单据不存在", materielGroupDTO); } if (inboundOrder.Details == null || inboundOrder.Details.Count == 0) { return (false, "无单据明细信息", materielGroupDTO); } if (inboundOrder.OrderStatus != InOrderStatusEnum.未开始.ObjToInt() && inboundOrder.OrderStatus != InOrderStatusEnum.入库中.ObjToInt()) { return (false, "该单据不可再组盘", materielGroupDTO); } List inboundOrderDetails = inboundOrder.Details.Where(x => barcodeCodes.Contains(x.Barcode)).ToList(); if (inboundOrderDetails.GroupBy(x => x.Barcode).Count() != barcodeCodes.Count) { return (false, "有物料不在单据内", materielGroupDTO); } IGrouping? temp = inboundOrder.Details.Where(x => barcodeCodes.Contains(x.Barcode)).GroupBy(x => x.Barcode).FirstOrDefault(x => x.Sum(v => v.OverInQuantity) >= x.Sum(v => v.OrderQuantity) || x.Sum(v => v.ReceiptQuantity) >= x.Sum(v => v.OrderQuantity)); if (temp != null) { return (false, "有物料超出单据数量", materielGroupDTO); } return (true, "成功", materielGroupDTO); } /// /// 组盘数据更新 /// /// 入库单 /// 入库单明细 /// 组盘数据 /// public WebResponseContent MaterielGroupUpdateData(Dt_InboundOrder inboundOrder, List inboundOrderDetails, Dt_StockInfo stockInfo) { try { _unitOfWorkManage.BeginTran(); UpdateData(inboundOrder); _inboundOrderDetailService.UpdateData(inboundOrderDetails); _stockService.StockInfoService.AddMaterielGroup(stockInfo); _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK(); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error(ex.Message); } } public WebResponseContent UnPalletQuantity(string orderNo) { // 初始化返回DTO(默认值都为0,避免null) var resultDTO = new PalletSumQuantityDTO { StockSumQuantity = 0, StockCount = 0, UniqueUnit = "" }; WebResponseContent content = new WebResponseContent(); try { if (string.IsNullOrWhiteSpace(orderNo)) { return content.Error("传入的订单号orderNo为空或空白"); } var orderDetail = _inboundOrderRepository.Db.Queryable().Includes(x => x.Details).Where(s => s.InboundOrderNo == orderNo).First(); if (orderDetail == null) { return content.Error("未找到单据"); } var unitGroups = orderDetail.Details.GroupBy(d => d.Unit).ToList(); if (unitGroups.Count == 1) { resultDTO.UniqueUnit = unitGroups.First().Key; } else { resultDTO.UniqueUnit = ""; } var inbound =_inboundOrderRepository.Db.Queryable().Where(x => x.InboundOrderNo == orderNo); var inboundDetails = _inboundOrderDetailRepository.Db.Queryable().Where(x => x.OrderId == inbound.First().Id).ToList(); resultDTO.StockSumQuantity = inboundDetails.Where(x=>x.ReceiptQuantity==0).Sum(x=>x.OrderQuantity); resultDTO.StockCount = inboundDetails.Where(x => x.ReceiptQuantity == 0).Count(); //var validDetails = _stockDetailRepository.Db.Queryable().Where(s => s.OrderNo == orderNo).ToList(); //resultDTO.StockSumQuantity = orderDetail.Details.Sum(d => d.OrderQuantity); //resultDTO.StockCount = orderDetail.Details.Count; //if (validDetails.Any()) //{ // resultDTO.StockSumQuantity -= validDetails.Sum(d => d.StockQuantity); // // 明细记录数:符合条件的有效记录条数 // resultDTO.StockCount -= validDetails.Count; //} return content.OK("", resultDTO); } catch (Exception ex) { return content.Error("SumQuantity 统计库存数量失败,订单号:{OrderNo}"); } } public WebResponseContent UndoPalletGroup(string palletCode, string barcode = "") { if (string.IsNullOrWhiteSpace(palletCode)) { return WebResponseContent.Instance.Error("托盘号不能为空"); } try { _unitOfWorkManage.BeginTran(); // 2. 查询托盘库存主记录(避免无数据抛异常) var stock = _stockRepository.Db.Queryable() .Includes(o => o.Details) .First(x => x.PalletCode == palletCode && (x.StockStatus == (int)StockStatusEmun.组盘暂存 || x.StockStatus == StockStatusEmun.入库确认.ObjToInt())); if (stock == null) { return WebResponseContent.Instance.Error($"未找到托盘号{palletCode}对应的库存记录"); } // 3. 场景1:删除指定条码 if (!string.IsNullOrWhiteSpace(barcode)) { var targetDetail = stock.Details?.FirstOrDefault(x => x.Barcode == barcode); if (targetDetail == null) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error($"托盘{palletCode}下未找到条码{barcode}的明细记录"); } ResetInboundOrderStatus(new List { targetDetail.OrderNo }, new List { targetDetail.Barcode }); // 删除指定明细 _stockDetailRepository.DeleteData(targetDetail); // 重新查询剩余明细(保证数据准确性) var remainingDetails = _stockDetailRepository.Db.Queryable() .Where(x => x.StockId == stock.Id) .ToList(); // 剩余明细为空 → 删除主表 + 重置入库单及明细状态 if (!remainingDetails.Any()) { // 重置入库单及明细状态 ResetInboundOrderStatus(stock.Details.Select(d => d.OrderNo).Distinct().ToList()); _stockRepository.DeleteData(stock); _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK($"条码{barcode}撤销成功,托盘无剩余明细,已删除托盘并重置关联入库单状态"); } _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK($"条码{barcode}撤销成功,托盘仍有剩余明细"); } // 删除整托盘(无条码传入) if (stock.Details == null || !stock.Details.Any()) { _stockRepository.DeleteData(stock); _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK("托盘无明细记录,已直接删除托盘主数据"); } // 有明细 → 重置入库单及明细状态 + 删除库存 var relatedOrderNos = stock.Details.Select(d => d.OrderNo).Distinct().ToList(); if (!relatedOrderNos.Any()) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error("库存明细未关联任何入库单号,无法完成撤销"); } // 重置入库单主状态 + 明细状态 ResetInboundOrderStatus(relatedOrderNos, stock.Details.Select(d => d.Barcode).ToList()); // 4.3 删除库存明细和主表 _stockDetailRepository.DeleteData(stock.Details); _stockRepository.DeleteData(stock); _unitOfWorkManage.CommitTran(); return WebResponseContent.Instance.OK("托盘撤销成功,已重置关联入库单及明细状态"); } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error($"托盘撤销失败:{ex.Message}"); } } private void ResetInboundOrderStatus(List orderNos, List barcodes = null) { foreach (var orderNo in orderNos) { var inboundOrder = _inboundOrderRepository.Db.Queryable() .Includes(x => x.Details) .First(x => x.InboundOrderNo == orderNo); if (inboundOrder == null) continue; bool isSingleBarcode = barcodes != null && barcodes.Count == 1; if (!isSingleBarcode) { // 非单个条码(整单/多个条码):重置主表状态为0 inboundOrder.OrderStatus = 0; _inboundOrderRepository.UpdateData(inboundOrder); } // 重置入库单明细状态 if (inboundOrder.Details == null || !inboundOrder.Details.Any()) continue; var targetDetails = barcodes == null ? inboundOrder.Details.ToList() // 不传条码则重置整单明细 : inboundOrder.Details.Where(d => barcodes.Contains(d.Barcode)).ToList(); foreach (var detail in targetDetails) { detail.ReceiptQuantity = 0; detail.OrderDetailStatus = 0; _inboundOrderDetailRepository.UpdateData(detail); } } } public override PageGridData GetPageData(PageDataOptions options) { string wheres = ValidatePageOptions(options); string pattern = @"inboundOrderNo like '[^']+'\s*and\s*"; wheres = Regex.Replace(wheres, pattern, "", RegexOptions.IgnoreCase); //获取排序字段 Dictionary orderbyDic = GetPageDataSort(options, TProperties); List orderByModels = new List(); foreach (var item in orderbyDic) { OrderByModel orderByModel = new() { FieldName = item.Key, OrderByType = item.Value }; orderByModels.Add(orderByModel); } ISugarQueryable sugarQueryable1 = BaseDal.Db.Queryable(); int totalCount = 0; List searchParametersList = new List(); if (!string.IsNullOrEmpty(options.Wheres)) { try { searchParametersList = options.Wheres.DeserializeObject>(); if (searchParametersList.Count > 0) { SearchParameters? searchParameters = searchParametersList.FirstOrDefault(x => x.Name == nameof(Dt_InboundOrder.InboundOrderNo).FirstLetterToLower()); if (searchParameters != null) { sugarQueryable1 = sugarQueryable1.Where(x => x.InboundOrderNo.Contains(searchParameters.Value.ToString()) || x.UpperOrderNo.Contains(searchParameters.Value.ToString()) || x.Details.Any(d => d.Barcode == searchParameters.Value.ToString())); } searchParameters = searchParametersList.FirstOrDefault(x => x.Name == nameof(Dt_InboundOrder.OrderType).FirstLetterToLower()); if (searchParameters != null) { sugarQueryable1 = sugarQueryable1.Where(x => x.OrderType.Equals(searchParameters.Value.ToString())); } //var dataList = sugarQueryable1.ToPageList(options.Page, options.Rows, ref totalCount); //return new PageGridData(totalCount, dataList); } options.Filter = searchParametersList; } catch { } } var data = sugarQueryable1 .WhereIF(!wheres.IsNullOrEmpty(), wheres) .Where(x => x.OrderType == 0) .OrderBy(orderByModels).Includes(x => x.Details) .ToPageList(options.Page, options.Rows, ref totalCount); return new PageGridData(totalCount, data); } //public override PageGridData GetPageData(PageDataOptions options) //{ // //var pageGridData = base.GetPageData(options); // ISugarQueryable sugarQueryable1 = BaseDal.Db.Queryable(); // if (!string.IsNullOrEmpty(options.Wheres)) // { // List searchParametersList = options.Wheres.DeserializeObject>(); // int totalCount = 0; // if (searchParametersList.Count > 0) // { // SearchParameters? searchParameters = searchParametersList.FirstOrDefault(x => x.Name == nameof(Dt_InboundOrder.InboundOrderNo).FirstLetterToLower()); // if (searchParameters != null) // { // sugarQueryable1 = sugarQueryable1.Where(x => x.InboundOrderNo.Contains(searchParameters.Value.ToString()) // || x.UpperOrderNo.Contains(searchParameters.Value.ToString()) || // x.Details.Any(d => d.Barcode == searchParameters.Value.ToString())); // } // searchParameters = searchParametersList.FirstOrDefault(x => x.Name == nameof(Dt_InboundOrder.OrderType).FirstLetterToLower()); // if (searchParameters != null) // { // sugarQueryable1 = sugarQueryable1.Where(x => x.OrderType.Equals(searchParameters.Value.ToString())); // } // var dataList = sugarQueryable1.ToPageList(options.Page, options.Rows, ref totalCount); // return new PageGridData(totalCount, dataList); // } // } // return new PageGridData(); //} public WebResponseContent UnPalletGroupBarcode(string orderNo) { WebResponseContent content = new WebResponseContent(); var inbound = _inboundOrderRepository.Db.Queryable().Where(x => x.InboundOrderNo == orderNo).First(); if(inbound == null) { return content.Error(); } var details = _inboundOrderDetailRepository.Db.Queryable().Where(x => x.OrderId == inbound.Id && x.ReceiptQuantity == 0).ToList(); return content.OK(data:details); } } }