using JNPF; using JNPF.Common.Core.Manager; using JNPF.Common.Dtos.VisualDev; using JNPF.Common.Extension; using JNPF.Common.Manager; using JNPF.Common.Security; using JNPF.EventBus; using JNPF.FriendlyException; using JNPF.Systems.Interfaces.System; using JNPF.VisualDev; using JNPF.VisualDev.Entitys; using JNPF.VisualDev.Interfaces; using Mapster; using Microsoft.AspNetCore.Mvc; using SqlSugar; using Tnb.BasicData.Entities; using Tnb.Common.Utils; using Tnb.WarehouseMgr.Entities; using Tnb.WarehouseMgr.Entities.Attributes; using Tnb.WarehouseMgr.Entities.Consts; using Tnb.WarehouseMgr.Entities.Dto; using Tnb.WarehouseMgr.Entities.Enums; using Tnb.WarehouseMgr.Entities.Exceptions; using Tnb.WarehouseMgr.Interfaces; namespace Tnb.WarehouseMgr { /// /// 齐套分拣服务类 /// [ServiceModule(BizTypeId)] [OverideVisualDev(ModuleConsts.MODULE_WMSSETSORTING_ID)] public class WmsSetSortingService : BaseWareHouseService, IWmsSetSortingService { private readonly ISqlSugarClient _db; private readonly IWareHouseService _wareHouseService; private readonly IBillRullService _billRullService; private readonly IUserManager _userManager; private readonly ICacheManager _cacheManager; private readonly IRunService _runService; private readonly IVisualDevService _visualDevService; private const string BizTypeId = "26186830379045"; public WmsSetSortingService( ISqlSugarRepository repository, IWareHouseService wareHouseService, IUserManager userManager, IBillRullService billRullService, ICacheManager cacheManager, IRunService runService, IVisualDevService visualDevService, IEventPublisher publisher ) { _db = repository.AsSugarClient(); _wareHouseService = wareHouseService; _billRullService = billRullService; _userManager = userManager; _cacheManager = cacheManager; _runService = runService; _visualDevService = visualDevService; //OverideFuncs.CreateAsync = Create; } private async Task Create(VisualDevModelDataCrInput input) { //在线开发 try { VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(ModuleConsts.MODULE_WMSEMPTYINSTOCK_ID, true); await _runService.Create(templateEntity, input); await PackSortingByAdd(); } catch (Exception) { throw; } return Task.FromResult(1); } /// /// 齐套分拣(新增状态) /// /// [HttpPost, Timed(Name = nameof(PackSortingByAdd))] public async Task PackSortingByAdd(CancellationToken? ct = default) { if (_userManager.User.IsNull()) { System.Security.Claims.ClaimsPrincipal curUser = await GetUserIdentity(); await SetUserEntity(_userManager, curUser); } SqlSugarClient curDb = _db.CopyNew(); try { await curDb.Ado.BeginTranAsync(); string firstLocationId = "27010980724501", secondLocationId = "27010987857941"; BasLocation endLocation = await curDb.Queryable().FirstAsync(it => it.id == secondLocationId); List setSortings = await curDb.Queryable() .Where(a => a.status == WmsWareHouseConst.BILLSTATUS_ADD_ID) .Select() .OrderBy(a => a.seq) .ToListAsync(); List items = await curDb.Queryable().Where(it => it.status == WmsWareHouseConst.BILLSTATUS_ON_ID).ToListAsync(); bool onFlag = items?.Count > 0; if (setSortings?.Count > 0 && !onFlag) { WmsSetsortingH singleSorting = setSortings[0]; List setSortingDList = await curDb.Queryable().Where(it => it.bill_id == singleSorting.id).ToListAsync(); if (setSortingDList?.Count > 0) { List carryMats = new(); List carryCodes = new(); List carryIds = new(); foreach (WmsSetsortingD os in setSortingDList) { OutStockStrategyQuery OutStockStrategyInput = new() { material_id = os.material_id, warehouse_id = os.warehouse_id, code_batch = os.code_batch, }; List outStkCarrys = await _wareHouseService.OutStockStrategy(OutStockStrategyInput); List carryCodesPart = await curDb.Queryable().InnerJoin((a, b) => a.id == b.carry_id).InnerJoin((a, b, c) => a.location_id == c.id) .Where((a, b) => outStkCarrys.Select(x => x.id).Contains(b.carry_id)) .Select() .ToListAsync(); if (carryCodesPart?.Count > 0) { carryCodes.AddRange(carryCodesPart); decimal codeQty = carryCodes.Sum(x => x.codeqty); if (codeQty < os.pr_qty) { throw new AppFriendlyException($"需要出库[{os.pr_qty}],实际库存{codeQty},数量不足", 500); } List curCarryCodes = new(); for (int i = 0; i < carryCodesPart.Count; i++) { if (os.pr_qty > carryCodesPart[i].codeqty) { os.pr_qty -= carryCodesPart[i].codeqty; curCarryCodes.Add(carryCodesPart[i]); } else if (os.pr_qty <= carryCodesPart[i].codeqty) { WmsCarryCode curCarryCode = DeepCopyHelper.DeepCopy(carryCodesPart[i]); curCarryCode.codeqty = os.pr_qty; curCarryCodes.Add(curCarryCode); break; } } List partCarryMats = curCarryCodes.Adapt>(); for (int i = 0; i < partCarryMats.Count; i++) { partCarryMats[i].need_qty = curCarryCodes[i].codeqty; } carryMats.AddRange(partCarryMats); } } if (carryMats.Count > 0) { carryMats.ForEach(x => x.id = SnowflakeIdHelper.NextId()); carryMats = carryMats.OrderBy(o => o.create_time).GroupBy(g => new { g.carry_id, g.material_id, g.code_batch }) .Select(x => { WmsCarryMat[] arr = x.ToArray(); WmsCarryMat carryMat = arr[^arr.Length]; carryMat.need_qty = arr.Sum(d => d.need_qty); return carryMat; }) .ToList(); _ = await curDb.Insertable(carryMats).ExecuteCommandAsync(); carryIds = carryMats.Select(x => x.carry_id).Distinct().ToList(); _ = await curDb.Updateable() .SetColumns(it => new WmsCarryH { out_status = ((int)EnumOutStatus.全部出).ToString(), collocation_scheme_id = singleSorting.collocation_scheme_id, collocation_scheme_code = singleSorting.collocation_scheme_code, source_id = singleSorting.source_id, source_code = singleSorting.source_code }) .Where(it => carryIds.Contains(it.id)).ExecuteCommandAsync(); //await curDb.Updateable().SetColumns(it => new WmsCarryH { out_status = ((int)EnumOutStatus.全部出).ToString(), collocation_scheme_id = singleSorting.collocation_scheme_id, collocation_scheme_code = singleSorting.collocation_scheme_code }).Where(it => carryIds.Contains(it.id)).ExecuteCommandAsync(); //天益项目不需要 //await _db.Updateable().SetColumns(it => new WmsCarryH { out_status = ((int)EnumOutStatus.分拣出).ToString() }).Where(it => sortingOutIds.Contains(it.id)).ExecuteCommandAsync(); } WmsCarryH[] carrys = await curDb.Queryable().Where(it => carryIds.Contains(it.id)).ToArrayAsync(); if (carrys?.Length > 0) { if (setSortings?.Count > 0) { WmsCarryH curCarry = carrys[^carrys.Length]; bool isMatch = await IsCarryAndLocationMatchByCarryStd(curCarry, endLocation); if (!isMatch) { throw new AppFriendlyException("库位与载具规格不匹配", 500); } } List preTasks = new(); List locIds = new(); int mid = 6; if (carrys.Length > mid) { WmsCarryH[] leftCarrys = carrys[..mid]; WmsCarryH[] rightCarrys = carrys[mid..]; await InnerGenPreTask(leftCarrys, locIds, firstLocationId, singleSorting.id, singleSorting.bill_code, preTasks, endLocation); await InnerGenPreTask(rightCarrys, locIds, secondLocationId, singleSorting.id, singleSorting.bill_code, preTasks, endLocation); } else { await InnerGenPreTask(carrys, locIds, firstLocationId, singleSorting.id, singleSorting.bill_code, preTasks, endLocation); } List pretaskCodes = new(); foreach (WmsPretaskH pt in preTasks) { List partCodes = carryCodes.FindAll(x => x.carry_id == pt.carry_id).Distinct().ToList(); List curPreTaskCodes = partCodes.Adapt>(); curPreTaskCodes.ForEach(x => { x.id = SnowflakeIdHelper.NextId(); x.bill_id = pt.id; x.create_time = DateTime.Now; }); pretaskCodes.AddRange(curPreTaskCodes); } _ = await _wareHouseService.GenPreTask(preTasks, pretaskCodes); _ = await curDb.Updateable().SetColumns(it => new WmsSetsortingH { status = WmsWareHouseConst.BILLSTATUS_ON_ID }).Where(it => it.id == singleSorting.id).ExecuteCommandAsync(); GenPreTaskUpInput genPreTaskAfterUpInput = new() { CarryIds = preTasks.Select(x => x.carry_id).ToList(), LocationIds = new HashSet(locIds).ToList() }; await _wareHouseService.GenInStockTaskHandleAfter(genPreTaskAfterUpInput, it => new WmsCarryH { is_lock = 1, carry_status = ((int)EnumCarryStatus.齐套分拣).ToString() }, it => new BasLocation { is_use = ((int)EnumCarryStatus.齐套分拣).ToString(), is_lock = 1 }); } } } await curDb.Ado.CommitTranAsync(); } catch (Exception ex) { JNPF.Logging.Log.Error("齐套分拣执行时出现错误", ex); await curDb.Ado.RollbackTranAsync(); if (_userManager?.ToKen.IsNullOrEmpty() ?? false) { TimedTaskErrorInfo ei = new() { RequestURL = App.HttpContext?.Request?.Path, RequestMethod = App.HttpContext?.Request?.Method, userIdentity = await GetUserIdentity(_userManager.ToKen), }; TimedTaskException timedTaskEx = ex.ToTimedTaskException(ei); //cts?.Cancel(); throw timedTaskEx; } } finally { await InvokeGenPretaskExcute(); } } private async Task InnerGenPreTask(WmsCarryH[] carrys, List locIds, string eLocationId, string requireId, string requireCode, List preTasks, BasLocation endLocation) { foreach (WmsCarryH carry in carrys) { WmsPointH sPoint = await _db.Queryable().FirstAsync(it => it.location_id == carry.location_id); WmsPointH ePoint = await _db.Queryable().FirstAsync(it => it.location_id == eLocationId); if (sPoint != null && ePoint != null) { List? points = await _wareHouseService.PathAlgorithms(sPoint.id, ePoint.id); if (points?.Count > 0) { locIds.AddRange(points.Select(x => x.location_id).ToList()!); } //根据获取的路径点生成预任务,生成顺序必须预路径算法返回的起终点的顺序一致(预任务顺序) if (points?.Count > 0) { if (points.Count <= 2) { throw new AppFriendlyException($"sPoint {sPoint.point_code} ePoint{ePoint.point_code}该路径不存在", 500); } List curPreTasks = points.Where(it => !it.location_id.IsNullOrEmpty()).GroupBy(g => g.area_code).Select(it => { WmsPointH? sPoint = it.FirstOrDefault(); WmsPointH? ePoint = it.LastOrDefault(); WmsPretaskH preTask = new() { org_id = _userManager.User.OrganizeId, startlocation_id = sPoint?.location_id!, startlocation_code = sPoint?.location_code!, endlocation_id = ePoint?.location_id!, endlocation_code = ePoint?.location_code!, start_floor = sPoint?.floor.ToString(), end_floor = ePoint?.floor.ToString(), bill_code = _billRullService.GetBillNumber(WmsWareHouseConst.WMS_PRETASK_H_ENCODE).GetAwaiter().GetResult(), status = WmsWareHouseConst.PRETASK_BILL_STATUS_DXF_ID, biz_type = WmsWareHouseConst.BIZTYPE_WMSSETSORTING_ID, task_type = WmsWareHouseConst.WMS_PRETASK_OUTSTOCK_TYPE_ID, carry_id = carry.id, carry_code = carry.carry_code, area_id = sPoint?.area_id!, area_code = it.Key, require_id = requireId, require_code = requireCode, create_id = _userManager.UserId, create_time = DateTime.Now, source_id = carry.source_id, source_code = carry.source_code, }; return preTask; }).ToList(); if (endLocation.is_sign == 0) { curPreTasks[^1].is_sign = 0; // 修改最后一个元素的是否签收值 } preTasks.AddRange(curPreTasks); } } } } public override async Task ModifyAsync(WareHouseUpInput input) { if (input == null) { throw new ArgumentNullException(nameof(input)); } //根据载具更新明细表状态 try { await _db.Ado.BeginTranAsync(); string carryId = input.carryIds[^input.carryIds.Count]; List? ssds = await _db.Queryable().Where(it => it.bill_id == input.requireId).ToListAsync(); List carryCodes = await _db.Queryable().Where(it => it.carry_id == carryId).ToListAsync(); List sortingCoees = carryCodes.Adapt>(); sortingCoees.ForEach(x => { string? billDId = ssds?.Find(xx => xx.material_id == x.material_id && xx.code_batch == x.code_batch)?.id; if (billDId.IsNullOrEmpty()) { billDId = ssds?.Find(xx => xx.material_id == x.material_id)?.id; } x.id = SnowflakeIdHelper.NextId(); x.bill_id = input.requireId; x.bill_d_id = billDId!; x.org_id = ssds?.Select(xx => xx.org_id).FirstOrDefault() ?? string.Empty; x.create_id = _userManager.UserId; x.create_time = DateTime.Now; }); _ = await _db.Insertable(sortingCoees).ExecuteCommandAsync(); List detailIds = sortingCoees.Select(x => x.bill_d_id).ToList(); List curSortingDetails = ssds.FindAll(x => detailIds.Contains(x.id)); Dictionary> dic = sortingCoees.GroupBy(g => g.bill_d_id).ToDictionary(x => x.Key, x => x.Select(x => x.codeqty).ToList()); foreach (WmsSetsortingD osd in curSortingDetails) { if (dic.ContainsKey(osd.id)) { osd.qty += dic[osd.id].Sum(d => d); osd.line_status = osd.qty >= osd.pr_qty ? WmsWareHouseConst.BILLSTATUS_COMPLETE_ID : WmsWareHouseConst.BILLSTATUS_ON_ID; } } _ = await _db.Updateable(curSortingDetails).ExecuteCommandAsync(); if (curSortingDetails.All(it => it.line_status == WmsWareHouseConst.BILLSTATUS_COMPLETE_ID)) { _ = await _db.Updateable().SetColumns(it => new WmsSetsortingH { status = WmsWareHouseConst.BILLSTATUS_COMPLETE_ID }).Where(it => it.id == input.requireId).ExecuteCommandAsync(); } WmsCarryH carry = await _db.Queryable().SingleAsync(it => it.id == carryId); if (carry != null) { if (carry.location_id?.IsNotEmptyOrNull() ?? false) { _ = await _db.Updateable().SetColumns(it => new BasLocation { is_use = ((int)EnumCarryStatus.空闲).ToString() }).Where(it => it.id == carry.location_id).ExecuteCommandAsync(); } carry.out_status = ((int)EnumOutStatus.正常).ToString(); carry.carry_status = ((int)EnumCarryStatus.齐套).ToString(); carry.location_id = null; carry.location_code = null; _ = await _db.Updateable(carry).UpdateColumns(it => new { it.out_status, it.carry_status, it.location_id, it.location_code }).ExecuteCommandAsync(); _ = await _db.Deleteable().Where(it => it.carry_id == carryId).ExecuteCommandAsync(); } await _db.Ado.CommitTranAsync(); } catch (Exception) { await _db.Ado.RollbackTranAsync(); throw; } } } }