using System.Data; using System.Linq.Expressions; using JNPF; using JNPF.Common.Core.Manager; using JNPF.Common.Enums; using JNPF.Common.Extension; using JNPF.Common.Manager; using JNPF.Common.Security; using JNPF.EventBus; using JNPF.FriendlyException; using JNPF.LinqBuilder; using JNPF.Logging; using JNPF.Systems.Interfaces.System; using Mapster; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using SqlSugar; using Tnb.BasicData.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.Enums; using Tnb.WarehouseMgr.Entities.Exceptions; using Tnb.WarehouseMgr.Interfaces; namespace Tnb.WarehouseMgr { /// /// 齐套出库服务类 /// [ServiceModule(BizTypeId)] public class WmskittingOutService : BaseWareHouseService, IWmskittingOutService { private readonly ISqlSugarClient _db; private readonly IWareHouseService _warehouseService; private readonly IUserManager _userManager; private readonly IBillRullService _billRullService; private readonly IWmsCarryService _carryService; private readonly ICacheManager _cacheManager; private const string BizTypeId = "26169472620837"; public WmskittingOutService( ISqlSugarRepository repository, IWareHouseService warehouseService, IUserManager userManager, IBillRullService billRullService, IWmsCarryService carryService, ICacheManager cacheManager, IEventPublisher eventPublisher ) { _db = repository.AsSugarClient(); _warehouseService = warehouseService; _userManager = userManager; _billRullService = billRullService; _carryService = carryService; _cacheManager = cacheManager; } /// /// 齐套出库(新增状态) /// /// [HttpPost] public async Task KittingOutByAdd() { //if (ct?.IsCancellationRequested ?? false) //{ // ct?.ThrowIfCancellationRequested(); //} SqlSugarClient curDb = _db.CopyNew(); try { await curDb.Ado.BeginTranAsync(); List kittingOuts = await curDb.Queryable() .Where(a => a.status == WmsWareHouseConst.BILLSTATUS_ADD_ID) .OrderBy(a => a.seq) .ToListAsync(); // 是否有已呼叫的齐套出库任务 // var set = true ; 如果有 把set修改为false List items = await curDb.Queryable().Where(it => it.status == WmsWareHouseConst.BILLSTATUS_CALLED_ID).ToListAsync(); bool isCalled = items?.Count > 0; if (kittingOuts?.Count > 0) { foreach (WmsKittingoutH ko in kittingOuts) { //a.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID Expression> whereExp = (ko.carry_id != null) ? a => a.id == ko.carry_id : a => a.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID; List carrys = await curDb.Queryable() .InnerJoin((a, b) => a.collocation_scheme_id == b.id) .Where(whereExp.And(a => a.collocation_scheme_id == ko.collocation_scheme_id && a.is_lock == 0)) .OrderBy((a, b) => b.seq) .ToListAsync(); if (carrys?.Count > 0) { WmsCarryH? firstCarry = carrys.FirstOrDefault(); GenPreTaskUpInput genPreTaskInput = new() { CarryId = firstCarry?.id }; await _warehouseService.GenInStockTaskHandleAfter(genPreTaskInput, it => new WmsCarryH { is_lock = 1, out_status = EnumOutStatus.全部出.ToString() }, null!); ko.status = WmsWareHouseConst.BILLSTATUS_TOBESHIPPED_ID; ko.carry_id = firstCarry?.id; ko.carry_code = firstCarry?.carry_code; _ = await _db.Updateable(ko).UpdateColumns(it => new { it.status, it.carry_id, it.carry_code }).ExecuteCommandAsync(); _ = KittingOutByIsToBeShipped(); if (firstCarry != null) { firstCarry.source_id = ko.source_id; firstCarry.source_code = ko.source_code; _ = await _db.Updateable(firstCarry).UpdateColumns(it => new { it.source_id, it.source_code }).ExecuteCommandAsync(); } } else { //if(false) 跳出 插入完一次齐套分拣 set 改为false if (!isCalled) { WmsSetsortingH setSortingH = ko.Adapt(); setSortingH.warehouse_id = WmsWareHouseConst.WAREHOUSE_ZC_ID; setSortingH.id = SnowflakeIdHelper.NextId(); setSortingH.kittingout_id = ko.id; setSortingH.seq = ko.seq; setSortingH.org_id = _userManager.User.OrganizeId; setSortingH.create_id = _userManager.UserId; setSortingH.create_time = DateTime.Now; _ = await curDb.Insertable(setSortingH).ExecuteCommandAsync(); List kittingOutDetails = await curDb.Queryable().Where(it => it.bill_id == ko.id).ToListAsync(); List setSortDetails = kittingOutDetails.Adapt>(); setSortDetails.ForEach(x => { x.id = SnowflakeIdHelper.NextId(); x.bill_id = setSortingH.id; x.warehouse_id = setSortingH.warehouse_id; x.org_id = _userManager.User.OrganizeId; x.create_id = _userManager.UserId; x.create_time = DateTime.Now; }); _ = await curDb.Insertable(setSortDetails).ExecuteCommandAsync(); ko.status = WmsWareHouseConst.BILLSTATUS_CALLED_ID; _ = await curDb.Updateable(ko).UpdateColumns(it => it.status).ExecuteCommandAsync(); isCalled = true; //await Publish(nameof(IWmsSetSortingService.PackSortingByAdd)); } } } } await curDb.Ado.CommitTranAsync(); } catch (Exception ex) { 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; } } } /// /// 齐套出库,(待配送状态) /// /// [HttpPost] public async Task KittingOutByIsToBeShipped() { //if (UserManager.AsscessToken.IsNullOrWhiteSpace()) return; //var curUser = await GetUserIdentity(); SqlSugarClient curDb = _db.CopyNew(); try { List kittingOuts = await curDb.Queryable() .Where(a => a.status == WmsWareHouseConst.BILLSTATUS_TOBESHIPPED_ID) .OrderBy(a => a.seq) .ToListAsync(); if (kittingOuts?.Count > 0) { List> grpList = kittingOuts.GroupBy(g => g.location_id).ToList(); foreach (IGrouping? koGrp in grpList) { List locs = await curDb.Queryable().Where(it => it.id == koGrp.Key && it.is_use == ((int)EnumCarryStatus.空闲).ToString() && it.is_lock == 0).ToListAsync(); if (locs?.Count > 0) { WmsKittingoutH[] arr = koGrp.ToArray(); WmsKittingoutH ko = arr[^arr.Length]; WmsCarryH carry = await curDb.Queryable().SingleAsync(it => it.id == ko.carry_id); if (carry != null) { WmsPointH sPoint = await curDb.Queryable().FirstAsync(it => it.location_id == carry.location_id); WmsPointH ePoint = await curDb.Queryable().FirstAsync(it => it.location_id == ko.location_id); if (sPoint != null && ePoint != null) { //判断目标库位是否自动签收 BasLocation loc = await curDb.Queryable().SingleAsync(it => it.id == ePoint.location_id); List points = await _warehouseService.PathAlgorithms(sPoint.id, ePoint.id); if (points.Count <= 2) { throw new AppFriendlyException($"sPoint {sPoint.point_code} ePoint{ePoint.point_code}该路径不存在", 500); } if (points?.Count > 0) { List preTasks = 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(), startpoint_id = sPoint?.id!, startpoint_code = sPoint?.point_code!, endpoint_id = ePoint?.id!, endpoint_code = ePoint?.point_code!, bill_code = _billRullService.GetBillNumber(WmsWareHouseConst.WMS_PRETASK_H_ENCODE).GetAwaiter().GetResult(), status = WmsWareHouseConst.PRETASK_BILL_STATUS_DXF_ID, biz_type = ko.biz_type, task_type = WmsWareHouseConst.WMS_PRETASK_OUTSTOCK_TYPE_ID, carry_id = ko!.carry_id!, carry_code = ko!.carry_code!, area_id = sPoint?.area_id!, area_code = it.Key, require_id = ko.id, require_code = ko.bill_code, create_id = _userManager.UserId, create_time = DateTime.Now, source_id = ko.source_id, source_code = ko.source_code }; return preTask; }).ToList(); if (loc.is_sign == 0) { preTasks[^1].is_sign = 0; // 修改最后一个元素的是否签收值 } _ = await _warehouseService.GenPreTask(preTasks, null!); List subCarrys = await curDb.Queryable().Where(it => it.carry_id == ko.carry_id).ToListAsync(); List carryIds = subCarrys.Select(x => x.carry_id).Concat(new[] { ko.carry_id }).Distinct().ToList(); GenPreTaskUpInput genPreTaskInput = new() { CarryIds = carryIds!, LocationIds = new List { carry.location_id!, ko.location_id! } }; await _warehouseService.GenInStockTaskHandleAfter(genPreTaskInput, it => new WmsCarryH { is_lock = 1, carry_status = ((int)EnumCarryStatus.齐套).ToString() }, it => new BasLocation { is_lock = 1 }); _ = await curDb.Updateable().SetColumns(it => it.status == WmsWareHouseConst.BILLSTATUS_ON_ID).Where(it => it.id == ko.id).ExecuteCommandAsync(); } } } } } } } catch (Exception ex) { 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(); } } 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]; WmsCarryH carry = await _db.Queryable().SingleAsync(it => it.id == carryId); List? kods = await _db.Queryable().Where(it => it.bill_id == input.requireId).ToListAsync(); //载具为料架时,取所有料箱的条码 List mCarryIds = new(); if (carry.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID) { List carryDs = await _db.Queryable().Where(it => it.carry_id == carryId).ToListAsync(); mCarryIds = carryDs.Select(x => x.membercarry_id).ToList(); } //当前载具对应的所有条码插入 Expression> whereExp = mCarryIds?.Count > 0 ? a => mCarryIds.Contains(a.carry_id) : a => a.carry_id == carryId; List carryCodes = await _db.Queryable().Where(whereExp).ToListAsync(); List kittingoutCodes = carryCodes.Adapt>(); kittingoutCodes.ForEach(x => { string? billDId = kods?.Find(xx => xx.material_id == x.material_id && xx.code_batch == x.code_batch)?.id; if (billDId.IsNullOrEmpty()) { billDId = kods?.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 = _userManager.User.OrganizeId; x.create_id = _userManager.UserId; x.create_time = DateTime.Now; }); int row = await _db.Insertable(kittingoutCodes).ExecuteCommandAsync(); List detailIds = kittingoutCodes.Select(x => x.bill_d_id).ToList(); List curKittingoutDetails = kods.FindAll(x => detailIds.Contains(x.id)); Dictionary> dic = kittingoutCodes.GroupBy(g => g.bill_d_id).ToDictionary(x => x.Key, x => x.Select(x => x.codeqty).ToList()); foreach (WmsKittingoutD kod in curKittingoutDetails) { if (dic.ContainsKey(kod.id)) { kod.qty += dic[kod.id].Sum(d => d); kod.line_status = kod.qty >= kod.pr_qty ? WmsWareHouseConst.BILLSTATUS_COMPLETE_ID : WmsWareHouseConst.BILLSTATUS_ON_ID; } } _ = await _db.Updateable(curKittingoutDetails).ExecuteCommandAsync(); bool isOk = await _db.Updateable().SetColumns(it => new WmsKittingoutH { status = WmsWareHouseConst.BILLSTATUS_COMPLETE_ID }).Where(it => it.id == input.requireId).ExecuteCommandHasChangeAsync(); //if (carry != null) //{ // row = await _carryService.UpdateNullCarry(carry); // isOk = row > 0; //} //判断当前载具是否为料架,如果是料架 清空所有料架/料箱数据, if (carry.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID && mCarryIds?.Count > 0) { List carrys = await _db.Queryable().Where(it => mCarryIds.Contains(it.id)).ToListAsync(); carrys.Add(carry); if (carrys?.Count > 0) { await _db.Ado.BeginTranAsync(); List>> tasks = new(); Task upateNullCarryFunc(WmsCarryH carryIt) { return Task.Run(() => _db.CopyNew().Updateable(carryIt).ExecuteCommandAsync()); } foreach (WmsCarryH carryIt in carrys) { tasks.Add(_carryService.UpdateNullCarry(carryIt, upateNullCarryFunc)); } int[] all = await Task.WhenAll(tasks.Select(t => t.Unwrap())); if (all.All(x => x > 0)) { isOk = all?.Length > 0; } await _db.Ado.CommitTranAsync(); } } if (!isOk) { throw Oops.Oh(ErrorCode.COM1001); } await _db.Ado.CommitTranAsync(); } catch (Exception) { await _db.Ado.RollbackTranAsync(); throw; } } /// /// MES齐套出库接口 /// /// /// [HttpPost] [AllowAnonymous] public async Task MESKittingOutStk(List input) { bool isSuccessFul = false; if (input.IsNull()) { throw new ArgumentNullException(nameof(input)); } try { await _db.Ado.BeginTranAsync(); List kittingOutDs = new(); List kittingOuts = input.Adapt>(); string[] ids = input.Select(x => x.location_code).ToArray(); for (int i = 0; i < kittingOuts.Count; i++) { WmsKittingoutH x = kittingOuts[i]; x.id = SnowflakeIdHelper.NextId(); x.bill_code = _billRullService.GetBillNumber(WmsWareHouseConst.WMS_KITTINGOUTSTK_ENCODE).GetAwaiter().GetResult(); x.bill_date = DateTime.Now; x.bill_type = WmsWareHouseConst.BIZTYPE_WMSKITTINGOUTSTK_ID; x.status = WmsWareHouseConst.BILLSTATUS_ADD_ID; x.biz_type = WmsWareHouseConst.BIZTYPE_WMSKITTINGOUTSTK_ID; x.location_id = ids[i]; List? d = input[i]?.wmsKittingoutDs?.Adapt>(); d?.ForEach(it => { it.id = SnowflakeIdHelper.NextId(); it.bill_id = x.id; it.qty = 0; it.real_box = 0; it.warehouse_id = x.warehouse_id; }); if (d != null) { kittingOutDs.AddRange(d); } } _ = await _db.Insertable(kittingOuts).ExecuteCommandAsync(); _ = await _db.Insertable(kittingOutDs).ExecuteCommandAsync(); await _db.Ado.CommitTranAsync(); await KittingOutByAdd(); isSuccessFul = true; } catch (Exception ex) { Log.Error("MES齐套出库接口出错", ex); isSuccessFul = false; await _db.Ado.RollbackTranAsync(); } return isSuccessFul; } } }