using Furion; using Furion.EventBus; using Mapster; using Microsoft.Extensions.Logging; using Myshipping.Core; using SqlSugar; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; 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) { BookingSlotStockUpdateModel paraObj = context.Source.Payload as BookingSlotStockUpdateModel; await BookingSlotStock(paraObj); } public async Task BookingSlotStock(BookingSlotStockUpdateModel paraObj) { _logger.LogInformation($"收到更新库存订阅请求:{paraObj.ToJsonString()}"); var _repBase = App.GetService>(); var _repCtn = App.GetService>(); var _repStock = App.GetService>(); var _repAlloc = App.GetService>(); var _repAllocCtn = App.GetService>(); if (string.IsNullOrEmpty(paraObj.VESSEL) || string.IsNullOrEmpty(paraObj.VOYNO) || string.IsNullOrEmpty(paraObj.CONTRACT_NO) || string.IsNullOrEmpty(paraObj.BOOKING_SLOT_TYPE) || string.IsNullOrEmpty(paraObj.CARRIERID) || string.IsNullOrEmpty(paraObj.PORTLOADID) || string.IsNullOrEmpty(paraObj.PORTDISCHARGEID)) { _logger.LogInformation($"收到更新库存订阅请求:部分参数存在空值,结束"); return; } var baseList = await _repBase.AsQueryable().Filter(null, true) .Where(x => !x.IsDeleted && x.TenantId == paraObj.TenantId && 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.PORTLOADID == paraObj.PORTLOADID && x.PORTDISCHARGEID == paraObj.PORTDISCHARGEID) .OrderByDescending(x => x.UpdatedTime) .ToListAsync(); var stockObj = await _repStock.AsQueryable().Filter(null, true) .FirstAsync(x => !x.IsDeleted && x.TenantId == paraObj.TenantId && 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.PORTLOADID == paraObj.PORTLOADID && x.PORTDISCHARGEID == paraObj.PORTDISCHARGEID); if (!baseList.Any()) { if (stockObj != null) { // 从库存表删除这7项维度的库存数据 await _repStock.DeleteAsync(x => x.Id == stockObj.Id); } return; } var isInsert = stockObj == null; var idTemp = stockObj?.Id; stockObj = baseList[0].Adapt(stockObj); if (isInsert) { stockObj.Id = 0; } else { stockObj.Id = (long)idTemp; } // 总舱位数 stockObj.TOTAL_ORDERS = baseList.Count; // 取消舱位数 stockObj.CANCEL_NUM = baseList.Count(x => x.IS_CANCELLATION); // 舱位主键列表 var slotBaseIdList = baseList.Select(x => x.Id).ToList(); // 总的箱型箱量 var ctnAllList = await _repCtn.AsQueryable().Filter(null, true) .Where(x => !x.IsDeleted && slotBaseIdList.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 && slotBaseIdList.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 allocIdList = lstAllocKeyList.Select(x => x.Id).ToList(); var allocSlotIdList = lstAllocKeyList.Select(x => x.BOOKING_SLOT_ID).Distinct().ToList(); var userCtnNumList = await _repAllocCtn.AsQueryable().Filter(null, true) .Where(x => !x.IsDeleted && allocIdList.Contains(x.SLOT_ALLOC_ID)) .GroupBy(x => x.SLOT_ALLOC_ID) .Select(x => new { x.SLOT_ALLOC_ID, CTNNUM = SqlFunc.AggregateSum(x.CTNNUM) }).ToListAsync(); var hasCtnNumList = await _repCtn.AsQueryable().Filter(null, true) .Where(x => !x.IsDeleted && allocSlotIdList.Contains(x.SLOT_ID)) .GroupBy(x => x.SLOT_ID) .Select(x => new { x.SLOT_ID, CTNNUM = SqlFunc.AggregateSum(x.CTNNUM) }) .ToListAsync(); var useNum = 0; foreach (long slotId in allocSlotIdList) { List temp1 = lstAllocKeyList.Where(x => x.BOOKING_SLOT_ID == slotId).Select(x => x.Id).ToList(); var userNum = userCtnNumList.Where(x => temp1.Contains(x.SLOT_ALLOC_ID)).Sum(x => x.CTNNUM); var hasNum = hasCtnNumList.Where(x => x.SLOT_ID == slotId).Sum(x => x.CTNNUM); if (userNum >= hasNum) { useNum++; } } // 已使用舱位数 stockObj.USE_NUM = useNum; // 已使用的箱型箱量 var userCtnList = await _repAllocCtn.AsQueryable() .Filter(null, true) .Where(x => !x.IsDeleted && allocIdList.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; } if (isInsert) { await _repStock.InsertAsync(stockObj); } else { 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; } /// /// 装货港代码 /// public string PORTLOADID { get; set; } /// /// 卸货港代码 /// public string PORTDISCHARGEID { get; set; } /// /// 租户Id /// public long? TenantId { get; set; } } }