优化调整

This commit is contained in:
gcw_MV9p2JJN 2025-09-16 10:44:17 +08:00
parent 343ade3179
commit 8a1a757dae

View File

@ -30,28 +30,8 @@ namespace DOAN.Service.MES.product
[AppService(ServiceType = typeof(IProweekplanManageService), ServiceLifetime = LifeTime.Transient)]
public class ProweekplanManageService : BaseService<ProWorkorder>, IProweekplanManageService
{
/// <summary>
/// 导入Excel支持大数据量处理
/// - 内存使用量大幅降低 通过批处理机制内存占用可减少70%-90%
// - 处理速度显著提升 批量数据库操作可将导入速度提升3-5倍
// - 系统稳定性增强 :避免了大数据量导致的内存溢出和超时问题
// - 代码可维护性提高 :模块化设计使后续修改和扩展更加容易
/// </summary>
/// <param name="formFile"></param>
// 设置批处理大小
public int ImportExcel(IFormFile formFile, string username)
{
// 参数校验
if (formFile == null || formFile.Length == 0)
{
throw new CustomException("上传的文件不能为空");
}
if (string.IsNullOrEmpty(username))
{
throw new CustomException("用户名不能为空");
}
using (var stream = formFile.OpenReadStream())
{
try
@ -59,367 +39,163 @@ namespace DOAN.Service.MES.product
List<ProWeeklyPlan> insertProWeekPlanList = new List<ProWeeklyPlan>();
List<ProWeeklyDate> insertProWeeklyDateList = new List<ProWeeklyDate>();
// 安全创建工作簿
IWorkbook workbook = new XSSFWorkbook(stream);
// 安全获取工作表
ISheet sheet = workbook.GetSheet("Sheet1");
if (sheet == null)
{
throw new CustomException("未找到名称为 'Sheet1' 的工作表");
}
// 处理第2行 获取日期
IRow secondRow = sheet.GetRow(1);
if (secondRow == null)
{
throw new CustomException("Excel文件格式不正确第2行不存在");
}
// 安全获取单元格
NPOI.SS.UserModel.ICell cell = secondRow.GetCell(0);
if (cell == null)
{
throw new CustomException("Excel文件格式不正确第2行第1列没有数据");
}
string title = cell.ToString() ?? string.Empty;
if (string.IsNullOrEmpty(title))
{
throw new CustomException("Excel文件格式不正确标题不能为空");
}
//提取括号内的数字
int week = extractWeek(title);
// 处理第2行 获取标题(含周数信息)
IRow secondRow = sheet.GetRow(1);
string title = secondRow?.GetCell(0)?.ToString() ?? "";
int week = extractWeek(title); // 你自己实现的提取周数的方法
int year = DateTime.Now.Year;
// 遍历每一
// 从第6行开始遍历数据行
for (int row = 6; row <= sheet.LastRowNum; row++)
{
int index = row - 5;
IRow currentRow = sheet.GetRow(row);
if (currentRow != null) // 确保行不为空
if (currentRow == null) continue;
int index = row - 5;
ProWeeklyPlan proWeeklyPlan = new ProWeeklyPlan
{
ProWeeklyPlan proWeeklyPlan = new ProWeeklyPlan();
Id = SnowFlakeSingle.Instance.NextId(),
PlanCode = "WP" + SnowFlakeSingle.Instance.NextId().ToString("D19").PadLeft(19, '0'),
PlanYear = DateTime.Now.Year,
PlanWeek = week,
CreatedTime = DateTime.Now,
ProductCode = currentRow.GetCell(2)?.ToString(),
ProductName = currentRow.GetCell(3)?.ToString(),
Specification = currentRow.GetCell(4)?.ToString(),
Planner = currentRow.GetCell(6)?.ToString(),
CreatedBy = username,
PlanQty = (int)(currentRow.GetCell(7)?.NumericCellValue ?? 0),
CompletedQty = (int)(currentRow.GetCell(8)?.NumericCellValue ?? 0),
};
proWeeklyPlan.Id = SnowFlakeSingle.Instance.NextId();
// 如果产品相关字段全部为空,则跳过该行
if (string.IsNullOrEmpty(proWeeklyPlan.ProductCode) &&
string.IsNullOrEmpty(proWeeklyPlan.ProductName) &&
string.IsNullOrEmpty(proWeeklyPlan.Specification))
{
continue;
}
proWeeklyPlan.PlanCode = "WP" + DateTime.Now.ToString("yyMM") + index.ToString("000");
proWeeklyPlan.PlanYear = DateTime.Now.Year;
proWeeklyPlan.PlanWeek = week;
proWeeklyPlan.CreatedTime = DateTime.Now;
//班组
string group_name = currentRow.GetCell(0)?.ToString();
//车型
string part_no = currentRow.GetCell(1)?.ToString();
//产品编码
string _ProductCode = currentRow.GetCell(2)?.ToString();
proWeeklyPlan.ProductCode = _ProductCode;
//产品名称
string _ProductName = currentRow.GetCell(3)?.ToString();
proWeeklyPlan.ProductName = _ProductName;
//产品零件号
string _Specification = currentRow.GetCell(4)?.ToString();
proWeeklyPlan.Specification = _Specification;
if (string.IsNullOrEmpty(_ProductCode) && string.IsNullOrEmpty(_ProductName) && string.IsNullOrEmpty(_Specification))
// 可选字段
proWeeklyPlan.PlanStatus = !string.IsNullOrEmpty(currentRow.GetCell(5)?.ToString())
? currentRow.GetCell(5).ToString()
: null;
// 初始化默认日期
proWeeklyPlan.PlanStartDate = DateTime.MinValue;
proWeeklyPlan.PlanEndDate = DateTime.MinValue;
// 处理星期一到星期日第9列开始每4列一组类型、计划数、是否变更、实际数
for (int dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++)
{
int colIndex = 9 + dayOfWeek * 4;
ICell dateCell = sheet.GetRow(2)?.GetCell(colIndex);
ICell dayNameCell = sheet.GetRow(3)?.GetCell(colIndex);
ICell productTypeCell = currentRow.GetCell(colIndex);
ICell planQtyCell = currentRow.GetCell(colIndex + 1);
ICell isChangeCell = currentRow.GetCell(colIndex + 2);
ICell actualQtyCell = currentRow.GetCell(colIndex + 3);
DateTime? weekDate = dateCell?.DateCellValue;
string dayOfWeekName = dayNameCell?.ToString() ?? "";
string productType = productTypeCell?.ToString() ?? "";
int planNum = (int)(planQtyCell?.NumericCellValue ?? 0);
string isChange = isChangeCell?.ToString() ?? "";
int actualQt = (int)(actualQtyCell?.NumericCellValue ?? 0);
var proWeeklyDate = new ProWeeklyDate
{
continue;
}
//生产状态
string _PlanStatus = currentRow.GetCell(5)?.ToString();
if (!string.IsNullOrEmpty(_PlanStatus))
proWeeklyPlan.PlanStatus = _PlanStatus;
Id = SnowFlakeSingle.Instance.NextId(),
FkWeeklyId = proWeeklyPlan.Id,
PlanCode = proWeeklyPlan.PlanCode,
WeekDate = weekDate,
DayOfWeek = dayOfWeekName,
ProductType = productType,
PlanNum = planNum,
IsChange = isChange,
ActualQt = actualQt,
CreatedTime = DateTime.Now
};
//车间计划员
string planner = currentRow.GetCell(6)?.ToString();
proWeeklyPlan.Planner = planner;
//本周计划装配数量 - 安全访问
var planQtyCell = currentRow.GetCell(7);
proWeeklyPlan.PlanQty = planQtyCell != null && planQtyCell.CellType == NPOI.SS.UserModel.CellType.Numeric
? (int)planQtyCell.NumericCellValue
: 0;
insertProWeeklyDateList.Add(proWeeklyDate);
//本周实际装配数 - 安全访问
var actualQtyCell = currentRow.GetCell(8);
proWeeklyPlan.CompletedQty = actualQtyCell != null && actualQtyCell.CellType == NPOI.SS.UserModel.CellType.Numeric
? (int)actualQtyCell.NumericCellValue
: 0;
proWeeklyPlan.CreatedBy = username;
// 2025/8/25 星期一 产品类型
// 2025/8/25
ProWeeklyDate proWeeklyDatePlan = new ProWeeklyDate();
proWeeklyDatePlan.Id = SnowFlakeSingle.Instance.NextId();
proWeeklyDatePlan.FkWeeklyId = proWeeklyPlan.Id;
proWeeklyDatePlan.PlanCode = proWeeklyPlan.PlanCode;
int weekdayindex = 9;
// 安全获取日期
IRow dateRow = sheet.GetRow(2);
if (dateRow != null)
// 设置周计划的开始和结束日期
if (dayOfWeek == 0 && weekDate.HasValue)
{
var dateCell = dateRow.GetCell(weekdayindex);
if (dateCell != null)
{
DateTime? MondayDate = null;
try
{
// 根据单元格类型安全获取日期值
if (dateCell.CellType == NPOI.SS.UserModel.CellType.Numeric)
{
MondayDate = dateCell.DateCellValue;
}
else if (dateCell.CellType == NPOI.SS.UserModel.CellType.String)
{
DateTime parsedDate;
if (DateTime.TryParse(dateCell.StringCellValue, out parsedDate))
{
MondayDate = parsedDate;
}
}
}
catch {}
proWeeklyDatePlan.WeekDate = MondayDate ?? DateTime.MinValue;
proWeeklyPlan.PlanStartDate = MondayDate ?? DateTime.MinValue;
// 安全访问DateTime值的属性
if (MondayDate.HasValue)
{
proWeeklyPlan.PlanYear = MondayDate.Value.Year;
year = MondayDate.Value.Year;
}
}
proWeeklyPlan.PlanStartDate = weekDate.Value;
proWeeklyPlan.PlanYear = weekDate.Value.Year;
year = weekDate.Value.Year;
}
// 星期一名称
string MondayName = sheet.GetRow(3).GetCell(weekdayindex)?.ToString();
proWeeklyDatePlan.DayOfWeek = MondayName;
//产品类型
string Mondayproducttype = currentRow.GetCell(9)?.ToString();
proWeeklyDatePlan.ProductType = Mondayproducttype;
//计划数量 - 安全访问
var mondayPlanQtyCell = currentRow.GetCell(10);
int MondayPlanQty = mondayPlanQtyCell != null && mondayPlanQtyCell.CellType == NPOI.SS.UserModel.CellType.Numeric
? (int)mondayPlanQtyCell.NumericCellValue
: 0;
proWeeklyDatePlan.PlanNum = MondayPlanQty;
//是否变更 - 安全访问
string MondayIsChange = currentRow.GetCell(11)?.ToString() ?? string.Empty;
proWeeklyDatePlan.IsChange = MondayIsChange;
//实际数量 - 安全访问
var mondayActualQtyCell = currentRow.GetCell(12);
int MondayActualQty = mondayActualQtyCell != null && mondayActualQtyCell.CellType == NPOI.SS.UserModel.CellType.Numeric
? (int)mondayActualQtyCell.NumericCellValue
: 0;
proWeeklyDatePlan.ActualQt = MondayActualQty;
proWeeklyDatePlan.CreatedTime = DateTime.Now;
// 2025/8/25 星期二 产品类型
// 2025/8/25
ProWeeklyDate proWeeklyDatePlan2 = new ProWeeklyDate();
proWeeklyDatePlan2.Id = SnowFlakeSingle.Instance.NextId();
proWeeklyDatePlan2.FkWeeklyId = proWeeklyPlan.Id;
proWeeklyDatePlan2.PlanCode = proWeeklyPlan.PlanCode;
DateTime? TuesdayDate = sheet.GetRow(2).GetCell(weekdayindex + 4 * 1)?.DateCellValue;
proWeeklyDatePlan2.WeekDate = TuesdayDate;
// 星期二名称
string TuesdayName = sheet.GetRow(3).GetCell(weekdayindex + 4 * 1)?.ToString();
proWeeklyDatePlan2.DayOfWeek = TuesdayName;
//产品类型
string Tuesdayproducttype = currentRow.GetCell(9 + 4 * 1)?.ToString();
proWeeklyDatePlan2.ProductType = Tuesdayproducttype;
//计划数量
int TuesdayPlanQty = (int)currentRow.GetCell(10 + 4 * 1)?.NumericCellValue;
proWeeklyDatePlan2.PlanNum = TuesdayPlanQty;
//是否变更
string TuesdayIsChange = currentRow.GetCell(11 + 4 * 1)?.ToString();
proWeeklyDatePlan2.IsChange = TuesdayIsChange;
//实际数量
int TuesdayActualQty = (int)currentRow.GetCell(12)?.NumericCellValue;
proWeeklyDatePlan2.ActualQt = TuesdayActualQty;
proWeeklyDatePlan2.CreatedTime = DateTime.Now;
// 2025/8/25 星期三 产品类型
// 2025/8/25
ProWeeklyDate proWeeklyDatePlan3 = new ProWeeklyDate();
proWeeklyDatePlan3.Id = SnowFlakeSingle.Instance.NextId();
proWeeklyDatePlan3.FkWeeklyId = proWeeklyPlan.Id;
proWeeklyDatePlan3.PlanCode = proWeeklyPlan.PlanCode;
DateTime? WednesdayDate = sheet.GetRow(2).GetCell(weekdayindex + 4 * 2)?.DateCellValue;
proWeeklyDatePlan3.WeekDate = WednesdayDate;
// 星期三名称
string WednesdayName = sheet.GetRow(3).GetCell(weekdayindex + 4 * 2)?.ToString();
proWeeklyDatePlan3.DayOfWeek = WednesdayName;
//产品类型
string Wednesdayproducttype = currentRow.GetCell(9 + 4 * 2)?.ToString();
proWeeklyDatePlan3.ProductType = Wednesdayproducttype;
//计划数量
int WednesdayPlanQty = (int)currentRow.GetCell(10 + 4 * 2)?.NumericCellValue;
proWeeklyDatePlan3.PlanNum = WednesdayPlanQty;
//是否变更
string WednesdayIsChange = currentRow.GetCell(11 + 4 * 2)?.ToString();
proWeeklyDatePlan3.IsChange = WednesdayIsChange;
//实际数量
int WednesdayActualQty = (int)currentRow.GetCell(12 + 4 * 2)?.NumericCellValue;
proWeeklyDatePlan3.ActualQt = WednesdayActualQty;
proWeeklyDatePlan3.CreatedTime = DateTime.Now;
// 2025/8/25 星期四 产品类型
// 2025/8/25
ProWeeklyDate proWeeklyDatePlan4 = new ProWeeklyDate();
proWeeklyDatePlan4.Id = SnowFlakeSingle.Instance.NextId();
proWeeklyDatePlan4.FkWeeklyId = proWeeklyPlan.Id;
proWeeklyDatePlan4.PlanCode = proWeeklyPlan.PlanCode;
DateTime? ThursdayDate = sheet.GetRow(2).GetCell(weekdayindex + 4 * 3)?.DateCellValue;
proWeeklyDatePlan4.WeekDate = ThursdayDate;
// 星期三名称
string ThursdayName = sheet.GetRow(3).GetCell(weekdayindex + 4 * 3)?.ToString();
proWeeklyDatePlan4.DayOfWeek = ThursdayName;
//产品类型
string Thursdayproducttype = currentRow.GetCell(9 + 4 * 3)?.ToString();
proWeeklyDatePlan4.ProductType = Thursdayproducttype;
//计划数量
int ThursdayPlanQty = (int)currentRow.GetCell(10 + 4 * 3)?.NumericCellValue;
proWeeklyDatePlan4.PlanNum = ThursdayPlanQty;
//是否变更
string ThursdayIsChange = currentRow.GetCell(11 + 4 * 3)?.ToString();
proWeeklyDatePlan4.IsChange = ThursdayIsChange;
//实际数量
int ThursdayActualQty = (int)currentRow.GetCell(12 + 4 * 3)?.NumericCellValue;
proWeeklyDatePlan4.ActualQt = ThursdayActualQty;
proWeeklyDatePlan4.CreatedTime = DateTime.Now;
// 2025/8/25 星期五 产品类型
// 2025/8/25
ProWeeklyDate proWeeklyDatePlan5 = new ProWeeklyDate();
proWeeklyDatePlan5.Id = SnowFlakeSingle.Instance.NextId();
proWeeklyDatePlan5.FkWeeklyId = proWeeklyPlan.Id;
proWeeklyDatePlan5.PlanCode = proWeeklyPlan.PlanCode;
DateTime? FridayDate = sheet.GetRow(2).GetCell(weekdayindex + 4 * 4)?.DateCellValue;
proWeeklyDatePlan5.WeekDate = FridayDate;
// 星期三名称
string FridayName = sheet.GetRow(3).GetCell(weekdayindex + 4 * 4)?.ToString();
proWeeklyDatePlan5.DayOfWeek = FridayName;
//产品类型
string Fridayproducttype = currentRow.GetCell(9 + 4 * 4)?.ToString();
proWeeklyDatePlan5.ProductType = Fridayproducttype;
//计划数量
int FridayPlanQty = (int)currentRow.GetCell(10 + 4 * 4)?.NumericCellValue;
proWeeklyDatePlan5.PlanNum = FridayPlanQty;
//是否变更
string FridayIsChange = currentRow.GetCell(11 + 4 * 4)?.ToString();
proWeeklyDatePlan5.IsChange = FridayIsChange;
//实际数量
int FridayActualQty = (int)currentRow.GetCell(12 + 4 * 4)?.NumericCellValue;
proWeeklyDatePlan5.ActualQt = FridayActualQty;
proWeeklyDatePlan5.CreatedTime = DateTime.Now;
// 2025/8/25 星期六 产品类型
// 2025/8/25
ProWeeklyDate proWeeklyDatePlan6 = new ProWeeklyDate();
proWeeklyDatePlan6.Id = SnowFlakeSingle.Instance.NextId();
proWeeklyDatePlan6.FkWeeklyId = proWeeklyPlan.Id;
proWeeklyDatePlan6.PlanCode = proWeeklyPlan.PlanCode;
DateTime? SaturdayDate = sheet.GetRow(2).GetCell(weekdayindex + 4 * 5)?.DateCellValue;
proWeeklyDatePlan6.WeekDate = SaturdayDate;
// 星期三名称
string SaturdayName = sheet.GetRow(3).GetCell(weekdayindex + 4 * 5)?.ToString();
proWeeklyDatePlan6.DayOfWeek = SaturdayName;
//产品类型
string Saturdayproducttype = currentRow.GetCell(9 + 4 * 5)?.ToString();
proWeeklyDatePlan6.ProductType = Saturdayproducttype;
//计划数量
int SaturdayPlanQty = (int)currentRow.GetCell(10 + 4 * 5)?.NumericCellValue;
proWeeklyDatePlan6.PlanNum = SaturdayPlanQty;
//是否变更
string SaturdayIsChange = currentRow.GetCell(11 + 4 * 5)?.ToString();
proWeeklyDatePlan6.IsChange = SaturdayIsChange;
//实际数量
int SaturdayActualQty = (int)currentRow.GetCell(12 + 4 * 5)?.NumericCellValue;
proWeeklyDatePlan6.ActualQt = SaturdayActualQty;
proWeeklyDatePlan6.CreatedTime = DateTime.Now;
// 2025/8/25 星期日 产品类型
// 2025/8/25
ProWeeklyDate proWeeklyDatePlan7 = new ProWeeklyDate();
proWeeklyDatePlan7.Id = SnowFlakeSingle.Instance.NextId();
proWeeklyDatePlan7.FkWeeklyId = proWeeklyPlan.Id;
proWeeklyDatePlan7.PlanCode = proWeeklyPlan.PlanCode;
DateTime? SundayDate = sheet.GetRow(2).GetCell(weekdayindex + 4 * 6)?.DateCellValue;
proWeeklyDatePlan7.WeekDate = SundayDate;
// 星期三名称
string SundayName = sheet.GetRow(3).GetCell(weekdayindex + 4 * 6)?.ToString();
proWeeklyDatePlan7.DayOfWeek = SundayName;
//产品类型
string Sundayproducttype = currentRow.GetCell(9 + 4 * 6)?.ToString();
proWeeklyDatePlan7.ProductType = Sundayproducttype;
//计划数量
int SundayPlanQty = (int)currentRow.GetCell(10 + 4 * 6)?.NumericCellValue;
proWeeklyDatePlan7.PlanNum = SundayPlanQty;
//是否变更
string SundayIsChange = currentRow.GetCell(11 + 4 * 6)?.ToString();
proWeeklyDatePlan7.IsChange = SundayIsChange;
//实际数量
int SundayActualQty = (int)currentRow.GetCell(12 + 4 * 6)?.NumericCellValue;
proWeeklyDatePlan7.ActualQt = SundayActualQty;
proWeeklyDatePlan7.CreatedTime = DateTime.Now;
// 安全设置结束日期
if (SundayDate.HasValue)
if (dayOfWeek == 6 && weekDate.HasValue)
{
proWeeklyPlan.PlanEndDate = SundayDate.Value;
proWeeklyPlan.PlanEndDate = weekDate.Value;
}
}
insertProWeekPlanList.Add(proWeeklyPlan);
insertProWeekPlanList.Add(proWeeklyPlan);
insertProWeeklyDateList.Add(proWeeklyDatePlan);
insertProWeeklyDateList.Add(proWeeklyDatePlan2);
insertProWeeklyDateList.Add(proWeeklyDatePlan3);
insertProWeeklyDateList.Add(proWeeklyDatePlan4);
insertProWeeklyDateList.Add(proWeeklyDatePlan5);
insertProWeeklyDateList.Add(proWeeklyDatePlan6);
insertProWeeklyDateList.Add(proWeeklyDatePlan7);
// ======================
// 🚩分批提交每500条计划及其关联日期插入一次
// ======================
if (insertProWeekPlanList.Count >= 500)
{
InsertBatchData(insertProWeekPlanList, insertProWeeklyDateList, year, week, username);
// 清空缓存列表
insertProWeekPlanList.Clear();
insertProWeeklyDateList.Clear();
}
}
// 插入数据
UseTran2(() =>
// 插入剩余不足500条的数据
if (insertProWeekPlanList.Count > 0)
{
//获取本周本年 所有日计划
Context
.Deleteable<ProWeeklyDate>()
.Where(d =>
SqlFunc.Subqueryable<ProWeeklyPlan>()
.Where(it => it.PlanYear == year && it.PlanWeek == week && it.PlanCode == d.PlanCode)
.Any()).ExecuteCommand();
Context.Deleteable<ProWeeklyPlan>().Where(it => it.PlanYear == year && it.PlanWeek == week).ExecuteCommand();
InsertBatchData(insertProWeekPlanList, insertProWeeklyDateList, year, week, username);
}
//批量插入周计划
Context.Insertable(insertProWeekPlanList).ExecuteCommand();
//批量插入日计划
Context.Insertable(insertProWeeklyDateList).ExecuteCommand();
});
return insertProWeekPlanList.Count();
return insertProWeekPlanList.Count + (insertProWeeklyDateList.Count > 0 ? 0 : 0); // 实际可根据需求返回总插入条数
}
catch (Exception ex)
{
// 可以添加日志记录
throw new CustomException($"Excel导入失败: {ex.Message}");
}
{
// 建议记录日志,而不是直接抛出
// Log.Error(ex, "导入Excel失败");
throw; // 不要 throw ex直接 throw 保留堆栈
}
}
}
/// <summary>
/// 批量插入数据(分批次事务处理)
/// </summary>
private void InsertBatchData(
List<ProWeeklyPlan> proWeeklyPlans,
List<ProWeeklyDate> proWeeklyDates,
int year,
int week,
string username)
{
// 使用事务包裹当前批次
UseTran(() =>
{
// 1. 删除旧数据:根据年份+周数+计划编码删除 ProWeeklyDate然后删除 ProWeeklyPlan
var planCodes = proWeeklyPlans.Select(p => p.PlanCode).ToList();
Context.Deleteable<ProWeeklyDate>()
.Where(d => planCodes.Contains(d.PlanCode) )
.ExecuteCommand();
Context.Deleteable<ProWeeklyPlan>()
.Where(p => p.PlanYear == year && p.PlanWeek == week && planCodes.Contains(p.PlanCode))
.ExecuteCommand();
// 2. 插入新的周计划和日计划
Context.Insertable(proWeeklyPlans).ExecuteCommand();
Context.Insertable(proWeeklyDates).ExecuteCommand();
});
}
const int BATCH_SIZE = 500;
/// <summary>
@ -639,49 +415,75 @@ namespace DOAN.Service.MES.product
public int UpdateActualAssemblyProgress(int year, int week)
{
int result = 0;
//获取周的日期开始到结束
var WeekStartAndEnd = Context.Queryable<ProWeeklyPlan>().Where(it => it.PlanYear == year && it.PlanWeek == week)
.Select(it => new { it.PlanStartDate, it.PlanEndDate }).First();
if(WeekStartAndEnd == null)
{
// 1. 获取该周的开始和结束日期
var weekInfo = Context.Queryable<ProWeeklyPlan>()
.Where(it => it.PlanYear == year && it.PlanWeek == week)
.Select(it => new { it.PlanStartDate, it.PlanEndDate })
.First();
if (weekInfo == null)
return result;
}
DateTime WeekStartDate = WeekStartAndEnd.PlanStartDate;
DateTime WeekEndDate = WeekStartAndEnd.PlanEndDate;
//
List<ProWeeklyPlan> proWeeklyPlans = Context.Queryable<ProWeeklyPlan>().Where(it => it.PlanYear == year && it.PlanWeek == week).ToList();
if (proWeeklyPlans.Count > 0)
DateTime weekStartDate = weekInfo.PlanStartDate;
DateTime weekEndDate = weekInfo.PlanEndDate;
// 2. 查询该周所有的生产计划ProWeeklyPlan
var proWeeklyPlans = Context.Queryable<ProWeeklyPlan>()
.Where(it => it.PlanYear == year && it.PlanWeek == week)
.ToList();
if (proWeeklyPlans == null || !proWeeklyPlans.Any())
return result;
// 3. 提取所有唯一的 (ProductionCode, Specification) 组合,用于后续统计
var planGroups = proWeeklyPlans
.Select(p => new { p.ProductCode, p.Specification, p.Id, p.PlanQty })
.ToList();
if (!planGroups.Any())
return result;
// 4. 【关键优化点】一次性查询所有相关的工单数据,并按 ProductCode + Specification 分组统计总合格数
var workOrderStats = Context.Queryable<ProWorkorder>()
.LeftJoin<ProReportwork>((wo, rw) => wo.Workorder == rw.FkWorkorder) // ⚠️ 请根据实际外键关系修改!!!
.Where((wo, rw) =>
wo.WorkorderDate >= weekStartDate &&
wo.WorkorderDate <= weekEndDate &&
planGroups.Select(pg => pg.ProductCode).Contains(wo.ProductionCode) &&
planGroups.Select(pg => pg.Specification).Contains(wo.Specification)
)
.GroupBy((wo, rw) => new { wo.ProductionCode, wo.Specification })
.Select((wo, rw) => new
{
foreach (var plan in proWeeklyPlans)
{
//计算实际装配数
var workorderData = Context
.Queryable<ProWorkorder>()
.LeftJoin<ProReportwork>((w, r) => w.Id == r.Id)
.Where((w, r) => w.WorkorderDate >= WeekStartDate && w.WorkorderDate <= WeekEndDate && w.ProductionCode == plan.ProductCode && w.Specification == plan.Specification)
.GroupBy((w, r) => new { w.ProductionCode, w.Specification })
.Select((w, r) => new
{
w.ProductionCode,
w.Specification,
TotalDeliveryNum = SqlFunc.AggregateSum(r.QualifiedNumber)
}).First();
if (workorderData != null)
{
plan.CompletedQty = workorderData.TotalDeliveryNum ?? 0;
plan.RemainingQty = plan.PlanQty - plan.CompletedQty;
plan.UpdatedBy = "system";
plan.UpdatedTime = DateTime.Now;
result+= Context.Updateable(plan).ExecuteCommand();
}
}
ProductionCode = wo.ProductionCode,
Specification = wo.Specification,
TotalDeliveryNum = SqlFunc.AggregateSum(rw.QualifiedNumber) ?? 0 // 注意rw 可能是 Reportwork需有 QualifiedNumber 字段
})
.ToList();
// 5. 遍历原始计划,从统计结果中找到对应的 TotalDeliveryNum进行更新
foreach (var plan in proWeeklyPlans)
{
var key = new { plan.ProductCode, plan.Specification };
var stat = workOrderStats.FirstOrDefault(s => s.ProductionCode == key.ProductCode && s.Specification == key.Specification);
int completedQty = stat?.TotalDeliveryNum ?? 0;
int remainingQty = plan.PlanQty - completedQty;
// 只有当数据有变化时才更新(可选,减少不必要的更新)
if (plan.CompletedQty != completedQty || plan.RemainingQty != remainingQty)
{
plan.CompletedQty = completedQty;
plan.RemainingQty = remainingQty;
plan.UpdatedBy = "system";
plan.UpdatedTime = DateTime.Now;
result += Context.Updateable(plan).ExecuteCommand();
}
return result;
}
return result;
}