diff --git a/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs b/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs
index 497b8e6a..30d621bf 100644
--- a/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs
+++ b/Myshipping.Application/Service/BookingSlot/BookingSlotService.cs
@@ -226,6 +226,96 @@ namespace Myshipping.Application
//更新库存
await _publisher.PublishAsync(new ChannelEventSource("BookingSlotStock:Update", input));
}
+
+ ///
+ /// 查询可用的舱位及箱子
+ ///
+ [HttpGet("/BookingSlot/getAvailableSlots")]
+ public async Task> GetAvailableSlots([FromQuery] BookingSlotBaseDto input)
+ {
+ string[] ctnCodeList = null;
+ if (!string.IsNullOrEmpty(input.CTN_STAT))
+ {
+ ctnCodeList = input.CTN_STAT.Split(',');
+ }
+
+ // 1. 【舱位基础表】与【箱子表】做关联,并根据【舱位主键】、【箱型】做分组,统计出【总的箱量】,作为queryable1
+ var queryable1 = _repBase.Context.Queryable((bas, ctn) => bas.Id == ctn.SLOT_ID)
+ .WhereIF(!string.IsNullOrEmpty(input.PORTLOAD), bas => bas.PORTLOAD.Contains(input.PORTLOAD))
+ .WhereIF(!string.IsNullOrEmpty(input.PORTDISCHARGE), bas => bas.PORTLOAD.Contains(input.PORTLOAD))
+ .WhereIF(!string.IsNullOrEmpty(input.VESSEL), bas => bas.VESSEL.Contains(input.VESSEL))
+ .WhereIF(!string.IsNullOrEmpty(input.VOYNO), bas => bas.VOYNO.Contains(input.VOYNO))
+ .WhereIF(!string.IsNullOrEmpty(input.CARRIAGE_TYPE), bas => bas.CARRIAGE_TYPE == input.CARRIAGE_TYPE)
+ .WhereIF(!string.IsNullOrEmpty(input.BOOKING_SLOT_TYPE), bas => bas.BOOKING_SLOT_TYPE == input.BOOKING_SLOT_TYPE)
+ .WhereIF(ctnCodeList != null, (bas, ctn) => ctnCodeList.Contains(ctn.CTNCODE))
+ .GroupBy((bas, ctn) => new
+ {
+ bas.Id,
+ ctn.CTNCODE
+ })
+ .Select((bas, ctn) => new
+ {
+ id = bas.Id,
+ ctnCode = ctn.CTNCODE,
+ numAll = SqlFunc.AggregateSum(ctn.CTNNUM)
+ })
+ .MergeTable();
+
+ // 2. 【已引入舱位表】与【已使用的箱子表】做关联,并根据【舱位主键】、【箱型】做分组,统计出【已使用的箱量】,作为queryable2
+ var queryable2 = _repBase.Context.Queryable((alc, ctn) => alc.Id == ctn.SLOT_ALLOC_ID)
+ .GroupBy((alc, ctn) => new
+ {
+ alc.BOOKING_SLOT_ID,
+ ctn.CTNCODE
+ })
+ .Select((alc, ctn) => new
+ {
+ id = alc.BOOKING_SLOT_ID,
+ ctnCode = ctn.CTNCODE,
+ numUse = SqlFunc.AggregateSum(ctn.CTNNUM)
+ })
+ .MergeTable();
+
+ // 3. 将queryable1 左连接 queryable2,使用【总的箱量】减去【已使用的箱量】,得到【剩余的箱量】,添加【剩余的箱量】> 0 的条件,作为queryable3
+ var queryable3 = queryable1.LeftJoin(queryable2, (q1, q2) => q1.id == q2.id && q1.ctnCode == q2.ctnCode)
+ .Select((q1, q2) => new
+ {
+ q1.id,
+ q1.ctnCode,
+ numResidue = SqlFunc.IsNull(q1.numAll - q2.numUse, q1.numAll)
+ })
+ .MergeTable()
+ .Where(r => r.numResidue > 0);
+
+ // 4. 执行ToList(),得到可用的【舱位主键】、【箱型】、【箱量】列表
+ var canUselist = await queryable3.ToListAsync();
+
+ // 查询舱位列表
+ var baseIdList = canUselist.Select(c => c.id);
+ List baseList = await _repBase.AsQueryable()
+ .Where(u => baseIdList.Contains(u.Id))
+ .ToListAsync();
+
+ List ctnCodeCache = await _cache.GetAllCodeCtn();
+
+ // 构建结果
+ List result = baseList.Adapt>();
+ foreach (var item in result)
+ {
+ var ctnList = canUselist.Where(c => c.id == item.Id).ToList();
+ if (ctnList?.Any() == true)
+ {
+ item.CtnList = ctnList.Select(c => new BookingSlotCtnDto()
+ {
+ CTNCODE = c.ctnCode,
+ CTNNUM = c.numResidue,
+ CTNALL = ctnCodeCache.FirstOrDefault(e => e.Code == c.ctnCode)?.Name ?? throw new Exception($"舱位信息中存在未收录的箱型:{c.ctnCode},需要在箱型字典中补充"),
+ }).ToList();
+ }
+ }
+
+ return result;
+ }
#endregion
}
}
diff --git a/Myshipping.Application/Service/BookingSlot/Dto/BookingSlotBaseDto.cs b/Myshipping.Application/Service/BookingSlot/Dto/BookingSlotBaseDto.cs
index 96117f33..fc87d325 100644
--- a/Myshipping.Application/Service/BookingSlot/Dto/BookingSlotBaseDto.cs
+++ b/Myshipping.Application/Service/BookingSlot/Dto/BookingSlotBaseDto.cs
@@ -298,4 +298,15 @@ namespace Myshipping.Application.Service.BookingSlot.Dto
///
public string UpdatedUserName { get; set; }
}
+
+ ///
+ /// 查询可用舱位信息Dto
+ ///
+ public class BookingSlotAvailableDto: BookingSlotBaseDto
+ {
+ ///
+ /// 舱位箱信息
+ ///
+ public List CtnList { get; set; }
+ }
}