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_Common.TaskEnum; 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_DTO.Stock; 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; private readonly IRepository _allocateOrderRepository; private readonly IRepository _outboundOrderRepository; 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, IRepository allocateOrderRepository, IRepository outboundOrderRepository) : 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; _allocateOrderRepository = allocateOrderRepository; _outboundOrderRepository = outboundOrderRepository; } 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) { Dt_MaterielInfo materielInfo = materielInfos.First(x => x.MaterielCode == item.MaterielCode); //var purchaseToStockResult = await _materialUnitService.ConvertPurchaseToStockAsync(item.MaterielCode, item.BarcodeQty); UnitConvertResultDTO totalResult = _basicService.UnitQuantityConvert(item.MaterielCode, item.Unit, materielInfo.inventoryUOM, 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 && x.EnableStatus == (int)EnableStatusEnum.Normal).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 code) { if (string.IsNullOrWhiteSpace(code)) { return WebResponseContent.Instance.Error("托盘号或条码不能为空"); } try { _unitOfWorkManage.BeginTran(); // 智能识别输入类型 string palletCode = null; string barcode = null; // 1. 先尝试按托盘号查询 var stockByPallet = _stockRepository.Db.Queryable() .Includes(o => o.Details) .First(x => x.PalletCode == code && (x.StockStatus == (int)StockStatusEmun.组盘暂存 || x.StockStatus == StockStatusEmun.入库确认.ObjToInt())); if (stockByPallet != null) { // 识别为托盘号 palletCode = code; var task =_taskRepository.Db.Queryable().Where(t => t.PalletCode == palletCode).ToList(); if(task!=null && task.Any()) { return WebResponseContent.Instance.Error($"托盘号 {palletCode} 存在未完成的任务,无法撤销"); } } else { var detail = _stockDetailRepository.Db.Queryable().Where(d => d.Barcode == code).First(); if (detail != null) { var stockInfo = _stockRepository .Db.Queryable() .Where(s => s.Id == detail.StockId&& (s.StockStatus == (int)StockStatusEmun.组盘暂存 || s.StockStatus == StockStatusEmun.入库确认.ObjToInt())) .First(); if (stockInfo != null) { barcode = code; palletCode = stockInfo.PalletCode; } } else { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error($"未找到 {code} 对应的托盘或条码记录"); } } // 根据识别结果执行撤销逻辑 if (!string.IsNullOrWhiteSpace(barcode)) { // ===== 撤销指定条码 ===== 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) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error($"未找到托盘号 {palletCode} 对应的库存记录"); } 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} 撤销成功,托盘仍有剩余明细"); } else { // ===== 撤销整个托盘 ===== 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) { _unitOfWorkManage.RollbackTran(); return WebResponseContent.Instance.Error($"未找到托盘号 {palletCode} 对应的库存记录"); } 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()); _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; if(inboundOrder.BusinessType == "11") { detail.WarehouseCode = ""; } _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()) || x.Details.Any(d => d.OutBoxbarcodes == 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 detailMaterielCode = searchParametersList.FirstOrDefault(x => x.Name == "materielCode"); if(detailMaterielCode!=null && !string.IsNullOrEmpty(detailMaterielCode.Value?.ToString())) { string materielCode = detailMaterielCode.Value.ToString().Trim(); sugarQueryable1 = sugarQueryable1.Where(x => x.Details.Any(d => d.MaterielCode.Contains(materielCode))); } //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); } public WebResponseContent GetLocationType(string code) { var warehouseAreaName = _warehouseAreaRepository.QueryFirst(x => x.Code == code); if(string.IsNullOrWhiteSpace(warehouseAreaName.ToString())) { return WebResponseContent.Instance.Error("未找到仓库名称"); } var locationTypeDesc = _locationTypeRepository.Db.Queryable().Where(x => string.Equals(x.LocationTypeDesc, warehouseAreaName.Name, StringComparison.OrdinalIgnoreCase)).First(); return WebResponseContent.Instance.OK(data:locationTypeDesc.LocationType); } public WebResponseContent HandCloseOrder(List orderNos) { try { foreach (var orderNo in orderNos) { var inbound = _inboundOrderRepository.QueryFirst(x => x.InboundOrderNo == orderNo); var outbound = _outboundOrderRepository.QueryFirst(x=>x.OrderNo == orderNo); if (inbound != null) { if (inbound.OrderStatus != (int)InOrderStatusEnum.未开始 && inbound.OrderStatus != (int)InOrderStatusEnum.入库中) { return WebResponseContent.Instance.Error($"该单据状态不可以关闭"); } inbound.OrderStatus = (int)InOrderStatusEnum.手动关闭; inbound.Operator = App.User.UserName; _inboundOrderRepository.UpdateData(inbound); var inboundItems = _inboundOrderDetailRepository.QueryData(x => x.OrderId == inbound.Id); if(inboundItems.FirstOrDefault().OrderDetailStatus == (int)OrderDetailStatusEnum.New) { foreach (var item in inboundItems) { item.OrderDetailStatus = (int)InOrderStatusEnum.手动关闭; item.Modifier = App.User.UserName; BaseDal.Db.Updateable(item).ExecuteCommand(); } } } else if (outbound != null) { if(outbound.OrderStatus !=(int)OutOrderStatusEnum.未开始 && outbound.OrderStatus != (int)OutOrderStatusEnum.出库中) { return WebResponseContent.Instance.Error($"该单据状态不可以关闭"); } outbound.OrderStatus = (int)OutOrderStatusEnum.关闭; outbound.Operator = App.User.UserName; _outboundOrderRepository.UpdateData(outbound); var outboundItems = BaseDal.Db.Queryable().Where(x => x.OrderId == outbound.Id).ToList(); if(outboundItems.FirstOrDefault().OrderDetailStatus == (int)OrderDetailStatusEnum.New) foreach(var item in outboundItems) { item.OrderDetailStatus = (int)OutOrderStatusEnum.关闭; item.Modifier = App.User.UserName; BaseDal.Db.Updateable(item).ExecuteCommand(); } } } return WebResponseContent.Instance.OK($"单据关闭成功"); } catch (Exception e) { return WebResponseContent.Instance.Error(e.Message); } } } }