using AutoMapper; using Kean.Domain.Stock.Repositories; 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 Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Linq; using System.Threading; namespace Kean.Domain.Task.CommandHandlers { /// /// 创建输送命令处理程序 /// public sealed class BypassEmptyCommandHandler : CommandHandler { private readonly ICommandBus _commandBus; // 命令总线 private readonly INotification _notifications; // 总线通知 private readonly IMapper _mapper; // 模型映射 private readonly ITaskRepository _taskRepository; // 任务仓库 private readonly Kean.Domain.Task.Repositories.IWarehouseRepository _warehouseRepository; // 库房仓库 private readonly BarcodeInterpreter _barcodeInterpreter; // 条码解释器 private readonly BarcodeValidator _barcodeValidator; // 条码验证器 private readonly StockProxy _stockProxy; // 仓储域代理 private readonly MaterialProxy _materialProxy; /// /// 依赖注入 /// public BypassEmptyCommandHandler( ICommandBus commandBus, INotification notifications, IMapper mapper, ITaskRepository taskRepository, Kean.Domain.Task.Repositories.IWarehouseRepository warehouseRepository, BarcodeInterpreter barcodeInterpreter, BarcodeValidator barcodeValidator, StockProxy stockProxy, MaterialProxy materialProxy) { _commandBus = commandBus; _notifications = notifications; _mapper = mapper; _taskRepository = taskRepository; _warehouseRepository = warehouseRepository; _barcodeInterpreter = barcodeInterpreter; _barcodeValidator = barcodeValidator; _stockProxy = stockProxy; _materialProxy = materialProxy; } /// /// 处理程序 /// public override async System.Threading.Tasks.Task Handle(BypassEmptyCommand 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 _taskRepository.HasTask(command.Barcode)) { await _commandBus.Notify(nameof(command.Barcode), "托盘正在执行任务", command.Barcode, cancellationToken: cancellationToken); return; } var pallet = await _barcodeInterpreter.Interpret(command.Barcode); // 不允许操作立库中的库存 var cell = await _stockProxy.GetCell(command.Barcode); if (cell.HasValue && await _warehouseRepository.IsCell(cell.Value) == true) { await _commandBus.Notify(nameof(command.Barcode), "不允许操作立库中的库存", command.Barcode, cancellationToken: cancellationToken); return; } // 获取操作位置 var original = command.Original switch { int i => await _warehouseRepository.GetStationById(i), long i => await _warehouseRepository.GetStationById((int)i), 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), Station s => s, _ => null }; // 操作位置可用性 if (original.AllowIn != true || original.Pallet?.Contains(pallet) == false || original.Spec?.Adaptive(command.Spec) == false) { await _commandBus.Notify(nameof(command.Original), "操作位置不正确", command.Original, cancellationToken: cancellationToken); return; } //校验 托盘规则与申请位置是否匹配 if ((original.Device.StartsWith("1") || original.Device.StartsWith("2")) && original.Device != "12226" && original.Device != "22226") { Models.Warehouse warehouse = await _warehouseRepository.GetWarehouse(original.Warehouse); if (warehouse.Code != command.Barcode.Substring(0, 3)) { await _commandBus.Notify(nameof(command.Barcode), $"托盘({command.Barcode})不能进入({warehouse.Name})库房", command.Barcode, cancellationToken: cancellationToken); return; } } if (!(await _stockProxy.GetCell(command.Barcode)).HasValue) { int? endDevice = original?.Id; var sGoods = await _materialProxy.GetMaterial(null, (string)pallet, true); Models.Material goods = JsonConvert.DeserializeObject(sGoods); if (goods == null) { await _commandBus.Notify(nameof(command.Original), "空托盘条码解析类型失败", command.Original, cancellationToken: cancellationToken); return; } int? goodsid = goods.Id; //@=@ W1固定值 int tempBypassArea = 110000; if (command.Barcode.Substring(0, 5) == "W1JPB" || command.Barcode.Substring(0, 3) == "M2C") { tempBypassArea = 110000; } else { tempBypassArea = 210000; } command.Tag = JsonConvert.SerializeObject(new { isAgv = "1", BypassArea = tempBypassArea, postUser = "系统", slTarget="" }); command.Operator = -1; await _stockProxy.PalletIn( command.Barcode, endDevice.Value, goodsid.Value, command.Operator, command.Tag ); } else { int? material = await _stockProxy.GetStorageMaterial(command.Barcode); bool bPallet = await _taskRepository.IsPallet(material.Value); if (bPallet) { } else { await _commandBus.Notify(nameof(command.Barcode), $"托盘({command.Barcode})已经有库存,无法空托盘入库", command.Barcode, cancellationToken: cancellationToken); return; } } //获取库存信息 string bypassTag = await _taskRepository.GetBypassTag(command.Barcode); string isAgv = string.Empty; string slTarget = string.Empty; int bypassArea = 0; string postUser = string.Empty; string Transaction = "Bypass"; int Operator = command.Operator; if (!string.IsNullOrEmpty(bypassTag)) { command.Tag = bypassTag; JObject jObj = JObject.Parse(bypassTag); JToken isAgvFlg = jObj.SelectToken("isAgv"); if (isAgvFlg != null) { isAgv = jObj["isAgv"].ToString(); } JToken slTargetFlg = jObj.SelectToken("slTarget"); if (slTargetFlg != null) { slTarget = jObj["slTarget"].ToString(); } JToken bypassAreaFlg = jObj.SelectToken("BypassArea"); if (bypassAreaFlg != null) { bypassArea = Convert.ToInt32(jObj["BypassArea"]); } JToken postUserFlg = jObj.SelectToken("postUser"); if (postUserFlg != null) { postUser = jObj["postUser"].ToString(); } } if (bypassArea == 0) { //@=@ W1固定值 bypassArea = 110000; if (command.Barcode.Substring(0, 5) == "W1JPB" || command.Barcode.Substring(0, 3) == "M2C") { bypassArea = 110000; } else { bypassArea = 210000; } command.Operator = -1; } // 获取目标位置 var destinationCache = await _warehouseRepository.GetCacheByArea(bypassArea); if (destinationCache == null) { await _commandBus.Notify("Destination", $"输送终点区域未知({bypassArea})", bypassArea, cancellationToken: cancellationToken); return; } var destination = destinationCache; //转换为实际出库站台 if (destinationCache.Group == "Trans") { destination = await _warehouseRepository.GetBypassStationByCell(original.Id, destinationCache.Area, command.Barcode.Substring(0,5)); if (destination == null) { await _commandBus.Notify(nameof(command.Destination), "未找到输送站台", command.Destination, cancellationToken: cancellationToken); return; } } command.Original = original.Id; command.Destination = destination.Id; // 时间戳 command.Timestamp ??= DateTime.Now; // 切点事件 var event0 = _mapper.Map(command); event0.Original = original; event0.Destination = destination; await _commandBus.Trigger(event0, cancellationToken); if (!_notifications.Any()) { // 创建任务 var task = _mapper.Map(command); task.Type = TaskType.Bypass; Output(nameof(command.Id), await _taskRepository.CreateTask(task)); // 成功事件 var event1 = _mapper.Map(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); } } } else { await _commandBus.Notify(command.ValidationResult, cancellationToken: cancellationToken); } } } }