using AutoMapper;
|
using System.Threading.Tasks;
|
using WIDESEA_Common;
|
using WIDESEA_Common.Location;
|
using WIDESEA_Core;
|
using WIDESEA_Core.BaseRepository;
|
using WIDESEA_Core.BaseServices;
|
using WIDESEA_Core.Helper;
|
using WIDESEA_IRepository;
|
using WIDESEA_IServices;
|
using WIDESEA_Model.Models;
|
|
namespace WIDESEA_Services
|
{
|
public class Dt_BillGroupStockService : ServiceBase<Dt_BillGroupStock, IDt_BillGroupStockRepository>, IDt_BillGroupStockService
|
{
|
private readonly IUnitOfWorkManage _unitOfWorkManage;
|
private readonly IDt_OutOrderService _outOrderService;
|
private readonly IDt_TaskService _taskService;
|
private readonly IDt_OutOrderAndStockRepository _OutOrderAndStockRepository;
|
private readonly IDt_OutOrderAndStock_HtyService _OutOrderAndStock_HtyService;
|
private readonly IDt_Task_HtyService _Task_HtyService;
|
private readonly IMapper _mapper;
|
|
public Dt_BillGroupStockService(IDt_BillGroupStockRepository baseDal,
|
IUnitOfWorkManage unitOfWorkManage,
|
IDt_OutOrderService outOrderService,
|
IDt_TaskService taskService,
|
IDt_OutOrderAndStockRepository outOrderAndStockRepository,
|
IMapper mapper,
|
IDt_OutOrderAndStock_HtyService outOrderAndStock_HtyService,
|
IDt_Task_HtyService task_HtyService) : base(baseDal)
|
{
|
_unitOfWorkManage = unitOfWorkManage;
|
_outOrderService = outOrderService;
|
_taskService = taskService;
|
_OutOrderAndStockRepository = outOrderAndStockRepository;
|
_mapper = mapper;
|
_OutOrderAndStock_HtyService = outOrderAndStock_HtyService;
|
_Task_HtyService = task_HtyService;
|
}
|
|
/// <summary>
|
/// 根据特定条件获取库存
|
/// </summary>
|
/// <param name="palletCode">托盘号</param>
|
/// <param name="locationID">货位ID</param>
|
/// <param name="materialNo">物料编号</param>
|
/// <returns>特定库存</returns>
|
public async Task<Dt_BillGroupStock> GetStocks(string palletCode = null, string locationID = null, string materialNo = null)
|
{
|
return await Db.Queryable<Dt_BillGroupStock>()
|
.WhereIF(palletCode != null, x => x.PalletCode == palletCode)
|
.WhereIF(locationID != null, x => x.LocationCode == locationID)
|
.WhereIF(materialNo != null, x => x.MaterialNo == materialNo)
|
.Includes(x => x.LocationInfo)
|
.Includes(x => x.StockDetailList)
|
.FirstAsync();
|
}
|
|
/// <summary>
|
/// 获取所有可出库库存,不包括已经出库的或已经分配的。
|
/// </summary>
|
/// <returns>出库库存列表</returns>
|
public async Task<WebResponseContent> GetOutboundStock()
|
{
|
WebResponseContent content = new WebResponseContent();
|
try
|
{
|
#region 前期没数据临时开发使用,后期更换根据订单进行筛选库存
|
|
// 获取所有可出库库存
|
var stocks = BaseDal.GetOutboundStockList();
|
|
// 获取订单
|
var order = GetOrder("2");
|
|
// 检查订单是否获取成功
|
if (order == null)
|
{
|
return content.Error("获取订单失败");
|
}
|
// 获取订单中的第一个物料号
|
var materialNo = order.OrderDetailList.MaterialId;
|
|
// 筛选并排序库存
|
var filteredStocks = stocks.Where(x => x.MaterialNo == materialNo.ToString())
|
.OrderBy(x => x.CreateDate)
|
.ToList();
|
|
#endregion 前期没数据临时开发使用,后期更换根据订单进行筛选库存
|
|
// 创建任务列表
|
var (tasks, updateOrder) = CreateTasks(order, filteredStocks);
|
|
// 更新库存状态
|
var stockList = UpdateStocks(filteredStocks, updateOrder);
|
|
// 创建订单库存列表
|
var orderStocks = CreateOrderStock(filteredStocks, updateOrder, tasks);
|
|
// 开始事务
|
_unitOfWorkManage.BeginTran();
|
|
// 更新库存
|
var isStockUpdated = BaseDal.UpdateNavStock(stockList);
|
|
// 更新订单
|
var isOrderUpdated = await _outOrderService.OutOrderUpdated(updateOrder);
|
|
//添加订单库存
|
var isOrderStockCread = _OutOrderAndStockRepository.AddData(orderStocks) > 0;
|
|
// 创建任务
|
var isTaskCreated = await _taskService.Create(tasks);
|
|
// 提交或回滚事务
|
if (isStockUpdated && isTaskCreated && isOrderUpdated && isOrderStockCread)
|
{
|
_unitOfWorkManage.CommitTran();
|
}
|
else
|
{
|
_unitOfWorkManage.RollbackTran();
|
}
|
|
return content.OK(data: stocks);
|
}
|
catch (Exception ex)
|
{
|
_unitOfWorkManage.RollbackTran();
|
return content.Error(ex.Message);
|
}
|
}
|
|
/// <summary>
|
/// 堆垛机任务完成
|
/// </summary>
|
/// <param name="saveModel">任务数据合集</param>
|
/// <returns>返回结果集</returns>
|
public async Task<WebResponseContent> CompleteStackTaskAsync(SaveModel saveModel)
|
{
|
WebResponseContent content = new WebResponseContent();
|
try
|
{
|
// 提取并验证主数据
|
var barCode = saveModel.MainData.GetValueOrDefault("barCode")?.ToString();
|
var taskNum = saveModel.MainData.GetValueOrDefault("taskNum")?.ObjToInt() ?? 0;
|
var target = saveModel.MainData.GetValueOrDefault("target")?.ToString();
|
|
// 获取任务和库存信息
|
var task = await _taskService.GetByTaskNum(taskNum);
|
if (task == null)
|
{
|
return content.Error("任务不存在");
|
}
|
|
var stock = await GetStocks(palletCode: barCode);
|
if (stock == null)
|
{
|
return content.Error("库存不存在");
|
}
|
|
// 更新库存状态
|
stock.LocationCode = null;
|
stock.LocationInfo.Status = LocationStateConst.LocationState_Empty;
|
|
// 更新任务状态
|
task.TaskState = TaskStateConst.StackerCompleted.ToString();
|
task.CurrentAddress = task.NextAddress;
|
task.NextAddress = target;
|
task.TargetAddress = target;
|
|
// 事务处理
|
_unitOfWorkManage.BeginTran();
|
var isStockUpdated = BaseDal.UpdateNavStock(stock);
|
var isTaskUpdated = await _taskService.Update(task);
|
|
if (isStockUpdated && isTaskUpdated)
|
{
|
_unitOfWorkManage.CommitTran();
|
return content.OK("任务完成成功");
|
}
|
else
|
{
|
_unitOfWorkManage.RollbackTran();
|
return content.Error("任务或库存更新失败");
|
}
|
}
|
catch (Exception err)
|
{
|
Console.WriteLine(err.Message);
|
return content.Error(err.Message);
|
}
|
}
|
|
/// <summary>
|
/// 出库任务完成
|
/// </summary>
|
/// <param name="saveModel">任务数据合集</param>
|
/// <returns>返回结果集</returns>
|
public async Task<WebResponseContent> CompleteTaskAsync(SaveModel saveModel)
|
{
|
WebResponseContent content = new WebResponseContent();
|
|
try
|
{
|
// 提取任务数据
|
var barCode = saveModel.MainData.GetValueOrDefault("barCode")?.ToString();
|
var taskNum = saveModel.MainData.GetValueOrDefault("taskNum")?.ObjToInt() ?? 0;
|
|
// 验证任务是否存在
|
var task = await _taskService.GetByTaskNum(taskNum);
|
if (task == null)
|
{
|
return content.Error("任务不存在");
|
}
|
|
// 验证库存是否存在
|
var stock = await GetStocks(palletCode: barCode);
|
if (stock == null)
|
{
|
return content.Error("库存不存在");
|
}
|
|
// 更新出库订单和库存信息
|
var orderStock = await UpdateOrderAndStockAsync(stock, barCode);
|
|
// 检查订单是否完成并处理后续操作
|
if (IsOrderComplete(orderStock))
|
{
|
// 处理已完成订单
|
await ProcessCompletedOrderAsync(orderStock, task);
|
}
|
else
|
{
|
// 处理未完成订单
|
await ProcessUpdateOrderAsync(orderStock, task);
|
}
|
|
content.OK("任务完成");
|
}
|
catch (Exception err)
|
{
|
// 记录异常信息
|
Console.WriteLine(err.Message.ToString());
|
content.Error("任务完成失败");
|
}
|
|
return content;
|
}
|
|
#region 内部方法
|
|
/// <summary>
|
/// 根据订单号获取订单
|
/// </summary>
|
/// <param name="orderNumber">订单号</param>
|
/// <returns>订单对象</returns>
|
private Dt_OutOrder GetOrder(string orderNumber)
|
{
|
// 获取订单信息
|
var content = _outOrderService.GetOutOrderByNumber(orderNumber);
|
|
// 检查订单是否获取成功
|
if (!content.Status)
|
{
|
return null;
|
}
|
|
// 反序列化订单对象
|
return (Dt_OutOrder)content.Data;
|
}
|
|
/// <summary>
|
/// 创建任务列表
|
/// </summary>
|
/// <param name="order">订单对象</param>
|
/// <param name="filteredStocks">筛选后的库存列表</param>
|
/// <returns>任务列表</returns>
|
private (List<Dt_Task>, Dt_OutOrder orderDetail) CreateTasks(Dt_OutOrder order, List<Dt_BillGroupStock> filteredStocks)
|
{
|
var tasks = new List<Dt_Task>();
|
|
foreach (var stock in filteredStocks)
|
{
|
// 如果已分配数量达到出库数量,停止分配
|
if (order.OrderDetailList.AllocatedQuantity >= order.OrderDetailList.OutboundQuantity)
|
break;
|
|
// 如果托盘任务已存在,跳过
|
if (_taskService.IsExist(stock.PalletCode))
|
continue;
|
|
// 创建任务
|
tasks.Add(new Dt_Task
|
{
|
CreateDate = DateTime.Now, // 创建时间
|
Creater = "System", // 创建人
|
CurrentAddress = stock.LocationCode, //当前位置
|
Dispatchertime = DateTime.Now, //调度时间(任务下发时间)
|
Grade = 1, // 等级
|
InboundNo = stock.InboundNo, //单据编号
|
MaterialNo = stock.MaterialNo, // 物料号
|
NextAddress = stock.LocationCode, // 下一位置
|
PalletCode = stock.PalletCode, //托盘号
|
Remark = stock.Remark, //备注
|
Roadway = stock.Remark, //巷道
|
SourceAddress = stock.LocationCode, //来源位置
|
TargetAddress = order.OrderDetailList.Remarks, //目标地址
|
TaskNum = 1001, //任务号
|
TaskState = TaskStateConst.PendingDispatch.ToString(), //任务状态
|
TaskType = TaskTypeConst.WholeOutbound.ToString(), //任务类型
|
});
|
|
// 更新已分配数量
|
order.OrderDetailList.AllocatedQuantity++;
|
}
|
|
return (tasks, order);
|
}
|
|
/// <summary>
|
/// 更新库存状态
|
/// </summary>
|
/// <param name="filteredStocks">筛选后的库存列表</param>
|
/// <param name="order">订单对象</param>
|
/// <returns>更新后的库存列表</returns>
|
private List<Dt_BillGroupStock> UpdateStocks(List<Dt_BillGroupStock> filteredStocks, Dt_OutOrder order)
|
{
|
var updatedStocks = new List<Dt_BillGroupStock>();
|
var orderDetail = order.OrderDetailList;
|
int index = 0;
|
|
foreach (var stock in filteredStocks)
|
{
|
// 如果已分配数量达到出库数量,停止分配
|
if (index >= orderDetail.OutboundQuantity)
|
{
|
break;
|
}
|
|
// 更新库存状态
|
stock.LocationInfo.IsLocked = true;
|
stock.LocationInfo.Status = 0;
|
stock.State = "3";
|
updatedStocks.Add(stock);
|
}
|
|
return updatedStocks;
|
}
|
|
/// <summary>
|
/// 创建订单库存列表
|
/// </summary>
|
/// <param name="stock">筛选后的库存列表</param>
|
/// <param name="order">订单对象</param>
|
/// <param name="task">任务列表</param>
|
/// <returns>订单库存列表</returns>
|
private List<Dt_OutOrderAndStock> CreateOrderStock(List<Dt_BillGroupStock> stock, Dt_OutOrder order, List<Dt_Task> task)
|
{
|
var orderStocks = new List<Dt_OutOrderAndStock>();
|
for (int i = 0; i < task.Count; i++)
|
{
|
orderStocks.Add(new Dt_OutOrderAndStock()
|
{
|
AllocatedQuantity = order.OrderDetailList.AllocatedQuantity,
|
MaterialNo = stock[i].MaterialNo,
|
MaterialName = order.OrderDetailList.MaterialName,
|
OrderNumber = order.OrderNumber,
|
OutboundQuantity = order.OrderDetailList.OutboundQuantity,
|
PalletCode = stock[i].PalletCode,
|
PalletQuantity = stock[i].StockDetailList.PalletQuantity,
|
State = stock[i].State,
|
BatchNumber = order.OrderDetailList.BatchNumber,
|
CompletedQuantity = order.OrderDetailList.CompletedQuantity,
|
Creater = "System",
|
CreateDate = DateTime.Now,
|
GroupId = stock[i].GroupId,
|
GroupDetailId = stock[i].StockDetailList.GroupDetailId,
|
LocationCode = stock[i].LocationInfo.LocationID,
|
OutOrderDetailId = order.OrderDetailList.Id,
|
OutOrderId = order.Id,
|
});
|
}
|
return orderStocks;
|
}
|
|
/// <summary>
|
/// 更新出库订单和库存信息
|
/// </summary>
|
/// <param name="stock">库存实例</param>
|
/// <param name="barCode">条码</param>
|
/// <returns>更新后的订单和库存信息</returns>
|
private async Task<Dt_OutOrderAndStock> UpdateOrderAndStockAsync(Dt_BillGroupStock stock, string barCode)
|
{
|
var orderStock = await _OutOrderAndStockRepository.GetOrderAndStock(palletCode: barCode);
|
|
orderStock.CompletedQuantity += stock.StockDetailList.PalletQuantity.Value;
|
orderStock.OrderDetailList.CompletedQuantity += stock.StockDetailList.PalletQuantity.Value;
|
|
return orderStock;
|
}
|
|
/// <summary>
|
/// 判断订单是否完成
|
/// </summary>
|
/// <param name="orderStock">订单和库存信息</param>
|
/// <returns>是否完成</returns>
|
private bool IsOrderComplete(Dt_OutOrderAndStock orderStock)
|
{
|
return orderStock.CompletedQuantity == orderStock.OutboundQuantity;
|
}
|
|
/// <summary>
|
/// 处理已完成的订单
|
/// </summary>
|
/// <param name="orderStock">订单和库存信息</param>
|
/// <param name="task">任务数据</param>
|
/// <returns>异步任务</returns>
|
private async Task ProcessCompletedOrderAsync(Dt_OutOrderAndStock orderStock, Dt_Task task)
|
{
|
// 创建历史订单记录
|
var stockHty = CreateHistoricalOrder(orderStock);
|
|
// 创建获取历史任务
|
var taskHty = CreateHistoricalTask(task);
|
|
_unitOfWorkManage.BeginTran();
|
|
try
|
{
|
// 添加历史任务
|
var isTaskHtyAdd = _Task_HtyService.InsertTask(taskHty);
|
|
// 删除任务数据
|
var isTaskDelete = await _taskService.Delete(task.TaskId);
|
|
// 插入历史订单
|
var isStockInsert = _OutOrderAndStock_HtyService.InsertNav(stockHty);
|
|
// 删除原订单
|
var isOrderStockDelete = _OutOrderAndStockRepository.DeleteNavOrderStock(orderStock);
|
|
if (isStockInsert && isOrderStockDelete && isTaskHtyAdd && isTaskDelete)
|
{
|
_unitOfWorkManage.CommitTran();
|
}
|
else
|
{
|
_unitOfWorkManage.RollbackTran();
|
}
|
}
|
catch
|
{
|
_unitOfWorkManage.RollbackTran();
|
throw; // 重新抛出异常以供外部捕获
|
}
|
}
|
|
/// <summary>
|
/// 处理未完成订单
|
/// </summary>
|
/// <param name="orderStock">订单和库存信息</param>
|
/// <param name="task">任务数据</param>
|
/// <returns>异步任务</returns>
|
private async Task ProcessUpdateOrderAsync(Dt_OutOrderAndStock orderStock, Dt_Task task)
|
{
|
// 创建获取历史任务
|
var taskHty = CreateHistoricalTask(task);
|
|
_unitOfWorkManage.BeginTran();
|
try
|
{
|
// 添加历史任务
|
var isTaskHtyAdd = _Task_HtyService.InsertTask(taskHty);
|
|
// 删除任务数据
|
var isTaskDelete = await _taskService.Delete(task.TaskId);
|
|
// 更新订单与库存
|
var isOrderUpdated = _OutOrderAndStockRepository.UpdateNavOrderStock(orderStock);
|
if (isTaskDelete && isTaskHtyAdd && isOrderUpdated)
|
{
|
_unitOfWorkManage.CommitTran();
|
}
|
else
|
{
|
_unitOfWorkManage.RollbackTran();
|
}
|
}
|
catch (Exception err)
|
{
|
Console.WriteLine(err.Message.ToString());
|
_unitOfWorkManage.RollbackTran();
|
throw; // 重新抛出异常以供外部捕获
|
}
|
}
|
|
/// <summary>
|
/// 创建历史订单记录
|
/// </summary>
|
/// <param name="orderStock">订单和库存信息</param>
|
/// <returns>历史订单记录</returns>
|
private Dt_OutOrderAndStock_Hty CreateHistoricalOrder(Dt_OutOrderAndStock orderStock)
|
{
|
var stockHty = _mapper.Map<Dt_OutOrderAndStock_Hty>(orderStock);
|
|
stockHty.StockDetailList.FinishTime = DateTime.Now;
|
stockHty.StockDetailList.OperateType = "Finish";
|
stockHty.StockDetailList.SourceId = orderStock.StockDetailList.GroupDetailId;
|
stockHty.StockDetailList.GroupDetailId = 0;
|
|
stockHty.StockList.FinishTime = DateTime.Now;
|
stockHty.StockList.OperateType = "Finish";
|
stockHty.StockList.SourceId = orderStock.StockList.GroupId;
|
stockHty.StockList.GroupId = 0;
|
|
stockHty.OrderDetailList.FinishTime = DateTime.Now;
|
stockHty.OrderDetailList.OperateType = "Finish";
|
stockHty.OrderDetailList.SourceId = orderStock.OrderDetailList.Id;
|
stockHty.OrderDetailList.Id = 0;
|
|
stockHty.OrderList.FinishTime = DateTime.Now;
|
stockHty.OrderList.OperateType = "Finish";
|
stockHty.OrderList.SourceId = orderStock.OrderList.Id;
|
stockHty.OrderList.Id = 0;
|
|
return stockHty;
|
}
|
|
private Dt_Task_Hty CreateHistoricalTask(Dt_Task task)
|
{
|
// 更新任务状态
|
task.TaskState = TaskStateConst.TaskCompleted.ToString();
|
task.CurrentAddress = task.NextAddress;
|
|
// 创建历史任务
|
var taskHty = _mapper.Map<Dt_Task_Hty>(task);
|
taskHty.FinishTime = DateTime.Now;
|
taskHty.OperateType = "Finish";
|
taskHty.SourceId = task.TaskId;
|
taskHty.TaskState = TaskStateConst.TaskCompleted.ToString();
|
return taskHty;
|
}
|
|
#endregion 内部方法
|
}
|
}
|