using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using JNPF.Common.Core.Manager; using JNPF.Common.Dtos.VisualDev; using JNPF.Common.Extension; 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 OBS.Internal; using SqlSugar; using Tnb.BasicData.Entities; using Tnb.WarehouseMgr.Entities; using Tnb.WarehouseMgr.Entities.Consts; using Tnb.WarehouseMgr.Entities.Dto; using Tnb.WarehouseMgr.Entities.Enums; using Tnb.WarehouseMgr.Interfaces; namespace Tnb.WarehouseMgr { /// /// 盘点任务 /// [OverideVisualDev(ModuleConsts.MODULE_WMSCHECKTASK_ID)] public class WmsCheckTaskService : BaseWareHouseService { private readonly ISqlSugarClient _db; private readonly IWareHouseService _warehouseService; private readonly IUserManager _userManager; private readonly IVisualDevService _visualDevService; private readonly IRunService _runService; private readonly IBillRullService _billRullService; public WmsCheckTaskService( ISqlSugarRepository repository, IWareHouseService wareHouseService, IVisualDevService visualDevService, IRunService runService, IBillRullService billRullService, IUserManager userManager, IEventPublisher eventPublisher ) { _db = repository.AsSugarClient(); _warehouseService = wareHouseService; _visualDevService = visualDevService; _runService = runService; _billRullService = billRullService; _userManager = userManager; OverideFuncs.CreateAsync = Create; } private async Task Create(VisualDevModelDataCrInput input) { var row = 1; if (input == null) throw new ArgumentNullException(nameof(input)); try { await _db.Ado.BeginTranAsync(); if (input.data?.Count > 0) { var checkType = input.data[nameof(WmsCheckstockH.checkstock_type)]?.ToString(); if (!checkType.IsNullOrEmpty()) { var billStatus = new List { WmsWareHouseConst.PRETASK_BILL_STATUS_CANCEL_ID, WmsWareHouseConst.PRETASK_BILL_STATUS_COMPLE_ID, }; var filter = Expressionable.Create() .And((a, b) => b.wh_id == input.data[nameof(WmsCheckstockH.warehouse_id)].ToString()) .And((a, b) => b.is_type == ((int)EnumLocationType.存储库位).ToString()) .And((a, b) => !billStatus.Contains(a.status)) .ToExpression(); var queryTasks = new List>>(); queryTasks.Add(Task.Run(() => FetchDisTasks((a, b) => a.startlocation_id == b.id, filter))); queryTasks.Add(Task.Run(() => FetchDisTasks((a, b) => a.endlocation_id == b.id, filter))); var disTasks = await Task.WhenAll(queryTasks); if (disTasks?.Length > 0) { throw new AppFriendlyException("该仓库还有未完成的任务,不允许盘点!", 500); } VisualDevEntity? templateEntity = await _visualDevService.GetInfoById(ModuleConsts.MODULE_WMSCHECKTASK_ID, true); await _runService.Create(templateEntity, input); List carryCodes = new(); List details = new(); switch (checkType!.ToEnum()) { case EnumCheckType.全库盘点: carryCodes = await _db.Queryable().InnerJoin((a, b) => a.id == b.location_id) .Where(a => a.wh_id == input.data[nameof(WmsCheckstockH.warehouse_id)].ToString() && a.is_type == ((int)EnumLocationType.存储库位).ToString()) .Select() .ToListAsync(); carryCodes ??= Enumerable.Empty().ToList(); var checkStockDs = carryCodes.Adapt>(); var prQtyDic = checkStockDs.GroupBy(g => new { g.carry_id, g.material_id, g.code_batch }).ToDictionary(x => x.Key, x => x.Sum(d => d.codeqty)); foreach (var (k, v) in prQtyDic) { WmsCheckstockD? checkstockD = checkStockDs?.Find(x => string.Equals(k, $"{x.carry_id}{x.material_id}{x.code_batch}")); if (checkstockD != null) { checkstockD.id = SnowflakeIdHelper.NextId(); checkstockD.create_id = _userManager.UserId; checkstockD.create_time = DateTime.Now; checkstockD.pr_qty = v; details.Add(checkstockD); } } await _db.Insertable(details).ExecuteCommandAsync(); break; case EnumCheckType.物料盘点: break; case EnumCheckType.批次盘点: break; } //生成预任务信息 if (details.Count > 0 && carryCodes.Count > 0) { var locTypes = new[] { ((int)EnumLocationType.出库库位).ToString(), ((int)EnumLocationType.出入库位).ToString() }; var endLocs = await _db.Queryable().Where(it => it.wh_id == input.data[nameof(WmsCheckstockH.warehouse_id)].ToString() && locTypes.Contains(it.is_type)).ToArrayAsync(); var randomIndex = new Random().Next(0, endLocs.GetUpperBound(0)); var carrys = await _db.Queryable().Where(it => carryCodes.Select(x => x.carry_id).Distinct().Contains(it.id)).ToListAsync(); var curDetails = details.DistinctBy(x => x.carry_id).ToList(); var curCarryCodes = carryCodes.FindAll(x => curDetails.Select(d => d.carry_id).Contains(x.carry_id)); if (curCarryCodes.Count > 0) { List preTasks = new(); List locIds = new(); foreach (var item in carrys) { WmsPointH? sPoint = await _db.Queryable().FirstAsync(it => it.location_id == item.location_id); WmsPointH? ePoint = await _db.Queryable().FirstAsync(it => it.location_id == endLocs[randomIndex].id); if (sPoint != null && ePoint != null) { var points = await _warehouseService.PathAlgorithms(sPoint.id, ePoint.id); if (points.Count <= 2) throw new AppFriendlyException("该路径不存在", 500); if (points?.Count > 0) { locIds.AddRange(points.Select(x => x.location_id).ToList()!); var curPreTasks = points.Where(it => !it.location_id.IsNullOrEmpty()).GroupBy(g => g.area_code).Select(it => { var sPoint = it.FirstOrDefault(); var 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_WMSCHECKOUTSTOCK_ID, task_type = WmsWareHouseConst.WMS_PRETASK_OUTSTOCK_TYPE_ID, carry_id = item.id, carry_code = item.carry_code!, area_id = sPoint?.area_id!, area_code = it.Key, require_id = input.data["ReturnIdentity"].ToString(), require_code = input.data[nameof(WmsCheckstockH.checkstock_code)]?.ToString(), create_id = _userManager.UserId, create_time = DateTime.Now }; return preTask; }).ToList(); if (endLocs[randomIndex].is_sign == 0) { curPreTasks[^1].is_sign = 0; } preTasks.AddRange(curPreTasks); } } } List pretaskCodes = new(); foreach (var pt in preTasks) { var partCodes = carryCodes.FindAll(x => x.carry_id == pt.carry_id).Distinct().ToList(); var curPreTaskCodes = partCodes.Adapt>(); curPreTaskCodes.ForEach(x => { x.id = SnowflakeIdHelper.NextId(); x.bill_id = pt.id; x.create_time = DateTime.Now; }); pretaskCodes.AddRange(curPreTaskCodes); } var isOk = await _warehouseService.GenPreTask(preTasks, pretaskCodes); if (isOk) { await _db.Updateable().SetColumns(it => it.status == ((int)EnumCheckStatus.盘点中).ToString()).ExecuteCommandAsync(); GenPreTaskUpInput genPreTaskAfterUpInput = new(); genPreTaskAfterUpInput.CarryIds = preTasks.Select(x => x.carry_id).ToList(); genPreTaskAfterUpInput.LocationIds = new HashSet(locIds).ToList(); await _warehouseService.GenInStockTaskHandleAfter(genPreTaskAfterUpInput, it => new WmsCarryH { is_lock = 1 }, it => new BasLocation { is_lock = 1 }); } } } } } await _db.Ado.CommitTranAsync(); } catch (Exception) { row = 0; await _db.Ado.RollbackTranAsync(); throw; } finally { await InvokeGenPretaskExcute(); } return Task.FromResult(row); } private Task> FetchDisTasks(Expression> joinExp, Expression> whereExp) { return _db.Queryable().InnerJoin(joinExp).Where(whereExp).Select().ToListAsync(); } } }