using Furion; using Furion.EventBus; using Furion.FriendlyException; using Furion.RemoteRequest.Extensions; using Mapster; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Myshipping.Application.ConfigOption; using Myshipping.Application.Entity; using Myshipping.Application.Service.BookingOrder.Dto; using Myshipping.Core; using Myshipping.Core.Entity; using Myshipping.Core.Service; using Newtonsoft.Json.Linq; using NPOI.OpenXmlFormats.Wordprocessing; using SqlSugar; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; using Yitter.IdGenerator; namespace Myshipping.Application.Event { /// /// 运踪 /// public class BookingSlotStockSubscriber : IEventSubscriber { private readonly ILogger _logger; public BookingSlotStockSubscriber( ILogger logger) { _logger = logger; } //更新库存 [EventSubscribe("BookingSlotStock:Update")] public async Task BookingSlotStock(EventHandlerExecutingContext context) { _logger.LogInformation($"收到更新库存订阅请求:{context.Source.Payload}"); var _repBase = App.GetService>(); var _repCtn = App.GetService>(); var _repStock = App.GetService>(); var _repAlloc = App.GetService>(); var _repAllocCtn = App.GetService>(); var paraObj = context.Source.Payload as BookingSlotStockUpdateModel; var baseList = await _repBase.AsQueryable().Filter(null, true) .Where(x => !x.IsDeleted && !x.IS_CANCELLATION && x.VESSEL == paraObj.VESSEL && x.VOYNO == paraObj.VOYNO && x.CONTRACT_NO == paraObj.CONTRACT_NO && x.BOOKING_SLOT_TYPE == paraObj.BOOKING_SLOT_TYPE && x.CARRIERID == paraObj.CARRIERID && x.PLACEDELIVERY == paraObj.PLACEDELIVERY && x.PLACERECEIPT == paraObj.PLACERECEIPT) .OrderByDescending(x => x.UpdatedTime) .ToListAsync(); if (!baseList.Any()) { return; } var stockObj = await _repStock.AsQueryable() .Filter(null, true) .FirstAsync(x => !x.IsDeleted && x.VESSEL == paraObj.VESSEL && x.VOYNO == paraObj.VOYNO && x.CONTRACT_NO == paraObj.CONTRACT_NO && x.BOOKING_SLOT_TYPE == paraObj.BOOKING_SLOT_TYPE && x.CARRIERID == paraObj.CARRIERID && x.PLACEDELIVERY == paraObj.PLACEDELIVERY && x.PLACERECEIPT == paraObj.PLACERECEIPT); if (stockObj == null) { stockObj = new BookingSlotStock(); stockObj.Id = YitIdHelper.NextId(); await _repStock.InsertAsync(stockObj); } var bkId = stockObj.Id; baseList[0].Adapt(stockObj); stockObj.Id = bkId; // 总舱位数 stockObj.TOTAL_ORDERS = baseList.Count; var lstBaseId = baseList.Select(x => x.Id).ToList(); // 总的箱型箱量 var ctnAllList = await _repCtn.AsQueryable().Filter(null, true) .Where(x => !x.IsDeleted && lstBaseId.Contains(x.SLOT_ID)) .GroupBy(x => x.CTNALL) .Select(x => new { x.CTNALL, CTNNUM = SqlFunc.AggregateSum(x.CTNNUM) }).ToListAsync(); stockObj.CTN_STAT = string.Join(' ', ctnAllList.Select(c => c.CTNALL + "*" + c.CTNNUM)); // 总箱数 stockObj.TOTAL_CTNS = ctnAllList.Sum(x => x.CTNNUM); // 订舱引用表主键与订舱主表主键 var lstAllocKeyList = await _repAlloc.AsQueryable() .Filter(null, true) .Where(x => !x.IsDeleted && lstBaseId.Contains(x.BOOKING_SLOT_ID)) .Select(x => new { x.Id, x.BOOKING_SLOT_ID }) .ToListAsync(); // 如果舱位未被引用过,可以直接确定库存 if (!lstAllocKeyList.Any()) { // 已使用舱位数 stockObj.USE_NUM = 0; // 已使用的箱型箱量 stockObj.USE_CTN_STAT = ""; // 已使用的箱数 stockObj.USE_CTNS_NUM = 0; // 剩余的箱型箱量 stockObj.REMAIN_CTN_STAT = stockObj.CTN_STAT; // 剩余箱数 stockObj.REMAIN_CTNS_NUM = stockObj.TOTAL_CTNS; } else { // 已使用舱位数 stockObj.USE_NUM = lstAllocKeyList.DistinctBy(x => x.BOOKING_SLOT_ID).Count(); // 订舱引用表主键列表 var lstAllocIdList = lstAllocKeyList.Select(x => x.Id).ToList(); // 已使用的箱型箱量 var userCtnList = await _repAllocCtn.AsQueryable() .Filter(null, true) .Where(x => !x.IsDeleted && lstAllocIdList.Contains(x.SLOT_ALLOC_ID)) .GroupBy(x => x.CTNALL) .Select(x => new { x.CTNALL, CTNNUM = SqlFunc.AggregateSum(x.CTNNUM) }).ToListAsync(); stockObj.USE_CTN_STAT = string.Join(' ', userCtnList.Select(c => c.CTNALL + "*" + c.CTNNUM)); // 已使用的箱数 stockObj.USE_CTNS_NUM = userCtnList.Sum(x => x.CTNNUM); // 剩余的箱型箱量 Dictionary remainCtnList = new(ctnAllList.Count); foreach (var item in ctnAllList) { var useItem = userCtnList.FirstOrDefault(x => x.CTNALL == item.CTNALL); if (useItem == null) { remainCtnList.Add(item.CTNALL, item.CTNNUM); } else { int remainCtnNum = item.CTNNUM - useItem.CTNNUM; if (remainCtnNum > 0) { remainCtnList.Add(item.CTNALL, remainCtnNum); } } } stockObj.REMAIN_CTN_STAT = string.Join(' ', remainCtnList.Select(x => x.Key + "*" + x.Value)); // 剩余箱数 stockObj.REMAIN_CTNS_NUM = stockObj.TOTAL_CTNS - stockObj.USE_CTNS_NUM; } await _repStock.UpdateAsync(stockObj); } } /// /// 刷新库存统计对象 /// public class BookingSlotStockUpdateModel { /// /// 船名 /// public string VESSEL { get; set; } /// /// 航次号 /// public string VOYNO { get; set; } /// /// 合约号 /// public string CONTRACT_NO { get; set; } /// /// 订舱方式 CONTRACT_ORDER-合约订舱;SPOT_ORDER-SPOT订舱 /// public string BOOKING_SLOT_TYPE { get; set; } /// /// 船公司代号 /// public string CARRIERID { get; set; } /// /// 收货地 /// public string PLACERECEIPT { get; set; } /// /// 交货地 /// public string PLACEDELIVERY { get; set; } } }