You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
10 KiB
231 lines
10 KiB
3 months ago
|
using AutoMapper;
|
||
|
using Kean.Domain.Task.Commands;
|
||
|
using Kean.Domain.Task.Enums;
|
||
|
using Kean.Domain.Task.Events;
|
||
|
using Kean.Domain.Task.Models;
|
||
|
using Kean.Domain.Task.Repositories;
|
||
|
using Kean.Domain.Task.SharedServices.Proxies;
|
||
|
using Kean.Infrastructure.Configuration;
|
||
|
using Kean.Infrastructure.Soap.Hithium.Models;
|
||
|
using Newtonsoft.Json.Linq;
|
||
|
using System;
|
||
|
using System.Linq;
|
||
|
using System.Threading;
|
||
|
|
||
|
namespace Kean.Domain.Task.CommandHandlers
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// 创建下架命令处理程序
|
||
|
/// </summary>
|
||
|
public sealed class ApplyOutCommandHandler : CommandHandler<ApplyOutCommand>
|
||
|
{
|
||
|
private readonly ICommandBus _commandBus; // 命令总线
|
||
|
private readonly INotification _notifications; // 总线通知
|
||
|
private readonly IMapper _mapper; // 模型映射
|
||
|
private readonly ITaskRepository _taskRepository; // 任务仓库
|
||
|
private readonly IWarehouseRepository _warehouseRepository; // 库房仓库
|
||
|
private readonly BarcodeInterpreter _barcodeInterpreter; // 条码解释器
|
||
|
private readonly BarcodeValidator _barcodeValidator; // 条码验证器
|
||
|
private readonly StockProxy _stockProxy; // 仓储域代理
|
||
|
//private static object _lock = new object();
|
||
|
|
||
|
//private readonly IStockRepository _stockRepository;
|
||
|
|
||
|
/// <summary>
|
||
|
/// 依赖注入
|
||
|
/// </summary>
|
||
|
public ApplyOutCommandHandler(
|
||
|
ICommandBus commandBus,
|
||
|
INotification notifications,
|
||
|
IMapper mapper,
|
||
|
ITaskRepository taskRepository,
|
||
|
IWarehouseRepository warehouseRepository,
|
||
|
//IStockRepository stockRepository,
|
||
|
BarcodeInterpreter barcodeInterpreter,
|
||
|
BarcodeValidator barcodeValidator,
|
||
|
StockProxy stockProxy)
|
||
|
{
|
||
|
_commandBus = commandBus;
|
||
|
_notifications = notifications;
|
||
|
_mapper = mapper;
|
||
|
_taskRepository = taskRepository;
|
||
|
_warehouseRepository = warehouseRepository;
|
||
|
_barcodeInterpreter = barcodeInterpreter;
|
||
|
_barcodeValidator = barcodeValidator;
|
||
|
_stockProxy = stockProxy;
|
||
|
|
||
|
//_stockRepository = stockRepository;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// 处理程序
|
||
|
/// </summary>
|
||
|
public override async System.Threading.Tasks.Task Handle(ApplyOutCommand command, CancellationToken cancellationToken)
|
||
|
{
|
||
|
if (command.ValidationResult.IsValid)
|
||
|
{
|
||
|
//lock (_lock)
|
||
|
//{
|
||
|
//}
|
||
|
// 获取目标位置
|
||
|
var destinationCache = command.Destination switch
|
||
|
{
|
||
|
int i => await _warehouseRepository.GetStationByDevice(i.ToString(),2),
|
||
|
long i => await _warehouseRepository.GetStationByDevice(i.ToString(),2),
|
||
|
string s when s.StartsWith("name:") => await _warehouseRepository.GetStationByName(s[5..], command.Warehouse),
|
||
|
string s when s.StartsWith("device:") => await _warehouseRepository.GetStationByDevice(s[7..], command.Warehouse),
|
||
|
string s => await _warehouseRepository.GetCacheByArea(Convert.ToInt32(s)),
|
||
|
Station s => s,
|
||
|
_ => null
|
||
|
};
|
||
|
|
||
|
int index = 0;
|
||
|
int volQty = 0;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
foreach (var i in command.Materials)
|
||
|
{
|
||
|
if (command.Qty > 0 && volQty >= command.Qty)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
index++;
|
||
|
// 获取拣选库存位置
|
||
|
var cell = await _stockProxy.ChooseStorageCell(
|
||
|
destinationCache.Id > 100000? destinationCache.Id: destinationCache.Area,
|
||
|
i,
|
||
|
command.enable,
|
||
|
command.IsLocal,
|
||
|
command.Batch == null ? "" : command.Batch.materialType,
|
||
|
command.Batch == null ? "" : command.Batch.workOrderNo,
|
||
|
command.Batch == null ? "" : command.Batch.qualityState,
|
||
|
command.Batch == null ? "" : command.Batch.productDate);
|
||
|
if (cell == null)
|
||
|
{
|
||
|
if (command.Qty > 0)
|
||
|
{
|
||
|
await _commandBus.Notify(null, $"可用极片数量({volQty}),不满足需求数量({command.Qty})", cancellationToken: cancellationToken);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
await _commandBus.Notify(null, $"可用库存托盘数量({index - 1}),不满足需求数量({command.Materials.Count()})", cancellationToken: cancellationToken);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (command.Qty > 0)
|
||
|
{
|
||
|
volQty += await _stockProxy.GetStorageLinesNum(cell);
|
||
|
}
|
||
|
|
||
|
var original = await _warehouseRepository.GetCellById(cell.Value);
|
||
|
command.Barcode = await _stockProxy.GetBarcode(cell.Value);
|
||
|
|
||
|
var destination = destinationCache;
|
||
|
//转换为实际出库站台
|
||
|
//if (destination.Area == 2 || destination.Area == 7)
|
||
|
if (destinationCache.Group == "Trans")
|
||
|
{
|
||
|
destination = await _warehouseRepository.GetOutStationByCell(original.Id, destinationCache.Area);
|
||
|
if (destination == null)
|
||
|
{
|
||
|
var destinationIgnorePath = await _warehouseRepository.GetOutStationByCellIgnorePath(original.Id, destinationCache.Area);
|
||
|
if (destinationIgnorePath == null)
|
||
|
{
|
||
|
await _commandBus.Notify(nameof(command.Destination), "未找到出库站台", command.Destination, cancellationToken: cancellationToken);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
await _commandBus.Notify(nameof(command.Destination), "设备故障导致无法出库", command.Destination, cancellationToken: cancellationToken);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// 时间戳
|
||
|
command.Timestamp ??= DateTime.Now;
|
||
|
// 切点事件
|
||
|
var event0 = _mapper.Map<ApplyOutExecutingEvent>(command);
|
||
|
event0.Original = original;
|
||
|
event0.Destination = destination;
|
||
|
await _commandBus.Trigger(event0, cancellationToken);
|
||
|
if (!_notifications.Any())
|
||
|
{
|
||
|
// 锁定库存位置
|
||
|
await _warehouseRepository.LockCell(original.Id);
|
||
|
// 非手动模式下的双深干涉处理
|
||
|
if (!command.Manual)
|
||
|
{
|
||
|
var avert = new AvertCommand
|
||
|
{
|
||
|
Cell = original,
|
||
|
Behavior = AvertCommand.Leaving,
|
||
|
Priority = command.Priority,
|
||
|
Previous = command.Previous,
|
||
|
Timestamp = command.Timestamp
|
||
|
};
|
||
|
await _commandBus.Execute(avert, cancellationToken);
|
||
|
if (_notifications.Any())
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if (avert.Id.HasValue)
|
||
|
{
|
||
|
command.Previous = avert.Id;
|
||
|
}
|
||
|
}
|
||
|
// 创建任务
|
||
|
var task = _mapper.Map<Models.Task>(command);
|
||
|
switch (command.Transaction)
|
||
|
{
|
||
|
case "ApplyOut":
|
||
|
task.Type = TaskType.ApplyOut;
|
||
|
break;
|
||
|
case "PalletOut":
|
||
|
task.Type = TaskType.PalletOut;
|
||
|
break;
|
||
|
}
|
||
|
if (destination.Id == 22009)
|
||
|
{
|
||
|
task.Type = TaskType.Outfeed;
|
||
|
}
|
||
|
|
||
|
task.Original = original.Id;
|
||
|
task.Destination = destination.Id;
|
||
|
|
||
|
Output(nameof(command.Barcode), command.Barcode);
|
||
|
Output(nameof(command.Id), await _taskRepository.CreateTask(task));
|
||
|
|
||
|
|
||
|
// 成功事件
|
||
|
var event1 = _mapper.Map<ApplyOutSuccessEvent>(command);
|
||
|
event1.Original = original;
|
||
|
event1.Destination = destination;
|
||
|
await _commandBus.Trigger(event1, cancellationToken);
|
||
|
// 手动
|
||
|
if (command.Manual && !_notifications.Any())
|
||
|
{
|
||
|
await _commandBus.Execute(new CompleteCommand { Id = command.Id }, cancellationToken);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch {
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
await _commandBus.Notify(command.ValidationResult,
|
||
|
cancellationToken: cancellationToken);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|