You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
13 KiB
C#
306 lines
13 KiB
C#
using DS.Module.Core;
|
|
using DS.Module.SqlSugar;
|
|
using DS.Module.UserModule;
|
|
using DS.WMS.Core.Op.Dtos;
|
|
using DS.WMS.Core.Op.Entity;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Newtonsoft.Json;
|
|
using NLog;
|
|
using SqlSugar;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Mapster;
|
|
using DS.WMS.Core.Op.Interface;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace DS.WMS.Core.Op.Method
|
|
{
|
|
/// <summary>
|
|
/// 舱位库存
|
|
/// </summary>
|
|
public class BookingSlotStockService: IBookingSlotStockService
|
|
{
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly ISqlSugarClient db;
|
|
private readonly IUser user;
|
|
private readonly ISaasDbService saasService;
|
|
|
|
private static readonly NLog.Logger Logger = LogManager.GetCurrentClassLogger();
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="serviceProvider"></param>
|
|
public BookingSlotStockService(IServiceProvider serviceProvider)
|
|
{
|
|
_serviceProvider = serviceProvider;
|
|
db = _serviceProvider.GetRequiredService<ISqlSugarClient>();
|
|
user = _serviceProvider.GetRequiredService<IUser>();
|
|
saasService = _serviceProvider.GetRequiredService<ISaasDbService>();
|
|
}
|
|
|
|
#region 计算舱位库存
|
|
/// <summary>
|
|
/// 计算舱位库存
|
|
/// </summary>
|
|
/// <param name="paraObj">请求参数</param>
|
|
/// <returns>返回回执</returns>
|
|
public async Task<DataResult<string>> BookingSlotStock(BookingSlotStockUpdateModel paraObj)
|
|
{
|
|
Logger.Log(NLog.LogLevel.Info, $"收到更新库存订阅请求:{ JsonConvert.SerializeObject(paraObj)}");
|
|
|
|
if (string.IsNullOrEmpty(paraObj.Vessel)
|
|
|| string.IsNullOrEmpty(paraObj.Voyno)
|
|
|| string.IsNullOrEmpty(paraObj.ContractNo)
|
|
|| string.IsNullOrEmpty(paraObj.BookingSlotType)
|
|
|| string.IsNullOrEmpty(paraObj.CarrierCode)
|
|
|| string.IsNullOrEmpty(paraObj.PortLoadId)
|
|
|| string.IsNullOrEmpty(paraObj.PortDischargeId))
|
|
{
|
|
Logger.Log(NLog.LogLevel.Info, $"收到更新库存订阅请求:部分参数存在空值,结束");
|
|
return DataResult<string>.FailedData(string.Empty);
|
|
}
|
|
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
var baseList = await tenantDb.Queryable<BookingSlotBase>()
|
|
.Where(x => !x.Deleted
|
|
//&& x.TenantId == paraObj.TenantId
|
|
&& x.Vessel == paraObj.Vessel
|
|
&& x.Voyno == paraObj.Voyno
|
|
&& x.ContractNo == paraObj.ContractNo
|
|
&& x.BookingSlotType == paraObj.BookingSlotType
|
|
&& x.CarrierCode == paraObj.CarrierCode
|
|
&& x.PortLoadCode == paraObj.PortLoadId
|
|
&& x.PortDischargeCode == paraObj.PortDischargeId)
|
|
.OrderByDescending(x => x.UpdateTime)
|
|
.ToListAsync();
|
|
|
|
var stockObj = await tenantDb.Queryable<BookingSlotStock>()
|
|
.FirstAsync(x => !x.Deleted
|
|
//&& x.TenantId == paraObj.TenantId
|
|
&& x.Vessel == paraObj.Vessel
|
|
&& x.Voyno == paraObj.Voyno
|
|
&& x.ContractNo == paraObj.ContractNo
|
|
&& x.BookingSlotType == paraObj.BookingSlotType
|
|
&& x.CarrierCode == paraObj.CarrierCode
|
|
&& x.PortLoadId == paraObj.PortLoadId
|
|
&& x.PortDischargeId == paraObj.PortDischargeId);
|
|
|
|
if (!baseList.Any())
|
|
{
|
|
if (stockObj != null)
|
|
{
|
|
// 从库存表删除这7项维度的库存数据
|
|
await tenantDb.Deleteable<BookingSlotStock>(stockObj).ExecuteCommandAsync();
|
|
}
|
|
|
|
return DataResult<string>.FailedData(string.Empty);
|
|
}
|
|
|
|
var isInsert = stockObj == null;
|
|
var idTemp = stockObj?.Id;
|
|
|
|
stockObj = baseList[0].Adapt(stockObj);
|
|
|
|
if (isInsert)
|
|
{
|
|
stockObj.Id = 0;
|
|
}
|
|
else
|
|
{
|
|
stockObj.Id = (long)idTemp;
|
|
}
|
|
|
|
stockObj.PortLoadId = baseList[0].PortLoadCode;
|
|
stockObj.PortDischargeId = baseList[0].PortDischargeCode;
|
|
|
|
// 总舱位数
|
|
stockObj.TotalOrders = baseList.Count;
|
|
|
|
// 取消舱位数
|
|
stockObj.CancelNum = baseList.Count(x => x.IsCancellation);
|
|
|
|
// 舱位主键列表
|
|
var slotBaseIdList = baseList.Select(x => x.Id).ToList();
|
|
|
|
// 总的箱型箱量
|
|
var ctnAllList = await tenantDb.Queryable<BookingSlotCtn>()
|
|
.Where(x => !x.Deleted && slotBaseIdList.Contains(x.SlotId))
|
|
.GroupBy(x => x.CtnAll)
|
|
.Select(x => new
|
|
{
|
|
x.CtnAll,
|
|
CTNNUM = SqlFunc.AggregateSum(x.CtnNum)
|
|
}).ToListAsync();
|
|
stockObj.CtnStat = string.Join(' ', ctnAllList.Select(c => c.CtnAll + "*" + c.CTNNUM));
|
|
|
|
// 总箱数
|
|
stockObj.TotalCtns = ctnAllList.Sum(x => x.CTNNUM);
|
|
|
|
// 订舱引用表主键与订舱主表主键
|
|
var lstAllocKeyList = await tenantDb.Queryable<BookingSlotAllocation>()
|
|
//.Filter(null, true)
|
|
.Where(x => !x.Deleted && slotBaseIdList.Contains(x.BookingSlotId))
|
|
.Select(x => new { x.Id, x.BookingSlotId })
|
|
.ToListAsync();
|
|
|
|
// 如果舱位未被引用过,可以直接确定库存
|
|
if (!lstAllocKeyList.Any())
|
|
{
|
|
// 已使用舱位数
|
|
stockObj.UseNum = 0;
|
|
// 已使用的箱型箱量
|
|
stockObj.UseCtnStat = "";
|
|
// 已使用的箱数
|
|
stockObj.UseCtnsNum = 0;
|
|
|
|
// 剩余的箱型箱量
|
|
stockObj.RemainCtnStat = stockObj.CtnStat;
|
|
// 剩余箱数
|
|
stockObj.RemainCtnsNum = stockObj.TotalCtns;
|
|
}
|
|
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.BookingSlotId).Distinct().ToList();
|
|
var userCtnNumList = await tenantDb.Queryable<BookingSlotAllocationCtn>().Filter(null, true)
|
|
.Where(x => !x.Deleted && allocIdList.Contains(x.SlotAllocId))
|
|
.GroupBy(x => x.SlotAllocId)
|
|
.Select(x => new
|
|
{
|
|
x.SlotAllocId,
|
|
CTNNUM = SqlFunc.AggregateSum(x.CtnNum)
|
|
}).ToListAsync();
|
|
var hasCtnNumList = await tenantDb.Queryable<BookingSlotCtn>().Filter(null, true)
|
|
.Where(x => !x.Deleted && allocSlotIdList.Contains(x.SlotId))
|
|
.GroupBy(x => x.SlotId)
|
|
.Select(x => new
|
|
{
|
|
x.SlotId,
|
|
CTNNUM = SqlFunc.AggregateSum(x.CtnNum)
|
|
})
|
|
.ToListAsync();
|
|
var useNum = 0;
|
|
foreach (long slotId in allocSlotIdList)
|
|
{
|
|
List<long> temp1 = lstAllocKeyList.Where(x => x.BookingSlotId == slotId).Select(x => x.Id).ToList();
|
|
var userNum = userCtnNumList.Where(x => temp1.Contains(x.SlotAllocId)).Sum(x => x.CTNNUM);
|
|
var hasNum = hasCtnNumList.Where(x => x.SlotId == slotId).Sum(x => x.CTNNUM);
|
|
if (userNum >= hasNum)
|
|
{
|
|
useNum++;
|
|
}
|
|
}
|
|
// 已使用舱位数
|
|
stockObj.UseNum = useNum;
|
|
|
|
// 已使用的箱型箱量
|
|
var userCtnList = await tenantDb.Queryable<BookingSlotAllocationCtn>()
|
|
.Filter(null, true)
|
|
.Where(x => !x.Deleted && allocIdList.Contains(x.SlotAllocId))
|
|
.GroupBy(x => x.CtnAll)
|
|
.Select(x => new
|
|
{
|
|
x.CtnAll,
|
|
CTNNUM = SqlFunc.AggregateSum(x.CtnNum)
|
|
}).ToListAsync();
|
|
stockObj.UseCtnStat = string.Join(' ', userCtnList.Select(c => c.CtnAll + "*" + c.CTNNUM));
|
|
|
|
// 已使用的箱数
|
|
stockObj.UseCtnsNum = userCtnList.Sum(x => x.CTNNUM);
|
|
|
|
// 剩余的箱型箱量
|
|
Dictionary<string, int> 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.RemainCtnStat = string.Join(' ', remainCtnList.Select(x => x.Key + "*" + x.Value));
|
|
|
|
// 剩余箱数
|
|
stockObj.RemainCtnsNum = stockObj.TotalCtns - stockObj.UseCtnsNum;
|
|
}
|
|
|
|
if (isInsert)
|
|
{
|
|
await tenantDb.Insertable<BookingSlotStock>(stockObj).ExecuteCommandAsync();
|
|
}
|
|
else
|
|
{
|
|
await tenantDb.Updateable<BookingSlotStock>(stockObj).ExecuteCommandAsync();
|
|
}
|
|
|
|
return DataResult<string>.Success(string.Empty);
|
|
}
|
|
#endregion
|
|
|
|
#region 重新计算某租户下面所有的库存
|
|
/// <summary>
|
|
/// 重新计算某租户下面所有的库存
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task RefreshAllStock()
|
|
{
|
|
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
|
|
|
|
var n = await tenantDb.Deleteable<BookingSlotStock>().ExecuteCommandAsync();
|
|
|
|
var group = await tenantDb.Queryable<BookingSlotBase>()
|
|
.Where(x => x.Deleted == false)
|
|
.GroupBy(x => new
|
|
{
|
|
x.Vessel,
|
|
x.Voyno,
|
|
x.CarrierCode,
|
|
x.ContractNo,
|
|
x.BookingSlotType,
|
|
x.PortLoadCode,
|
|
x.PortDischargeCode,
|
|
}).Select(x => new
|
|
{
|
|
x.Vessel,
|
|
x.Voyno,
|
|
x.CarrierCode,
|
|
x.ContractNo,
|
|
x.BookingSlotType,
|
|
x.PortLoadCode,
|
|
x.PortDischargeCode,
|
|
}).ToListAsync();
|
|
foreach (var item in group)
|
|
{
|
|
BookingSlotStockUpdateModel model = new BookingSlotStockUpdateModel {
|
|
Vessel = item.Vessel,
|
|
Voyno = item.Voyno,
|
|
CarrierCode = item.CarrierCode,
|
|
ContractNo = item.ContractNo,
|
|
BookingSlotType = item.BookingSlotType,
|
|
PortLoadId = item.PortLoadCode,
|
|
PortDischargeId = item.PortDischargeCode,
|
|
};
|
|
await BookingSlotStock(model);
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|