using System.Security.Cryptography.X509Certificates; using JNPF.Common.Core.Manager; using JNPF.Common.Dtos.VisualDev; using JNPF.Common.Enums; using JNPF.Common.Extension; using JNPF.Common.Security; using JNPF.FriendlyException; using JNPF.Systems.Interfaces.System; using JNPF.VisualDev; using JNPF.VisualDev.Entitys; using JNPF.VisualDev.Interfaces; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using NPOI.POIFS.Storage; using SqlSugar; using Tnb.BasicData.Entities; using Tnb.ProductionMgr.Entities; using Tnb.WarehouseMgr.Entities; using Tnb.WarehouseMgr.Entities.Attributes; using Tnb.WarehouseMgr.Entities.Consts; using Tnb.WarehouseMgr.Entities.Dto; using Tnb.WarehouseMgr.Entities.Dto.Inputs; using Tnb.WarehouseMgr.Entities.Dto.Outputs; using Tnb.WarehouseMgr.Entities.Entity; using Tnb.WarehouseMgr.Entities.Enums; using Tnb.WarehouseMgr.Interfaces; namespace Tnb.WarehouseMgr { [OverideVisualDev(ModuleConsts.MODULE_WMSPACKOUTSTOCK_ID)] [ServiceModule(BizTypeId)] public class WmsPackOutstockService : BaseWareHouseService, IWmsPrdReturnService { private const string BizTypeId = WmsWareHouseConst.BIZTYPE_WMSPACKOUTSTOCK_ID; private readonly ISqlSugarClient _db; private readonly IRunService _runService; private readonly IVisualDevService _visualDevService; private readonly IUserManager _userManager; private readonly IWareHouseService _wareHouseService; private readonly IWmsCarryBindService _wmsCarryBindService; private readonly IBillRullService _billRullService; public static SemaphoreSlim s_packOutstockSemaphore = new(1); private readonly IWmsCarryUnbindService _wmsCarryUnbindService; public WmsPackOutstockService( ISqlSugarRepository repository, IRunService runService, IVisualDevService visualDevService, IWareHouseService wareHouseService, IUserManager userManager, IWmsCarryBindService wmsCarryBindService, IWmsCarryUnbindService wmsCarryUnbindService, IBillRullService billRullService) { _db = repository.AsSugarClient(); _runService = runService; _visualDevService = visualDevService; _userManager = userManager; _wareHouseService = wareHouseService; _wmsCarryBindService = wmsCarryBindService; _wmsCarryUnbindService = wmsCarryUnbindService; _billRullService = billRullService; } public override async Task ModifyAsync(WareHouseUpInput input) { if (input == null) { throw new ArgumentNullException(nameof(input)); } try { // TODO 二楼工位放货完成后更新出库明细的实际出库数量 //if (input.wmsDistaskH.start_floor == 2 && input.wmsDistaskH.end_floor == 2) { WmsCarryCode wmsCarryCode = await _db.Queryable().Where(r => r.carry_id == input.wmsDistaskH.carry_id).FirstAsync(); await _db.Updateable().SetColumns(r => r.prqty == r.prqty + wmsCarryCode.codeqty).Where(r => r.id == input.wmsDistaskH.require_id).ExecuteCommandAsync(); CarryCodeUnbindInput carryCodeUnbindInput = new CarryCodeUnbindInput(); carryCodeUnbindInput.carry_id = input.wmsDistaskH.carry_id; await _wmsCarryUnbindService.CarryCodeUnbind(carryCodeUnbindInput, _db); } await _db.Ado.CommitTranAsync(); } catch (Exception ex) { Logger.LogError("【WmsPackOutStockService ModifyAsync】" + ex.Message); Logger.LogError("【WmsPackOutStockService ModifyAsync】" + ex.StackTrace); await _db.Ado.RollbackTranAsync(); } } /// /// 获取物料库存 /// /// /// /// [HttpPost, NonUnify, AllowAnonymous] public async Task MaterialInventory(MaterialTransferGetMaterialInventoryInput input) { try { if (input.palletCount <= 0) { throw new AppFriendlyException("托盘数必须大于0", 500); } if (string.IsNullOrEmpty(input.material_id)) { throw new AppFriendlyException("物料id不可为空", 500); } if (string.IsNullOrEmpty(input.code_batch)) { throw new AppFriendlyException("批号不可为空", 500); } //入库取终点 //出库起点 OutStockStrategyQuery inStockStrategyInput = new() { warehouse_id = WmsWareHouseConst.WAREHOUSE_BCK_ID, material_id = input.material_id, code_batch = input.code_batch, Size = input.palletCount }; List items = await _wareHouseService.OutStockStrategyYCL(inStockStrategyInput); decimal qty = _db.Queryable().Where(r => items.Select(a => a.id).Contains(r.carry_id) && r.material_id == input.material_id && r.code_batch == input.code_batch).Sum(r => r.codeqty); JObject keyValuePairs = new JObject(); keyValuePairs["realPalletCount"] = items.Count; keyValuePairs["realInvQty"] = qty; return await ToApiResult(HttpStatusCode.OK, "成功", keyValuePairs); } catch (Exception ex) { await _db.Ado.RollbackTranAsync(); return await ToApiResult(HttpStatusCode.InternalServerError, ex.Message); } } /// /// 按托下发 /// /// /// /// [HttpPost, NonUnify, AllowAnonymous] public async Task Distribute(MaterialTransferDistributeInput input) { Logger.LogInformation($"【Distribute】 包材出库下发"); try { if (string.IsNullOrEmpty(input.source_id)) { throw new AppFriendlyException("来源单据id不可为空", 500); } if (input.palletCount <= 0) { throw new AppFriendlyException("托盘数必须大于0", 500); } if (input.qty <= 0) { throw new AppFriendlyException("数量必须大于0", 500); } if (string.IsNullOrEmpty(input.code_batch)) { throw new AppFriendlyException("批号不可为空", 500); } WmsPackOutstockD wmsPackOutstockD = await _db.Queryable().FirstAsync(it => it.id == input.source_id); WmsPackOutstockH wmsPackOutstockH = await _db.Queryable().FirstAsync(it => it.id == wmsPackOutstockD.bill_id); if (wmsPackOutstockD.prqty == wmsPackOutstockD.qty) { throw new AppFriendlyException("已下发数量已达到出库数量", 500); } await s_packOutstockSemaphore.WaitAsync(); await _db.Ado.BeginTranAsync(); //入库取终点 //出库起点 OutStockStrategyQuery outStockStrategyInput = new() { warehouse_id = WmsWareHouseConst.WAREHOUSE_BCK_ID, material_id = wmsPackOutstockD.material_id, code_batch = input.code_batch, Size = input.palletCount }; List items = await _wareHouseService.OutStockStrategyYCL(outStockStrategyInput); if (items.Count == 0) { throw new AppFriendlyException($@"没有可以出库的载具", 500); } decimal qty = _db.Queryable().Where(r => items.Select(a => a.id).Contains(r.carry_id) && r.material_id == wmsPackOutstockD.material_id && r.code_batch == input.code_batch).Sum(r => r.codeqty); // 暂定PDA上查询到的物料批次和库存数量与提交时获取的不一致时,需要前台重新获取库存接口 if (input.palletCount != items.Count || input.qty != qty) { throw new AppFriendlyException($@"当前实际托盘数量为{input.palletCount} 实际库存数量为{qty},与前台数据不一致,请重新获取库存", HttpStatusCode.InternalServerError); } InStockStrategyQuery inStockStrategyInput = new() { warehouse_id = WmsWareHouseConst.WAREHOUSE_F2BCQ_ID, Size = input.palletCount }; List endLocations = await _wareHouseService.InStockStrategy(inStockStrategyInput); if (endLocations.Count == 0) { throw new AppFriendlyException("没有可用的入库库位", 500); } if (endLocations.Count() < input.palletCount) { throw new AppFriendlyException($@"可用的终点库位数量为{endLocations.Count()}个 下发数量为{input.palletCount}个 请检查终点库位的锁定和占用状态", 500); } foreach (var wmsCarryH in items) { WmsCarryCode wmsCarryCode = await _db.Queryable().Where(r => r.carry_id == wmsCarryH.id).FirstAsync(); BasLocation startLocation = await _db.Queryable().Where(r => r.id == wmsCarryH.location_id).FirstAsync(); InStockStrategyQuery _inStockStrategyInput = new() { warehouse_id = WmsWareHouseConst.WAREHOUSE_F2BCQ_ID, Size = 1 }; List _endLocations = await _wareHouseService.InStockStrategy(_inStockStrategyInput); BasLocation endLocation = _endLocations.First(); if (endLocation == null) { throw new AppFriendlyException($@"没有可用的终点库位!请检查终点库位的锁定和占用状态", 500); } CommonCreatePretaskInput commonCreatePretaskInput = new CommonCreatePretaskInput(); commonCreatePretaskInput.startlocation_id = startLocation.id; commonCreatePretaskInput.endlocation_id = endLocation.id; commonCreatePretaskInput.task_type = WmsWareHouseConst.WMS_PRETASK_OUTSTOCK_TYPE_ID; commonCreatePretaskInput.biz_type = WmsWareHouseConst.BIZTYPE_WMSPACKOUTSTOCK_ID; commonCreatePretaskInput.require_id = input.source_id; commonCreatePretaskInput.carry_id = wmsCarryH.id; commonCreatePretaskInput.carry_code = wmsCarryH.carry_code; commonCreatePretaskInput.isExcuteMission = false; Entities.Dto.Outputs.Result res = await _wareHouseService.CommonCreatePretask(commonCreatePretaskInput, _db); if (res.code != HttpStatusCode.OK) { Logger.LogInformation($@"生成预任务失败"); throw new AppFriendlyException($@"生成预任务失败", 500); } } // 更新子表已下发数量 await _db.Updateable().SetColumns(r => r.sendqty == r.sendqty + input.qty).Where(r => r.id == input.source_id).ExecuteCommandAsync(); await _db.Ado.CommitTranAsync(); Logger.LogInformation($"【Distribute】 包材出库下发完成"); } catch (Exception ex) { await _db.Ado.RollbackTranAsync(); Logger.LogError("【Distribute】 包材出库" + ex.Message); Logger.LogError("【Distribute】 包材出库" + ex.StackTrace); return await ToApiResult(HttpStatusCode.InternalServerError, ex.Message); } finally { _ = s_packOutstockSemaphore.Release(); InvokeGenPretaskExcute(); } return await ToApiResult(HttpStatusCode.OK, "成功"); } } }