namespace WIDESEA_StorageOutOrderServices; public class Dt_PaintingOrderInfoService : ServiceBase, IDt_PaintingOrderInfoService { private readonly LogFactory LogFactory = new LogFactory(); private readonly IUnitOfWorkManage _unitOfWorkManage; private readonly IDt_OutOrderProductionService _outOrderProductionService; private readonly IDt_OutOrderProductionDetailService _outOrderProductionDetailService; private readonly IDt_OutOrderDtailService _outOrderDtailService; private readonly IDt_OutOrderTransferRepository _OutOrderTransferRepository; private readonly IDt_OutOrderTransferDetailRepository _OutOrderTransferDetailRepository; private readonly IDt_MaterielInfoRepository _materielInfoRepository; private readonly IStockInfoRepository _stockInfoRepository; private readonly IDt_OutOrderAndStockRepository _outOrderAndStockRepository; private readonly IDt_TaskRepository _taskRepository; public Dt_PaintingOrderInfoService(IDt_PaintingOrderInfoRepository BaseDal, IUnitOfWorkManage unitOfWorkManage, IDt_OutOrderProductionService outOrderProductionService, IDt_OutOrderProductionDetailService outOrderProductionDetailService, IDt_OutOrderDtailService outOrderDtailService, IDt_OutOrderTransferDetailRepository outOrderTransferDetailRepository, IDt_OutOrderTransferRepository outOrderTransferRepository, IDt_MaterielInfoRepository materielInfoRepository, IStockInfoRepository stockInfoRepository, IDt_OutOrderAndStockRepository outOrderAndStockRepository, IDt_TaskRepository taskRepository) : base(BaseDal) { _unitOfWorkManage = unitOfWorkManage; _outOrderProductionService = outOrderProductionService; _outOrderProductionDetailService = outOrderProductionDetailService; _outOrderDtailService = outOrderDtailService; _OutOrderTransferDetailRepository = outOrderTransferDetailRepository; _OutOrderTransferRepository = outOrderTransferRepository; _materielInfoRepository = materielInfoRepository; _stockInfoRepository = stockInfoRepository; _outOrderAndStockRepository = outOrderAndStockRepository; _taskRepository = taskRepository; } /// /// 根据订单分配出库库存 /// /// 订单编号 /// public async Task GetOutboundStockAsync(string orderNo) { WebResponseContent content = new WebResponseContent(); try { // 获取订单 //var order = await BaseDal.GetOutOrderByNumberAsync(orderNo); //LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "根据订单编号获取订单数据", JsonConvert.SerializeObject(order)); //// 检查订单是否获取成功 //if (order == null) //{ // return content.Error("获取订单失败"); //} //// 获取订单中的第一个物料编号 //var materielInfo = await _materielInfoRepository.QueryFirstAsync(x => x.MaterielID == order.OrderDetailList.MaterialId); //LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "获取订单物料编号", JsonConvert.SerializeObject(materielInfo)); //#region 先入先出 //// 获取该物料所有可出库库存 //var filteredStocks = await _stockInfoRepository.QueryDataAsync(x => true); //filteredStocks.OrderBy(x => x.CreateDate).ToList(); //LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "获取该物料所有可出库库存", JsonConvert.SerializeObject(filteredStocks)); //#endregion 先入先出 //#region 查找靠近出库口库存 //// 默认列越大越靠近出库口 //filteredStocks = filteredStocks.OrderByDescending(x => x.LocationInfo.Column).OrderBy(x => x.CreateDate).ToList(); //#endregion 查找靠近出库口库存 //#region 一深位优先查找,再查找同列二深位 //filteredStocks = PickStocks(filteredStocks); //#endregion 一深位优先查找,再查找同列二深位 //// 创建任务列表 //var (tasks, updateOrder, stock) = CreateTasks(order, filteredStocks); //LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "创建任务列表,修改订单分配数量,获取出库分配库存", // $"任务列表:{JsonConvert.SerializeObject(tasks)},订单列表:{JsonConvert.SerializeObject(updateOrder)},已分配库存:{JsonConvert.SerializeObject(stock)}"); //// 更新库存状态 //var stockList = UpdateStocks(stock); //LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "更新库存状态", JsonConvert.SerializeObject(stockList)); //// 创建订单库存列表 //List? orderStocks = CreateOrderStock(stock, updateOrder); //LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "创建订单库存列表", JsonConvert.SerializeObject(orderStocks)); //// 开始事务 //_unitOfWorkManage.BeginTran(); //// 更新库存 //var isStockUpdated = _stockInfoRepository.UpdateData(stockList); //LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "事务更新库存", isStockUpdated); //// 更新订单 //var isOrderUpdated = await BaseDal.OutOrderUpdatedAsync(updateOrder); //LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "事务更新订单", isOrderUpdated); ////添加订单库存 //var isOrderStockCread = await _outOrderAndStockRepository.AddDataAsync(orderStocks) > 0; //LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "事务添加订单库存", isOrderStockCread); //// 创建任务 //var isTaskCreated = await _taskRepository.Create(tasks); //LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "事务创建任务", isTaskCreated); //// 提交或回滚事务 //if (isStockUpdated && isTaskCreated && isOrderUpdated && isOrderStockCread) //{ // LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "数据处理完成,提交事务", "无参数"); // _unitOfWorkManage.CommitTran(); //} //else //{ // LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, "添加数据库失败,请检查数据是否正确,数据回滚", $"更新库存:{isStockUpdated},更新订单:{isOrderUpdated},添加订单库存:{isOrderStockCread},创建任务:{isTaskCreated}"); // _unitOfWorkManage.RollbackTran(); // throw new Exception("添加数据库失败,请检查数据是否正确,数据回滚"); //} return content.OK(); //data: orderStocks } catch (Exception ex) { _unitOfWorkManage.RollbackTran(); LogFactory.GetLog("出库分配并创建任务").InfoFormat(true, $"系统异常,异常信息:{ex.Message}", "无参数"); return content.Error(ex.Message); } } #region 内部调用 /// /// 一深位优先查找 /// /// 可出库库存 /// 排序好的出库库存 public List PickStocks(List filteredStocks) { var oneDepthList = filteredStocks.Where(x => x.LocationInfo.Depth == 1).ToList(); var twoDepthList = filteredStocks.Where(x => x.LocationInfo.Depth == 2).ToList(); var results = new List(); foreach (var oneDepth in oneDepthList) { // 将 Line 字符串转换为整数 int oneDepthLine = oneDepth.LocationInfo.Row; // 计算相对行 int relativeLine = oneDepthLine % 2 == 1 ? oneDepthLine + 1 : oneDepthLine - 1; // 查找最接近的二深位记录 var closestTwoDepth = twoDepthList .Where(t => t.LocationInfo.Row == relativeLine) .Where(x => x.LocationInfo.Column == oneDepth.LocationInfo.Column) .Where(x => x.LocationInfo.Layer == oneDepth.LocationInfo.Layer) .FirstOrDefault(); // 如果找到了最接近的二深位记录,将其与一深位一起添加到结果列表 if (closestTwoDepth != null) { results.Add(oneDepth); results.Add(closestTwoDepth); } else { // 如果没有找到最接近的二深位记录,将一深位添加到结果列表 results.Add(oneDepth); } } return results; } #endregion 内部调用 #region 私有方法 #region 生产出库单 /// /// 根据主数据构建生产出库单对象。 /// private Dt_OutOrderProduction CreateProductionOrder(Dictionary mainData) { return new Dt_OutOrderProduction { OrderNumber = mainData.GetValueOrDefault("OrderNumber")?.ToString(), WarehouseId = mainData.GetValueOrDefault("WarehouseId")?.ObjToInt() ?? 0, Status = (int)OutOrderTypeEnum.Issue, Remarks = mainData.GetValueOrDefault("Remarks")?.ToString(), Creater = mainData.GetValueOrDefault("Creater")?.ToString(), CreateDate = mainData.GetValueOrDefault("CreateDate")?.ObjToDate() ?? DateTime.Now, OrderDate = mainData.GetValueOrDefault("OrderDate")?.ObjToDate() ?? DateTime.Now, }; } /// /// 根据明细数据和生产出库单ID构建生产出库单明细列表。 /// private List CreateProductionDetails(List> detailData) { var details = new List(); foreach (var item in detailData) { var detail = new Dt_OutOrderProductionDetail { MaterialId = item.GetValueOrDefault("MaterialId")?.ObjToInt() ?? 0, Quantity = item.GetValueOrDefault("Quantity")?.ObjToInt() ?? 0, Remarks = item.GetValueOrDefault("Remarks")?.ToString(), CreateDate = item.GetValueOrDefault("CreateDate")?.ObjToDate() ?? DateTime.Now, Creater = item.GetValueOrDefault("Creater")?.ToString(), BatchNumber = item.GetValueOrDefault("BatchNumber")?.ToString(), }; details.Add(detail); } return details; } /// /// 根据生产出库单对象和生产出库单ID构建系统出库单对象。 /// private Dt_OutOrder CreateSystemOrder(Dt_OutOrderProduction production) { return new Dt_OutOrder { Status = production.Status, CreateDate = DateTime.Now, Creater = production.Creater, OrderDate = DateTime.Now, OrderNumber = production.OrderNumber, Remarks = production.Remarks, WarehouseId = production.WarehouseId, }; } /// /// 根据生产出库单明细列表和系统出库单ID构建系统出库单明细列表。 /// private List CreateSystemOrderDetails(List productionDetails) { var orderDetails = new List(); foreach (var item in productionDetails) { var detail = new Dt_OutOrderDetail { AllocatedQuantity = 0, BatchNumber = item.BatchNumber, CompletedQuantity = 0, CreateDate = item.CreateDate, Creater = item.Creater, MaterialId = item.MaterialId, OutboundQuantity = item.Quantity, Remarks = item.Remarks, MaterialName = item.Remarks // 物料名称 }; orderDetails.Add(detail); } return orderDetails; } #endregion 生产出库单 #region 调拨出库单 /// /// 根据主数据构建调拨出库单对象。 /// private Dt_OutOrderTransfer CreateTransferOrder(Dictionary mainData) { return new Dt_OutOrderTransfer { OrderNumber = mainData.GetValueOrDefault("OrderNumber")?.ToString(), SourceWarehouseId = mainData.GetValueOrDefault("SourceWarehouseId")?.ObjToInt() ?? 0, DestinationWarehouseId = mainData.GetValueOrDefault("WarehouseId")?.ObjToInt() ?? 0, Status = (int)OutOrderTypeEnum.Allocate, Remarks = mainData.GetValueOrDefault("Remarks")?.ToString(), Creater = mainData.GetValueOrDefault("Creater")?.ToString(), CreateDate = mainData.GetValueOrDefault("CreateDate")?.ObjToDate() ?? DateTime.Now, OrderDate = mainData.GetValueOrDefault("OrderDate")?.ObjToDate() ?? DateTime.Now, }; } /// /// 根据明细数据和调拨出库单ID构建调拨出库单明细列表。 /// private List CreateTransferDetails(List> detailData) { var details = new List(); foreach (var item in detailData) { var detail = new Dt_OutOrderTransferDetail { MaterialId = item.GetValueOrDefault("MaterialId")?.ObjToInt() ?? 0, Quantity = item.GetValueOrDefault("Quantity")?.ObjToInt() ?? 0, Remarks = item.GetValueOrDefault("Remarks")?.ToString(), CreateDate = item.GetValueOrDefault("CreateDate")?.ObjToDate() ?? DateTime.Now, Creater = item.GetValueOrDefault("Creater")?.ToString(), BatchNumber = item.GetValueOrDefault("BatchNumber")?.ToString(), }; details.Add(detail); } return details; } /// /// 根据生产出库单对象和生产出库单ID构建系统出库单对象。 /// private Dt_OutOrder CreateSystemOrder(Dt_OutOrderTransfer transfer) { return new Dt_OutOrder { Status = transfer.Status, CreateDate = DateTime.Now, Creater = transfer.Creater, OrderDate = DateTime.Now, OrderNumber = transfer.OrderNumber, Remarks = transfer.Remarks, WarehouseId = transfer.SourceWarehouseId, }; } /// /// 根据生产出库单明细列表和系统出库单ID构建系统出库单明细列表。 /// private List CreateSystemOrderDetails(List transferDetails) { var orderDetails = new List(); foreach (var item in transferDetails) { var detail = new Dt_OutOrderDetail { AllocatedQuantity = 0, BatchNumber = item.BatchNumber, CompletedQuantity = 0, CreateDate = item.CreateDate, Creater = item.Creater, MaterialId = item.MaterialId, OutboundQuantity = item.Quantity, Remarks = item.Remarks, MaterialName = item.Remarks // 物料名称 }; orderDetails.Add(detail); } return orderDetails; } #endregion 调拨出库单 #region 出库分配 /// /// 创建任务列表 /// /// 订单对象 /// 筛选后的库存列表 /// 【任务列表,更新分配数量订单,创建任务的库存】 private (List, Dt_OutOrder, List) CreateTasks(Dt_OutOrder order, List filteredStocks) { var tasks = new List(); var stocks = new List(); foreach (var stock in filteredStocks) { // 如果已分配数量达到出库数量,停止分配 if (order.OrderDetailList.AllocatedQuantity >= order.OrderDetailList.OutboundQuantity) break; // 如果托盘任务已存在,跳过 if (_taskRepository.QueryFirst(x => x.PalletCode == stock.PalletCode) != null) continue; // 创建任务 tasks.Add(new Dt_Task { CreateDate = DateTime.Now, // 创建时间 Creater = App.User.UserName, // 创建人 CurrentAddress = stock.LocationCode, //当前位置 Dispatchertime = DateTime.Now, //调度时间(任务下发时间) Grade = 1, // 等级 //PVI = stock.StockInfoDetails[0].MaterielCode, // 物料号 NextAddress = stock.LocationCode, // 下一位置 PalletCode = stock.PalletCode, //托盘号 Remark = stock.Remark, //备注 Roadway = stock.LocationInfo.RoadwayNo, //巷道 SourceAddress = stock.LocationCode, //来源位置 TargetAddress = order.OrderDetailList.Remarks, //目标地址 TaskNum = _taskRepository.GetTaskNo().Result, //任务号 TaskState = (int)TaskOutStatusEnum.OutNew, //任务状态 TaskType = (int)TaskTypeEnum.Outbound, //任务类型 }); // 更新已分配数量 order.OrderDetailList.AllocatedQuantity += stock.StockInfoDetails.Sum(x => x.StockQuantity); stocks.Add(stock); } return (tasks, order, stocks); } /// /// 更新库存状态 /// /// 筛选后的库存列表 /// 更新后的库存列表 private List UpdateStocks(List filteredStocks) { var updatedStocks = new List(); foreach (var stock in filteredStocks) { // 更新库存状态 stock.LocationInfo.LocationStatus = (int)LocationEnum.Lock; stock.StockInfoDetails.ForEach(x => { x.Status = (int)StockStateEmun.出库锁定; }); updatedStocks.Add(stock); } return updatedStocks; } /// /// 创建订单库存列表 /// /// 筛选后的库存列表 /// 订单对象 /// 订单库存列表 private List CreateOrderStock(List stock, Dt_OutOrder order) { var orderStocks = new List(); foreach (var item in stock) { orderStocks.Add(new Dt_OutOrderAndStock() { AllocatedQuantity = order.OrderDetailList.AllocatedQuantity, MaterialNo = item.StockInfoDetails[0].MaterielCode, MaterialName = order.OrderDetailList.MaterialName, OrderNumber = order.OrderNumber, OutboundQuantity = order.OrderDetailList.OutboundQuantity, PalletCode = item.PalletCode, PalletQuantity = item.StockInfoDetails.Sum(x => x.StockQuantity), State = item.StockInfoDetails[0].Status, BatchNumber = order.OrderDetailList.BatchNumber, CompletedQuantity = order.OrderDetailList.CompletedQuantity, Creater = App.User.UserName, CreateDate = DateTime.Now, GroupId = item.Id, LocationCode = item.LocationInfo.LocationCode, OutOrderId = order.Id, }); } return orderStocks; } #endregion 出库分配 #endregion 私有方法 }