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 Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Kean.Domain.Stock.CommandHandlers { /// /// 入库命令处理程序 /// public sealed class ScanInboundCommandHandler : 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; // 任务域 private readonly MaterialProxy _materialProxy; // 物料服务 /// /// 依赖注入 /// public ScanInboundCommandHandler( ICommandBus commandBus, INotification notifications, IMapper mapper, IStockRepository stockRepository, IWarehouseRepository warehouseRepository, BarcodeValidator barcodeValidator, MaterialProxy materialProxy, TaskProxy taskProxy) { _commandBus = commandBus; _notifications = notifications; _mapper = mapper; _stockRepository = stockRepository; _warehouseRepository = warehouseRepository; _barcodeValidator = barcodeValidator; _taskProxy = taskProxy; _materialProxy = materialProxy; } /// /// 处理程序 /// public override async Task Handle(ScanInboundCommand command, CancellationToken cancellationToken) { if (command.ValidationResult.IsValid) { // 条码格式校验 if (!await _barcodeValidator.Validate(command.Barcode)) { await _commandBus.Notify(nameof(command.Barcode), "条码格式不正确", command.Barcode, cancellationToken: cancellationToken); return; } //校验 托盘规则与物料类型是否匹配 var sCategory = await _materialProxy.GetMaterialClass(command.Lines.First().Material); Models.Category category = JsonConvert.DeserializeObject(sCategory); if (!(category.Code.Contains(command.Barcode.Substring(2,1)))) { await _commandBus.Notify(nameof(command.Barcode), $"托盘({command.Barcode})不能装载 物料类别({category.Code})的物料", command.Barcode, cancellationToken: cancellationToken); return; } // 托盘有任务 if (await _taskProxy.HasTask(command.Barcode)) { await _commandBus.Notify(nameof(command.Barcode), $"托盘({command.Barcode})已有任务", command.Barcode, cancellationToken: cancellationToken); return; } var original = command.Barcode == string.Empty ? null : await _stockRepository.GetCell(command.Barcode); // 托盘已存在 if (original.HasValue) { await _commandBus.Notify(nameof(command.Barcode), $"{command.Barcode}已有库存", command.Barcode, cancellationToken: cancellationToken); return; } // 托盘不存在 else { //车身 车架 if (command.Barcode.Substring(0,3) == "LCF" || command.Barcode.Substring(0, 3) == "LCG") { original = 12001; } else { original = 12007; } //// 要求指定位置 //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; //} } //校验膜卷号唯一 foreach (var r in command.Lines) { if (await this._stockRepository.GetStorageBill(r.Bill) != null) { await _commandBus.Notify(nameof(r.Bill), $"膜卷码({r.Bill})已经存在,不能再入库", command.Barcode, cancellationToken: cancellationToken); return; } } if (!string.IsNullOrEmpty(command.Tag)) { JObject jObj = JObject.Parse(command.Tag); jObj.Add("requestNo", command.RequestNo); command.Tag = JsonConvert.SerializeObject(jObj); } else { //command.Tag = JsonConvert.SerializeObject(new //{ // requestNo = command.RequestNo //}); } // 时间戳 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); } // //获取最佳入库口 // string startStation = await this._warehouseRepository.GetInStartDevice((int)command.Destination, null, command.Barcode.Substring(0, 5), command.Lines.First().Material, command.Barcode); // if (string.IsNullOrEmpty(startStation)) // { // await _commandBus.Notify(nameof(command.Tag), $"设备故障,请先排除故障", startStation, //cancellationToken: cancellationToken); // return; // } // Output(nameof(command.Tag), startStation); } else { await _commandBus.Notify(command.ValidationResult, cancellationToken: cancellationToken); } } } }