using AutoMapper; using Kean.Domain.Stock.Commands; using Kean.Domain.Stock.Events; using Kean.Domain.Stock.Repositories; using Kean.Domain.Stock.SharedServices.Proxies; using Kean.Infrastructure.Configuration; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Kean.Domain.Stock.CommandHandlers { /// /// 入库命令处理程序 /// public sealed class InboundCommandHandler : CommandHandler { private readonly ICommandBus _commandBus; // 命令总线 private readonly INotification _notifications; // 总线通知 private readonly IMapper _mapper; // 模型映射 private readonly IStockRepository _stockRepository; // 存储仓库 private readonly IWarehouseRepository _warehouseRepository; // 库房仓库 private readonly BarcodeValidator _barcodeValidator; // 条码验证器 private readonly TaskProxy _taskProxy; // 任务域 /// /// 依赖注入 /// public InboundCommandHandler( ICommandBus commandBus, INotification notifications, IMapper mapper, IStockRepository stockRepository, IWarehouseRepository warehouseRepository, BarcodeValidator barcodeValidator, TaskProxy taskProxy) { _commandBus = commandBus; _notifications = notifications; _mapper = mapper; _stockRepository = stockRepository; _warehouseRepository = warehouseRepository; _barcodeValidator = barcodeValidator; _taskProxy = taskProxy; } /// /// 处理程序 /// public override async Task Handle(InboundCommand command, CancellationToken cancellationToken) { if (command.ValidationResult.IsValid) { // 条码格式校验 if (!await _barcodeValidator.Validate(command.Barcode)) { await _commandBus.Notify(nameof(command.Barcode), "条码格式不正确", command.Barcode, cancellationToken: cancellationToken); return; } // 托盘有任务 if (await _taskProxy.HasTask(command.Barcode)) { await _commandBus.Notify(nameof(command.Barcode), "托盘有任务", command.Barcode, cancellationToken: cancellationToken); return; } var original = command.Barcode == string.Empty ? null : await _stockRepository.GetCell(command.Barcode); // 托盘已存在 if (original.HasValue) { // 如果命令中带有位置,比对该托盘的实际位置 if (command.Destination.HasValue && command.Destination.Value != original.Value) { await _commandBus.Notify(nameof(command.Destination), "位置不正确", command.Destination, cancellationToken: cancellationToken); return; } // 不能在立库货位中操作 if (await _warehouseRepository.IsCell(original.Value) != false) { await _commandBus.Notify(nameof(command.Destination), "位置不可用", command.Destination, cancellationToken: cancellationToken); return; } } // 托盘不存在 else { // 要求指定位置 if (!command.Destination.HasValue) { await _commandBus.Notify(nameof(command.Destination), "位置未指定", command.Destination, cancellationToken: cancellationToken); return; } // 如果命令中带有位置,要求该位置不是立库货位 if (await _warehouseRepository.IsCell(command.Destination.Value) != false) { await _commandBus.Notify(nameof(command.Destination), "位置不可用", command.Destination, cancellationToken: cancellationToken); return; } } // 时间戳 command.Timestamp ??= DateTime.Now; // 切点事件 var event0 = _mapper.Map(command); event0.Cell = command.Destination ?? original.Value; await _commandBus.Trigger(event0, cancellationToken); if (!_notifications.Any()) { // 允许创建库存 var stock = _mapper.Map(command); stock.Cell = command.Destination ?? original.Value; stock.Timestamp = command.Timestamp.Value; if (await _stockRepository.CreateStock(stock).ContinueWith(task => { if (task.Exception?.InnerException is RepositoryException ex) { task.Exception.Handle(_ => true); _commandBus.Notify(ex.Member.Key, ex.Message, ex.Member.Value, cancellationToken: cancellationToken).Wait(); return true; } return false; })) { return; } // 成功事件 var event1 = _mapper.Map(command); event1.Cell = stock.Cell; event1.Timestamp = command.Timestamp.Value; await _commandBus.Trigger(event1, cancellationToken); } } else { await _commandBus.Notify(command.ValidationResult, cancellationToken: cancellationToken); } } } }