MRP修改

This commit is contained in:
杨晓东 2025-09-28 08:36:03 +08:00
parent aa2b0501a5
commit ba87992368

View File

@ -59,6 +59,8 @@ namespace DOAN.Service.MES.mm.paintedparts_call
.AndIF(parm.WorkOrderDate != null, it => it.WorkOrderDate == parm.WorkOrderDate)
.And(it => it.Quantity > 0);
var response = Queryable()
.OrderBy(m => m.MaterialCode) // 按预定义的物料号顺序
.OrderBy(m => m.LineCode)
.Where(predicate.ToExpression())
.ToPage<MmCallMrp, MmCallMrpDto>(parm);
@ -202,20 +204,49 @@ namespace DOAN.Service.MES.mm.paintedparts_call
.Queryable<ProWorkorder>()
.WhereIF(!string.IsNullOrEmpty(parm.LineCode) && !parm.LineCode.Contains("全部"), it => it.LineCode == parm.LineCode)
.Where(x => x.WorkorderDate == checkDate)
.Select(x => new { x.ProductionCode, x.DeliveryNum })
.Select(x => new { x.ProductionCode, x.DeliveryNum, x.LineCode })
.ToList();
List<string> lineProductionCodeList = workorders
.Select(x => x.ProductionCode)
.Distinct()
// 1. 按ProductionCode和LineCode分组并计算每个组的累加数量
var productionGroups = workorders
.GroupBy(x => new { x.ProductionCode, x.LineCode })
.Select(g => new
{
ProductionCode = g.Key.ProductionCode,
LineCode = g.Key.LineCode,
GroupTotal = g.Sum(x => x.DeliveryNum) ?? 0
})
.ToList();
if (!lineProductionCodeList.Any())
if (!productionGroups.Any())
{
Context.Ado.RollbackTran();
return 0;
//throw new Exception("未找到该线别对应的工单");
}
// 计算所有组的总数量
int totalQuantityAcrossAllGroups = productionGroups.Sum(g => g.GroupTotal);
if (totalQuantityAcrossAllGroups <= 0)
{
Context.Ado.RollbackTran();
return 0;
}
// 将总数量分成四份
int baseBatch = totalQuantityAcrossAllGroups / 4;
int remainder = totalQuantityAcrossAllGroups % 4;
int[] batchQuantities = new int[4];
for (int i = 0; i < 4; i++)
{
batchQuantities[i] = baseBatch + (i < remainder ? 1 : 0);
}
// 获取所有唯一的ProductionCode
List<string> lineProductionCodeList = productionGroups
.Select(x => x.ProductionCode)
.Distinct()
.ToList();
// 查询 BOM 表
List<MmCallMaterialBom> mmCallMaterialBoms = Context
.Queryable<MmCallMaterialBom>()
@ -223,58 +254,10 @@ namespace DOAN.Service.MES.mm.paintedparts_call
.Where(it => !string.IsNullOrEmpty(it.subInvCode))
.ToList();
// 计算每个 ProductionCode 的 DeliveryNum 总和
var totalDeliveryDict = workorders
.GroupBy(x => x.ProductionCode)
.ToDictionary(g => g.Key, g => g.Sum(x => x.DeliveryNum));
// 生成 MmCallRequests
List<MmCallMrp> mmCallMrpList = new();
//// 1. 按工单顺序排序 (假设按ProductionCode排序可根据实际需求调整)
//var sortedWorkorders = workorders.OrderBy(x => x.ProductionCode).ToList();
//// 2. 计算总交货量并拆分为四组
//int totalDeliveryNum = sortedWorkorders.Sum(x => x.DeliveryNum).Value;
//int groupTarget = totalDeliveryNum / 4;
//List<List<dynamic>> groups = new List<List<dynamic>>();
//List<dynamic> currentGroup = new List<dynamic>();
//int currentSum = 0;
//foreach (var wo in sortedWorkorders)
//{
// currentGroup.Add(wo);
// currentSum += wo.DeliveryNum.Value;
// if (currentSum >= groupTarget * (groups.Count + 1))
// {
// groups.Add(currentGroup);
// currentGroup = new List<dynamic>();
// currentSum = 0;
// }
//}
//// 处理剩余工单
//if (currentGroup.Any())
//{
// if (groups.Count < 4)
// {
// groups.Add(currentGroup);
// }
// else
// {
// groups[3].AddRange(currentGroup);
// }
//}
//// 确保有四组
//while (groups.Count < 4)
//{
// groups.Add(new List<dynamic>());
//}
// 3. 定义四个时间段
// 定义四个时间段
var timePeriods = new List<(DateTime Start, DateTime End)>
{
(checkDate.Date.AddHours(8), checkDate.Date.AddHours(10)), // 8:00~10:00
@ -283,89 +266,117 @@ namespace DOAN.Service.MES.mm.paintedparts_call
(checkDate.Date.AddHours(14), checkDate.Date.AddHours(16)) // 14:00~16:00
};
// 4. 分时段计算物料需求
foreach (var (startTime, endTime) in timePeriods)
// 4. 为每个时间段分配批次数量(核心修复部分)
foreach (var timePeriod in timePeriods.Select((tp, idx) => new { Period = tp, Index = idx }))
{
// 获取该组的ProductionCode列表并转换为HashSet以提高查找效率
// 显式指定泛型类型参数确保从dynamic转换为string
var groupProductionCodes = new HashSet<string>(lineProductionCodeList);
var (startTime, endTime) = timePeriod.Period;
int currentBatchIndex = timePeriod.Index;
int currentBatchQuantity = batchQuantities[currentBatchIndex];
//// 计算该组的DeliveryNum字典
//var groupDeliveryDict = group
// .GroupBy(x => x.ProductionCode)
// .ToDictionary(g => g.Key, g => g.Sum(x => x.DeliveryNum));
if (currentBatchQuantity <= 0)
continue;
// 按linecode与MaterialCode进行聚合统计
var aggregatedData = mmCallMaterialBoms
.Where(bom => groupProductionCodes.Contains(bom.InvCode))
.GroupBy(bom => new
{
bom.subInvCode,
bom.subInvName,
bom.InvCode,
bom.InvName
})
.Select(g => new
{
ProductionCode = g.Key.InvCode,
ProductionName = g.Key.InvName,
MaterialCode = g.Key.subInvCode,
MaterialName = g.Key.subInvName,
TotalQuantity = g.Sum(bom =>
{
int totalDeliveryNum = workorders
.Where(w => w.ProductionCode == bom.InvCode)
.Sum(w => w.DeliveryNum) ?? 0;
// 计算比例分配比例
decimal batchRatio = (decimal)currentBatchQuantity / totalQuantityAcrossAllGroups;
if (totalDeliveryNum <= 0)
{
return 0m; // 没有交货量则跳过
}
// 使用具体元组存储分配信息避免dynamic类型问题
var groupAllocations = new List<(string ProductionCode, string LineCode, int Allocated)>();
int itemIndex = 0;
decimal iusequantity;
if (!decimal.TryParse(bom.Iusequantity, out iusequantity))
{
Context.Ado.RollbackTran();
throw new Exception($"{bom.subInvCode}BOM使用数量异常");
}
return totalDeliveryNum * iusequantity;
})
})
.ToList();
// 生成该时间段的物料需求记录
foreach (var item in aggregatedData)
foreach (var group in productionGroups)
{
mmCallMrpList.Add(
new MmCallMrp
int allocated = itemIndex < productionGroups.Count - 1
? (int)Math.Round(group.GroupTotal * batchRatio)
: currentBatchQuantity - groupAllocations.Sum(a => a.Allocated);
groupAllocations.Add((group.ProductionCode, group.LineCode, allocated));
itemIndex++;
}
// 生成当前时间段的物料需求记录
foreach (var allocation in groupAllocations)
{
if (allocation.Allocated <= 0) continue;
// 获取BOM数据并计算需求
var relatedBoms = mmCallMaterialBoms
.Where(bom => bom.InvCode == allocation.ProductionCode)
.ToList();
var aggregatedData = relatedBoms
.GroupBy(bom => new { bom.subInvCode, bom.subInvName, bom.InvCode, bom.InvName })
.Select(g => new
{
ProductionCode = g.Key.InvCode,
ProductionName = g.Key.InvName,
MaterialCode = g.Key.subInvCode,
MaterialName = g.Key.subInvName,
TotalQuantity = g.Sum(bom =>
{
decimal iusequantity;
decimal.TryParse(bom.Iusequantity, out iusequantity);
return allocation.Allocated * iusequantity;
})
})
.ToList();
// 为每个物料创建带时间段信息的记录
foreach (var item in aggregatedData)
{
mmCallMrpList.Add(new MmCallMrp
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
LineCode = lineCode,
LineCode = allocation.LineCode,
WorkOrderDate = parm.WorkOrderDate.Value,
ProductionCode = item.ProductionCode,
ProductionName = item.ProductionName,
MaterialCode = item.MaterialCode,
MaterialName = item.MaterialName,
Quantity = (int?)item.TotalQuantity,
IssuanceTime =
startTime.ToString("HH:mm") + "-" + endTime.ToString("HH:mm"),
Sort = getSort(startTime),
IssuanceTime = $"{startTime:HH:mm}-{endTime:HH:mm}",
Sort = currentBatchIndex + 1,
CreatedBy = "系统自动生成",
CreatedTime = DateTime.Now,
}
);
});
}
}
}
mmCallMrpList = mmCallMrpList
.Where(it => !string.IsNullOrEmpty(it.MaterialCode) &&
(it.MaterialCode.Contains("-") || it.MaterialCode.Contains("—")))
.ToList();
foreach (var mrp in mmCallMrpList.Take(10))
// 过滤并合并相同物料号和线别的记录
var processedList = mmCallMrpList
.Where(it => !string.IsNullOrEmpty(it.MaterialCode) &&
(it.MaterialCode.Contains("-") || it.MaterialCode.Contains("—")))
.GroupBy(m => new { m.MaterialCode, m.LineCode, m.IssuanceTime }) // 按时间段分组合并
.Select(g => new MmCallMrp
{
Console.WriteLine($"MaterialCode: {mrp.MaterialCode}");
}
Id = SnowFlakeSingle.Instance.NextId().ToString(),
LineCode = g.Key.LineCode,
WorkOrderDate = g.First().WorkOrderDate,
ProductionCode = g.First().ProductionCode,
ProductionName = g.First().ProductionName,
MaterialCode = g.Key.MaterialCode,
MaterialName = g.First().MaterialName,
Quantity = g.Sum(m => m.Quantity),
IssuanceTime = g.Key.IssuanceTime, // 保留时间段信息
Sort = g.First().Sort,
CreatedBy = "系统自动生成",
CreatedTime = DateTime.Now
})
.ToList();
// 创建排序键字典确保相同物料号排在一起
var materialOrderDict = processedList
.Select(m => m.MaterialCode)
.Distinct()
.OrderBy(MaterialCode => MaterialCode)
.Select((MaterialCode, index) => new { MaterialCode, index })
.ToDictionary(item => item.MaterialCode, item => item.index);
// 按物料号和时间段排序
mmCallMrpList = processedList
.OrderBy(m => materialOrderDict[m.MaterialCode])
.ThenBy(m => m.Sort) // 按时间段排序
.ToList();
// 删除旧数据并插入新数据
Context
@ -377,7 +388,6 @@ namespace DOAN.Service.MES.mm.paintedparts_call
{
Context.Ado.CommitTran();
return 0;
//throw new Exception($"该线别:{lineCode}日期:{checkDate}无涂装MRP清单");
}
int result = Context.Insertable(mmCallMrpList).ExecuteCommand();
@ -401,14 +411,15 @@ namespace DOAN.Service.MES.mm.paintedparts_call
public static int getSort(DateTime startTime)
{
if(startTime.ToString("HH:mm") == "08:00")
if (startTime.ToString("HH:mm") == "08:00")
{
return 1;
}
else if(startTime.ToString("HH:mm") == "10:00")
else if (startTime.ToString("HH:mm") == "10:00")
{
return 2;
}else if(startTime.ToString("HH:mm") == "12:00")
}
else if (startTime.ToString("HH:mm") == "12:00")
{
return 3;
}