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
{
///
/// 舱位库存
///
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();
///
///
///
///
public BookingSlotStockService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
db = _serviceProvider.GetRequiredService();
user = _serviceProvider.GetRequiredService();
saasService = _serviceProvider.GetRequiredService();
}
#region 计算舱位库存
///
/// 计算舱位库存
///
/// 请求参数
/// 返回回执
public async Task> 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.FailedData(string.Empty);
}
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var baseList = await tenantDb.Queryable()
.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()
.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(stockObj).ExecuteCommandAsync();
}
return DataResult.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()
.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()
//.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().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().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 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()
.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 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(stockObj).ExecuteCommandAsync();
}
else
{
await tenantDb.Updateable(stockObj).ExecuteCommandAsync();
}
return DataResult.Success(string.Empty);
}
#endregion
#region 重新计算某租户下面所有的库存
///
/// 重新计算某租户下面所有的库存
///
///
public async Task RefreshAllStock()
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var n = await tenantDb.Deleteable().ExecuteCommandAsync();
var group = await tenantDb.Queryable()
.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
}
}