using Admin.NET.Application.Entity;
using Admin.NET.Application.Service.WmsStockSnapshot.Dto;
using Admin.NET.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Admin.NET.Application;
///
/// 库存快照
///
[ApiDescriptionSettings(ApplicationConst.WmsStockSnapshotDetailsGroupName, Order = 100)]
public class WmsStockSnapshotService : IDynamicApiController, ITransient
{
private readonly SqlSugarRepository _v_wms_stock_quanrRep;
private readonly SqlSugarRepository _wmsStockSnapshotRep;
private readonly SqlSugarRepository _wmsStockSnapshotDetails;
private readonly SqlSugarRepository _wmsStockSnapshotGroupRep;
private readonly SqlSugarRepository _repWmsRecordTrans;
private readonly SqlSugarRepository _wmsLogActionRep;
private readonly SqlSugarRepository _wmsRecordTransRep;
///
/// 构造函数
///
public WmsStockSnapshotService(SqlSugarRepository v_wms_stock_quanrRep,
SqlSugarRepository wmsStockSnapshotRep,
SqlSugarRepository wmsStockSnapshotDetails,
SqlSugarRepository wmsLogActionRep,
SqlSugarRepository wmsRecordTransRep, SqlSugarRepository wmsStockSnapshotGroupRep, SqlSugarRepository repWmsRecordTrans)
{
_wmsStockSnapshotGroupRep = wmsStockSnapshotGroupRep;
this._v_wms_stock_quanrRep = v_wms_stock_quanrRep;
this._wmsStockSnapshotRep = wmsStockSnapshotRep;
this._wmsStockSnapshotDetails = wmsStockSnapshotDetails;
this._wmsLogActionRep = wmsLogActionRep;
this._wmsRecordTransRep = wmsRecordTransRep;
_repWmsRecordTrans = repWmsRecordTrans;
}
///
/// 获取库存快照分页
///
///
[HttpGet]
[ApiDescriptionSettings(Name = "GetStockSnapshotPage", Description = "获取库存快照分页")]
[Description("/WmsStockSnapshot/GetStockSnapshotPage")]
public async Task GetStockSnapshotPage()
{
}
///
/// 添加库存快照
///
///
[HttpPost]
[ApiDescriptionSettings(Name = "CreateStockSnapshot", Description = "添加库存快照")]
[Description("/WmsStockSnapshot/CreateStockSnapshot")]
public async Task CreateStockSnapshot()
{
//获取当前库存
var stockQuanList = await _v_wms_stock_quanrRep.GetListAsync();
// 格式化为年月日字符串
string formattedDate = DateTime.Now.ToString("yyyyMMdd");
//查询当天是否有快照单号
var wmsStockSnapshot = await _wmsStockSnapshotRep.GetFirstAsync(u => u.SnapshotNo == "KZ" + formattedDate);
var stockSnapshotDetailsList = new List();
if (wmsStockSnapshot == null)
{
var isExist = false;
var Id = Yitter.IdGenerator.YitIdHelper.NextId();
var WmsStockSnapshot = new WmsStockSnapshot
{
Id = Id,
SnapshotDate = formattedDate,
SnapshotNo = "KZ" + formattedDate,
Remark = formattedDate + "以执行"
};
isExist = await _wmsStockSnapshotRep.IsAnyAsync(x => x.SnapshotDate == formattedDate);
if (!isExist)
{
foreach (var kvp in stockQuanList)
{
var stockSnapshotDetails = kvp.Adapt();
stockSnapshotDetails.SnapshotId = Id;
stockSnapshotDetails.Id = Yitter.IdGenerator.YitIdHelper.NextId();
stockSnapshotDetails.CreateTime = DateTime.Now;
stockSnapshotDetails.UpdateTime = null;
stockSnapshotDetails.SnapshotDate = formattedDate;
if (stockSnapshotDetails.SourceSNCode == null)
{
stockSnapshotDetails.SourceSNCode = "";
}
stockSnapshotDetailsList.Add(stockSnapshotDetails);
}
}
isExist = await _wmsStockSnapshotGroupRep.IsAnyAsync(x => x.SnapshotDate == formattedDate);
List addWmsStockSnapshotGroupList = new List();
if (!isExist)
{
//物料、库区分组
var stockQuanGroupList = stockQuanList.GroupBy(x => new { x.MaterialCode, x.MaterialName, x.AreaCode, x.AreaName, x.MaterialUnit }).Select(x => new
{
x.Key.MaterialCode,
x.Key.MaterialName,
x.Key.AreaCode,
x.Key.AreaName,
x.Key.MaterialUnit,
Quantity = x.Sum(s => s.Quantity)
}).ToList();
//汇总表
foreach (var item in stockQuanGroupList)
{
//快照汇总只记录有数量大于0且库区不为空的数据
if (item.Quantity > 0 && !string.IsNullOrWhiteSpace(item.AreaCode))
{
addWmsStockSnapshotGroupList.Add(new WmsStockSnapshotGroup()
{
Id = Yitter.IdGenerator.YitIdHelper.NextId(),
SnapshotId = Id,
SnapshotDate = formattedDate,
MaterialCode = item.MaterialCode,
MaterialName = item.MaterialName,
MaterialUnit = item.MaterialUnit??"",
AreaCode = item.AreaCode,
AreaName = item.AreaName,
Quantity = item.Quantity
});
}
}
}
var _tenant = _wmsStockSnapshotDetails.AsTenant();
try
{
await _wmsStockSnapshotRep.InsertAsync(WmsStockSnapshot);
await _wmsStockSnapshotDetails.InsertRangeAsync(stockSnapshotDetailsList);
await _wmsStockSnapshotGroupRep.InsertRangeAsync(addWmsStockSnapshotGroupList);
await _tenant.CommitTranAsync();
}
catch
{
await _tenant.RollbackTranAsync();
throw;
}
}
}
///
/// 历史库存查询
///
///
///
[HttpGet]
[ApiDescriptionSettings(Name = "HistorialStockPage", Description = "历史库存查询")]
[Description("/WmsStockSnapshot/HistorialStockPage")]
public async Task> HistorialStockPage([FromQuery] HistoricalStockQuery input)
{
// 要计算 A库区的某个时间点的库存
//--第一步:查询库存快照表的最近一个时间点的库存 CurQty
//--第二步:查询来源库区 = A的,变更数量 -= 源数量,库存 = CurQty - 变更数量
//-- 第三步:查询目标库区 = A的,变更数量 += 目标数量,库存 = CurQty + 变更数量
//更具输入时间查询第一条快照,然后根据SnapshotId快照ID查询到最近一段时间的快照列表
//var StockSnapshotModel = await _wmsStockSnapshotDetails.AsQueryable()
// .WhereIF(!string.IsNullOrWhiteSpace(input.BegineTime.ToString()), p => p.CreateTime < input.BegineTime)
// .WhereIF(!string.IsNullOrWhiteSpace(input.AreaCode), p => p.AreaCode.Contains(input.AreaCode))
// .WhereIF(!string.IsNullOrWhiteSpace(input.MaterialCode), p => p.MaterialCode.Contains(input.MaterialCode))
// .OrderByDescending(p => p.CreateTime)
// .FirstAsync();
//if (StockSnapshotModel == null)
//{
// return new SqlSugarPagedList() { };
//}
if (input.SearchKey == null && input.MaterialCode == null && input.SnapshotId == null && input.AreaCode == null && input.BegineTime.ToString() == "0001/1/1 0:00:00" )
{
return new SqlSugarPagedList() { };
}
//
var newStockSnapshotList = new List();
//var StockSnapshotList = await _wmsStockSnapshotDetails.AsQueryable()
// .WhereIF(!string.IsNullOrWhiteSpace(StockSnapshotModel.SnapshotId.ToString()),p => p.SnapshotId == StockSnapshotModel.SnapshotId)
// .WhereIF(!string.IsNullOrWhiteSpace(input.AreaCode), p => p.AreaCode.Contains(input.AreaCode))
// .WhereIF(!string.IsNullOrWhiteSpace(input.MaterialCode), p => p.MaterialCode.Contains(input.MaterialCode))
// .ToListAsync();
var HistoricalStockList = new List();
DateTime? searchDateTime = null;//选择的时间点
if (input.BegineTime.ToString() != "0001/1/1 0:00:00")
{
searchDateTime = Convert.ToDateTime(input.BegineTime);
};
//如果有时间参数 查询当天的快照汇总信息
var allStockSnapshotList = await _wmsStockSnapshotGroupRep.AsQueryable()
.WhereIF(!string.IsNullOrWhiteSpace(input.SearchKey), u =>
u.AreaCode.Contains(input.SearchKey.Trim())
|| u.MaterialCode.Contains(input.SearchKey.Trim())
)
// .WhereIF(searchDateTime!=null, p => p.SnapshotDate<= searchDateTime)
.WhereIF(searchDateTime != null, p => p.CreateTime <= searchDateTime)
.WhereIF(!string.IsNullOrWhiteSpace(input.AreaCode), p => p.AreaCode.Contains(input.AreaCode))
.WhereIF(!string.IsNullOrWhiteSpace(input.MaterialCode), p => p.MaterialCode.Contains(input.MaterialCode))
.WhereIF(input.SnapshotId > 0, p => p.SnapshotId == input.SnapshotId) //ly0813-库存快照明细页面用
.OrderByDescending(p => p.SnapshotDate)
.ToListAsync();
if (allStockSnapshotList.Count()==0) throw Oops.Oh("未找到库存快照");
//获取最接近当前查询时间点的快照日期
var recentlyStockSnapshot = allStockSnapshotList.OrderByDescending(p => p.CreateTime).FirstOrDefault();
//当前最近的库存快照
var currentStockSnapshotList = allStockSnapshotList
.Where( p => p.SnapshotDate == recentlyStockSnapshot.SnapshotDate)
.ToList();
//var wmsRecordTransList = await _repWmsRecordTrans.AsQueryable()
// .WhereIF(!string.IsNullOrWhiteSpace(input.BegineTime.ToString()),p => p.CreateTime >= TimeModel && p.CreateTime <= input.BegineTime)
// .WhereIF(!string.IsNullOrWhiteSpace(input.MaterialCode), p => p.MaterialCode == input.MaterialCode)
// .WhereIF(!string.IsNullOrWhiteSpace(input.AreaCode),p => p.ToAreaCode == input.AreaCode)
// .ToListAsync();
//如果有时间参数 查询快照当天凌晨开始到选择的时间点的事务
DateTime startSearchDateTime= Convert.ToDateTime(recentlyStockSnapshot.CreateTime);
DateTime? endSearchDateTime = searchDateTime;//选择的时间点
var wmsRecordTransList = await _repWmsRecordTrans.AsQueryable()
.Where(u=>u.SourceAreaCode != u.ToAreaCode)
.WhereIF(searchDateTime != null, p => p.CreateTime>= startSearchDateTime && p.CreateTime <= endSearchDateTime)
.WhereIF(!string.IsNullOrWhiteSpace(input.SearchKey), u =>
u.ToAreaCode.Contains(input.SearchKey.Trim())
|| u.SourceAreaCode.Contains(input.SearchKey.Trim())
|| u.MaterialCode.Contains(input.SearchKey.Trim())
)
.WhereIF(!string.IsNullOrWhiteSpace(input.MaterialCode), p => p.MaterialCode == input.MaterialCode)
.WhereIF(!string.IsNullOrWhiteSpace(input.AreaCode), p => p.ToAreaCode == input.AreaCode|| p.SourceAreaCode == input.AreaCode)
.ToListAsync();
//初始化事务记录中存在但是库存快照没有的物料信息,库存为0
var allStockSnapshotMaterialCodeList = allStockSnapshotList.Select(p => p.MaterialCode+p.AreaCode).Distinct().ToList();
//目标库区
var toAreaRecordTransMaterialList = wmsRecordTransList.Select(s=>new WmsStockSnapshotGroup() {
MaterialCode = s.MaterialCode,
MaterialName = s.MaterialName,
MaterialUnit = s.MaterialUnit,
Quantity = 0,
AreaCode = s.ToAreaCode,
AreaName= s.ToAreaName
}).Where(w=>!allStockSnapshotMaterialCodeList.Contains(w.MaterialCode+w.AreaCode)).ToList();
currentStockSnapshotList.AddRange(toAreaRecordTransMaterialList);
//来源库区
var sourceAreaRecordTransMaterialList = wmsRecordTransList.Select(s => new WmsStockSnapshotGroup()
{
MaterialCode = s.MaterialCode,
MaterialName = s.MaterialName,
MaterialUnit = s.MaterialUnit,
Quantity = 0,
AreaCode = s.SourceAreaCode,
AreaName = s.SourceAreaName
}).Where(w => !allStockSnapshotMaterialCodeList.Contains(w.MaterialCode+w.AreaCode)).ToList();
currentStockSnapshotList.AddRange(sourceAreaRecordTransMaterialList);
//循环快照库存,根据事务增减库存
foreach (var item in currentStockSnapshotList)
{
//--第二步:查询来源库区 = A的,变更数量 -= 源数量,库存 = CurQty - 变更数量
//来源库区等于库存的库区,目标库区不等于源库区的,表示是减库存
var sourceRecordTrans = wmsRecordTransList.Where( p => p.SourceAreaCode == item.AreaCode&&p.SourceAreaCode!=p.ToAreaCode && p.MaterialCode == item.MaterialCode).ToList();
//汇总扣减库存数
// var removeQty = sourceRecordTrans.Sum(p => p.ChangeQuantity);
var removeQty = sourceRecordTrans.Sum(p => p.ToQuantity);
item.Quantity-= (decimal)removeQty;
//-- 第三步:查询目标库区 = A的,变更数量 += 目标数量,库存 = CurQty + 变更数量
//目标库区等于库存的库区,目标库区不等于源库区的,表示是加库存
var toRecordTrans = wmsRecordTransList.Where(p => p.ToAreaCode == item.AreaCode && p.SourceAreaCode != p.ToAreaCode && p.MaterialCode == item.MaterialCode).ToList();
//汇总加库存数
// var addQty = toRecordTrans.Sum(p => p.ChangeQuantity);
var addQty = toRecordTrans.Sum(p => p.ToQuantity);
item.Quantity += (decimal)addQty;
var historicalStockModel = new HistoricalInventory()
{
MaterialCode = item.MaterialCode,
MaterialName = item.MaterialName,
MaterialUnit = item.MaterialUnit,
Quantity = item.Quantity,
AreaCode = item.AreaCode,
AreaName = item.AreaName,
};
HistoricalStockList.Add(historicalStockModel);
}
return HistoricalStockList.ToPagedList(input.Page, input.PageSize);
//foreach (var item in wmsRecordTransList)
//{
// //查询原来库区的库存快照,找到后进行对应库存数的增删
// var SourceAreaStock = StockSnapshotList.WhereIF(!string.IsNullOrWhiteSpace(item.SourceAreaCode), p => p.AreaCode == item.SourceAreaCode && p.MaterialCode == item.MaterialCode).FirstOrDefault();
// if (SourceAreaStock != null)
// {
// SourceAreaStock.Quantity = (decimal)(SourceAreaStock.Quantity - item.SourceQuantity);
// int index = StockSnapshotList.FindIndex(p => p.Id == SourceAreaStock.Id);
// StockSnapshotList[index] = SourceAreaStock;
// }
// var ToAreaStock = StockSnapshotList.WhereIF(!string.IsNullOrWhiteSpace(item.ToAreaCode), p => p.AreaCode == item.ToAreaCode && p.MaterialCode == item.MaterialCode).FirstOrDefault();
// //查询后续目标库区的库存快照,找到后进行库存的修改
// if (ToAreaStock != null)
// {
// ToAreaStock.Quantity = (decimal)(ToAreaStock.Quantity + item.SourceQuantity);
// int index = StockSnapshotList.FindIndex(p => p.Id == ToAreaStock.Id);
// StockSnapshotList[index] = ToAreaStock;
// }
//}
//var HistoricalStockList = new List();
//foreach(var item in StockSnapshotList)
//{
// var historicalStockModel = new HistoricalInventory()
// {
// MaterialCode = item.MaterialCode,
// MaterialName = item.MaterialName,
// MaterialUnit = item.MaterialUnit,
// Quantity = item.Quantity,
// AreaCode = item.AreaCode,
// AreaName = item.AreaName,
// };
// HistoricalStockList.Add(historicalStockModel);
//}
//var returnInfo = StockSnapshotList.GroupBy(p => p.AreaCode) // 根据 A 字段进行分组
// .Select(g => new HistoricalInventory()
// {
// AreaCode = g.Key, // 分组的键,即 A 字段的值
// AreaName =
// = g.Sum(s => s.Number) // 计算每组中 Number 字段的总和
// });
//return HistoricalStockList.ToPagedList(input.Page, input.PageSize);
}
///
/// 分页查询库存快照
///
///
///
[HttpPost]
[ApiDescriptionSettings(Name = "Page")]
[Description("WmsStockSnapshot/Page")]
public async Task> Page(WmsStockSnapshotInput input)
{
var query = CommonPageFilter(input);
return await query.OrderBuilder(input, "", "SnapshotDate").ToPagedListAsync(input.Page, input.PageSize);
}
#region 私有方法
///
/// 公共查询库存快照条件
///
///
///
private ISugarQueryable CommonPageFilter(WmsStockSnapshotInput input)
{
var query = _wmsStockSnapshotRep.AsQueryable()
.WhereIF(!string.IsNullOrWhiteSpace(input.SearchKey), u =>
u.SnapshotNo.Contains(input.SearchKey.Trim())
|| u.Remark.Contains(input.SearchKey.Trim())
|| u.CreateUserName.Contains(input.SearchKey.Trim())
|| u.UpdateUserName.Contains(input.SearchKey.Trim())
|| u.SnapshotDate.Contains(input.SearchKey.Trim())
)
.WhereIF(!string.IsNullOrWhiteSpace(input.SnapshotNo), u => u.SnapshotNo.Contains(input.SnapshotNo.Trim()))
.WhereIF(!string.IsNullOrWhiteSpace(input.SnapshotDate), u => u.SnapshotDate.Contains(input.SnapshotDate.Trim()))
.Select();
return query;
}
///
/// 重复性验证
///
/// 验证对象
/// 是否是编辑
///
private async Task CheckExist(WmsStockSnapshot input, bool isEdit = false)
{
//没有配置组合校验,不需要验重
//没有配置单独校验,不需要验重
}
///
/// 根据组合校验和单独校验验证数据是否已存在-导入时验证
///
///
///
private async Task CheckExisitForImport(List inputs)
{
if (inputs?.Count <= 0)
{
throw Oops.Oh($"导入数据不能为空");
}
//根据组合校验验证表格中中是否已存在相同数据
//根据单独校验验证表格中中是否已存在相同数据
}
#endregion
}