diff --git a/Myshipping.Application/Service/BookingOrder/BookingOrderService.cs b/Myshipping.Application/Service/BookingOrder/BookingOrderService.cs index 31df9840..5b24a19c 100644 --- a/Myshipping.Application/Service/BookingOrder/BookingOrderService.cs +++ b/Myshipping.Application/Service/BookingOrder/BookingOrderService.cs @@ -1588,43 +1588,22 @@ namespace Myshipping.Application } - // 【引入舱位】:如果存在舱位引入数据,则判断引入的舱位及箱子目前是否仍然可用 + // 【引入舱位】:判断订舱是否引入过舱位数据,以及余量是否充足 if (input.Slots?.Any() == true) { - // 当前操作如果为订舱台账的“修改”操作,判断是否该票订舱是否引入过舱位,如果引入过,则后续不再执行舱位引入的逻辑 - if (input.Id != 0 && await _repSlotAllocation.IsExistsAsync(a => a.BOOKING_ID == input.Id)) + var checkResult = await bookingSlotService.CheckImportSlots(input.Slots, input.Id); + + // 如果该票订舱引入过舱位,则清空后续input.Slots,不再执行舱位引入的逻辑 + if (checkResult.isExists) { input.Slots.Clear(); } else { - var slotIdList = input.Slots.Select(s => s.Id).ToList(); - - var latestSlotList = await bookingSlotService.GetAvailableSlots(null, slotIdList); - - foreach (var inSlotItem in input.Slots) + // 如果该票订舱没有引入过舱位,判断余量是否充足 + if (!checkResult.isEnough) { - var latestSlot = latestSlotList.FirstOrDefault(b => b.Id == inSlotItem.Id); - if (latestSlot == null) - { - throw Oops.Bah($"订舱编号为{inSlotItem.SLOT_BOOKING_NO}的舱位已被占用或取消,请重新引入"); - } - if (inSlotItem.CtnList?.Any() == false) - { - throw Oops.Bah($"每个舱位至少选择一个箱子,订舱编号:{inSlotItem.SLOT_BOOKING_NO}"); - } - foreach (var inCtnItem in inSlotItem.CtnList) - { - var latestCtn = latestSlot.CtnList.FirstOrDefault(c => c.CTNCODE == inCtnItem.CTNCODE); - if (latestCtn == null) - { - throw new Exception($"订舱编号为{latestSlot.SLOT_BOOKING_NO}的舱位中,箱型为{inCtnItem.CTNALL}的箱子已被占用或取消,请重新引入"); - } - if (latestCtn.CTNNUM < inCtnItem.CTNNUM) - { - throw new Exception($"订舱编号为{latestSlot.SLOT_BOOKING_NO}的舱位中,箱型为{inCtnItem.CTNALL}的箱子当前剩余{latestCtn.CTNNUM}个,少于所需的{inCtnItem.CTNNUM}个,请重新引入"); - } - } + throw Oops.Bah(checkResult.message); } } } @@ -1982,50 +1961,7 @@ namespace Myshipping.Application // 【引入舱位】:保存引用信息 if (input.Slots?.Any() == true) { - var slotIdList = input.Slots.Select(s => s.Id).ToList(); - List latestSlotList = await _repSlotBase.AsQueryable().Where(b => slotIdList.Contains(b.Id)).ToListAsync(); - foreach (var inSlotItem in input.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 = entity.Id; - newSlotAllocation.ALLO_BILL_NO = latestSlot.SLOT_BOOKING_NO; - newSlotAllocation.FINAL_BILL_NO = latestSlot.SLOT_BOOKING_NO; - await _repSlotAllocation.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 _repSlotAllocationCtn.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 - })); - } + await bookingSlotService.ImportSlots(input.Slots, entity.Id, false); } var Id = entity.Id; diff --git a/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs b/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs index 52621e27..8fd355a1 100644 --- a/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs +++ b/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; +using System.Threading; using System.Threading.Tasks; @@ -52,7 +53,8 @@ namespace Myshipping.Application ILogger logger, ISysCacheService cache, IEventPublisher publisher, - SqlSugarRepository repAllocation) + SqlSugarRepository repAllocation, + SqlSugarRepository repAllocationCtn) { _repBase = repBase; _repCtn = repCtn; @@ -60,6 +62,7 @@ namespace Myshipping.Application _repBookingLog = repBookingLog; _repBookingLogDetail = repBookingLogDetail; _repAllocation = repAllocation; + _repAllocationCtn = repAllocationCtn; _logger = logger; @@ -530,7 +533,7 @@ namespace Myshipping.Application /// /// 待引入的舱位列表 /// 待关联的订舱记录 - /// (指定订舱记录是否已经引入过舱位数据,现有舱位及箱子是否满足需求,提示信息) + /// isExists:指定订舱记录是否已经引入过舱位数据,isEnough:现有舱位及箱子是否满足需求,message:提示信息 [NonAction] public async Task<(bool isExists, bool isEnough, string message)> CheckImportSlots(List slots, long bookingOrderId) { @@ -573,70 +576,79 @@ namespace Myshipping.Application } return (false, true, $"可以引入"); } - + public static object ImportLockObj = new object(); + /// /// 为指定订舱记录引入舱位信息 /// /// 待引入的舱位列表 /// 待关联的订舱记录 /// 是否进行剩余量检查 - /// (是否成功,提示消息) + /// isSuccess:检查(余量及已引用检查)是否成功通过,message:提示信息 [NonAction] public async Task<(bool isSuccess, string message)> ImportSlots(List slots, long bookingOrderId, bool isCheck) { slots ??= new List(); - if (isCheck) + Monitor.Enter(ImportLockObj); + try { - (bool isExists, bool isEnough, string message) checkResult = await CheckImportSlots(slots, bookingOrderId); + if (isCheck) + { + (bool isExists, bool isEnough, string message) checkResult = await CheckImportSlots(slots, bookingOrderId); - if (checkResult.isExists || !checkResult.isEnough) - return (false, checkResult.message); - } + if (checkResult.isExists || !checkResult.isEnough) + return (false, 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() + 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) { - SLOT_ALLOC_ID = newSlotAllocation.Id, - CTNCODE = c.CTNCODE, - CTNALL = c.CTNALL, - CTNNUM = c.CTNNUM - }); - await _repAllocationCtn.InsertAsync(insertCtnList); + 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 - })); + // 更新库存 + 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 + })); + } + } + finally + { + Monitor.Exit(ImportLockObj); } return (true, "引入成功");