diff --git a/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs b/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs index 3274a2f9..b4488ea7 100644 --- a/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs +++ b/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs @@ -31,6 +31,8 @@ namespace Myshipping.Application private readonly SqlSugarRepository _repBase; private readonly SqlSugarRepository _repCtn; private readonly SqlSugarRepository _repStock; + private readonly SqlSugarRepository _repAllocation; + private readonly SqlSugarRepository _repAllocationCtn; private readonly SqlSugarRepository _repBookingLog; private readonly SqlSugarRepository _repBookingLogDetail; @@ -47,13 +49,15 @@ namespace Myshipping.Application SqlSugarRepository repBookingLogDetail, ILogger logger, ISysCacheService cache, - IEventPublisher publisher) + IEventPublisher publisher, + SqlSugarRepository repAllocation) { _repBase = repBase; _repCtn = repCtn; _repStock = repStock; _repBookingLog = repBookingLog; _repBookingLogDetail = repBookingLogDetail; + _repAllocation = repAllocation; _logger = logger; @@ -405,7 +409,9 @@ namespace Myshipping.Application //更新库存 await _publisher.PublishAsync(new ChannelEventSource("BookingSlotStock:Update", input)); } + #endregion + #region 舱位引入 /// /// 查询可用的舱位及箱子 /// @@ -413,7 +419,7 @@ namespace Myshipping.Application public async Task> GetAvailableSlots([FromQuery] BookingSlotBaseDto input) { return await GetAvailableSlots(input, null); - } + } /// /// 查询可用的舱位及箱子列表 @@ -511,6 +517,113 @@ namespace Myshipping.Application return result; } + + /// + /// 检查指定订舱记录,是否可以引入舱位列表 + /// + /// 待引入的舱位列表 + /// 待关联的订舱记录 + /// (指定订舱记录是否已经引入过舱位数据,现有舱位及箱子是否满足需求,提示信息) + [NonAction] + public async Task<(bool isExists, bool isEnough, string message)> CheckImportSlots(List slots, long bookingOrderId) + { + slots ??= new List(); + + // 判断是否已存在引用关系 + if (bookingOrderId != 0 && await _repAllocation.IsExistsAsync(a => a.BOOKING_ID == bookingOrderId)) + { + return (true, false, $"订舱主键{bookingOrderId}已引用舱位"); + } + var slotIdList = slots.Select(s => s.Id).ToList(); + + // 查询可用舱位及箱子列表 + var latestSlotList = await GetAvailableSlots(null, slotIdList); + + // 判断余量是否满足需求 + foreach (var inSlotItem in slots) + { + var latestSlot = latestSlotList.FirstOrDefault(b => b.Id == inSlotItem.Id); + if (latestSlot == null) + { + return (false, false, $"订舱编号为{inSlotItem.SLOT_BOOKING_NO}的舱位已被占用或取消,请重新引入"); + } + if (inSlotItem.CtnList?.Any() == false) + { + return (false, false, $"每个舱位至少选择一个箱子,订舱编号:{inSlotItem.SLOT_BOOKING_NO}"); + } + foreach (var inCtnItem in inSlotItem.CtnList) + { + var latestCtn = latestSlot.CtnList.FirstOrDefault(c => c.CTNCODE == inCtnItem.CTNCODE); + if (latestCtn == null) + { + return (false, false, $"订舱编号为{latestSlot.SLOT_BOOKING_NO}的舱位中,箱型为{inCtnItem.CTNALL}的箱子已被占用或取消,请重新引入"); + } + if (latestCtn.CTNNUM < inCtnItem.CTNNUM) + { + return (false, false, $"订舱编号为{latestSlot.SLOT_BOOKING_NO}的舱位中,箱型为{inCtnItem.CTNALL}的箱子当前剩余{latestCtn.CTNNUM}个,少于所需的{inCtnItem.CTNNUM}个,请重新引入"); + } + } + } + return (false, true, $"可以引入"); + } + + public async Task ImportSlots(List slots, long bookingOrderId, bool isCheck) + { + slots ??= new List(); + + if (isCheck) + { + (bool isExists, bool isEnough, string message) checkResult = await CheckImportSlots(slots, bookingOrderId); + + if (checkResult.isExists || !checkResult.isEnough) + throw Oops.Bah(checkResult.message); + } + + var slotIdList = slots.Select(s => s.Id).ToList(); + List latestSlotList = await _repBase.AsQueryable().Where(b => slotIdList.Contains(b.Id)).ToListAsync(); + foreach (var inSlotItem in slots) + { + var latestSlot = latestSlotList.First(b => b.Id == inSlotItem.Id); + + var config = new TypeAdapterConfig(); + config.ForType() + .Ignore(dest => dest.CreatedTime) + .Ignore(dest => dest.UpdatedTime) + .Ignore(dest => dest.CreatedUserId) + .Ignore(dest => dest.UpdatedUserId) + .Ignore(dest => dest.CreatedUserName) + .Ignore(dest => dest.UpdatedUserName) + .Ignore(dest => dest.TenantId) + .Ignore(dest => dest.TenantName); + + var newSlotAllocation = latestSlot.Adapt(config); + newSlotAllocation.Id = 0; + newSlotAllocation.BOOKING_SLOT_ID = latestSlot.Id; + newSlotAllocation.BOOKING_ID = bookingOrderId; + newSlotAllocation.ALLO_BILL_NO = latestSlot.SLOT_BOOKING_NO; + newSlotAllocation.FINAL_BILL_NO = latestSlot.SLOT_BOOKING_NO; + await _repAllocation.InsertAsync(newSlotAllocation); + + var insertCtnList = inSlotItem.CtnList.Select(c => new BookingSlotAllocationCtn() + { + SLOT_ALLOC_ID = newSlotAllocation.Id, + CTNCODE = c.CTNCODE, + CTNALL = c.CTNALL, + CTNNUM = c.CTNNUM + }); + await _repAllocationCtn.InsertAsync(insertCtnList); + + // 更新库存 + await _publisher.PublishAsync(new ChannelEventSource("BookingSlotStock:Update", new Event.BookingSlotStockUpdateModel + { + BOOKING_SLOT_TYPE = latestSlot.BOOKING_SLOT_TYPE, + CARRIERID = latestSlot.CARRIERID, + CONTRACT_NO = latestSlot.CONTRACT_NO, + VESSEL = latestSlot.VESSEL, + VOYNO = latestSlot.VOYNO + })); + } + } #endregion } }