namespace WIDESEA_StorageOutOrderServices;
|
|
public class Dt_AssemblyOrderInfoService : ServiceBase<Dt_AssemblyOrderInfo, IDt_AssemblyOrderInfoRepository>, IDt_AssemblyOrderInfoService
|
{
|
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_AssemblyOrderInfoService(IDt_AssemblyOrderInfoRepository 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;
|
}
|
|
|
|
/// <summary>
|
/// 根据订单分配出库库存
|
/// </summary>
|
/// <param name="orderNo">订单编号</param>
|
/// <returns></returns>
|
public async Task<WebResponseContent> 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<Dt_OutOrderAndStock>? 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 内部调用
|
|
/// <summary>
|
/// 一深位优先查找
|
/// </summary>
|
/// <param name="filteredStocks">可出库库存</param>
|
/// <returns>排序好的出库库存</returns>
|
public List<DtStockInfo> PickStocks(List<DtStockInfo> 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<DtStockInfo>();
|
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 生产出库单
|
|
/// <summary>
|
/// 根据主数据构建生产出库单对象。
|
/// </summary>
|
private Dt_OutOrderProduction CreateProductionOrder(Dictionary<string, object> 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,
|
};
|
}
|
|
/// <summary>
|
/// 根据明细数据和生产出库单ID构建生产出库单明细列表。
|
/// </summary>
|
private List<Dt_OutOrderProductionDetail> CreateProductionDetails(List<Dictionary<string, object>> detailData)
|
{
|
var details = new List<Dt_OutOrderProductionDetail>();
|
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;
|
}
|
|
/// <summary>
|
/// 根据生产出库单对象和生产出库单ID构建系统出库单对象。
|
/// </summary>
|
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,
|
};
|
}
|
|
/// <summary>
|
/// 根据生产出库单明细列表和系统出库单ID构建系统出库单明细列表。
|
/// </summary>
|
private List<Dt_OutOrderDetail> CreateSystemOrderDetails(List<Dt_OutOrderProductionDetail> productionDetails)
|
{
|
var orderDetails = new List<Dt_OutOrderDetail>();
|
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 调拨出库单
|
|
/// <summary>
|
/// 根据主数据构建调拨出库单对象。
|
/// </summary>
|
private Dt_OutOrderTransfer CreateTransferOrder(Dictionary<string, object> 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,
|
};
|
}
|
|
/// <summary>
|
/// 根据明细数据和调拨出库单ID构建调拨出库单明细列表。
|
/// </summary>
|
private List<Dt_OutOrderTransferDetail> CreateTransferDetails(List<Dictionary<string, object>> detailData)
|
{
|
var details = new List<Dt_OutOrderTransferDetail>();
|
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;
|
}
|
|
/// <summary>
|
/// 根据生产出库单对象和生产出库单ID构建系统出库单对象。
|
/// </summary>
|
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,
|
};
|
}
|
|
/// <summary>
|
/// 根据生产出库单明细列表和系统出库单ID构建系统出库单明细列表。
|
/// </summary>
|
private List<Dt_OutOrderDetail> CreateSystemOrderDetails(List<Dt_OutOrderTransferDetail> transferDetails)
|
{
|
var orderDetails = new List<Dt_OutOrderDetail>();
|
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 出库分配
|
|
/// <summary>
|
/// 创建任务列表
|
/// </summary>
|
/// <param name="order">订单对象</param>
|
/// <param name="filteredStocks">筛选后的库存列表</param>
|
/// <returns>【任务列表,更新分配数量订单,创建任务的库存】</returns>
|
private (List<Dt_Task>, Dt_OutOrder, List<DtStockInfo>) CreateTasks(Dt_OutOrder order, List<DtStockInfo> filteredStocks)
|
{
|
var tasks = new List<Dt_Task>();
|
var stocks = new List<DtStockInfo>();
|
|
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);
|
}
|
|
/// <summary>
|
/// 更新库存状态
|
/// </summary>
|
/// <param name="filteredStocks">筛选后的库存列表</param>
|
/// <returns>更新后的库存列表</returns>
|
private List<DtStockInfo> UpdateStocks(List<DtStockInfo> filteredStocks)
|
{
|
var updatedStocks = new List<DtStockInfo>();
|
|
foreach (var stock in filteredStocks)
|
{
|
// 更新库存状态
|
stock.LocationInfo.LocationStatus = (int)LocationEnum.Lock;
|
stock.StockInfoDetails.ForEach(x =>
|
{
|
x.Status = (int)StockStateEmun.出库锁定;
|
});
|
updatedStocks.Add(stock);
|
}
|
|
return updatedStocks;
|
}
|
|
/// <summary>
|
/// 创建订单库存列表
|
/// </summary>
|
/// <param name="stock">筛选后的库存列表</param>
|
/// <param name="order">订单对象</param>
|
/// <returns>订单库存列表</returns>
|
private List<Dt_OutOrderAndStock> CreateOrderStock(List<DtStockInfo> stock, Dt_OutOrder order)
|
{
|
var orderStocks = new List<Dt_OutOrderAndStock>();
|
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 私有方法
|
}
|