zhuangpei-mesbackend/DOAN.Service/MES/product/ProweekplanManageService.cs
2025-09-16 10:16:04 +08:00

881 lines
44 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AlibabaCloud.SDK.Dingtalkworkbench_1_0.Models;
using DOAN.Model;
using DOAN.Model.MES.product;
using DOAN.Model.MES.product.Dto;
using DOAN.Repository;
using DOAN.Service.MES.product.IService;
using Infrastructure;
using Infrastructure.Attribute;
using Infrastructure.Extensions;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using NPOI.HPSF;
using NPOI.HSSF.UserModel;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace DOAN.Service.MES.product
{
[AppService(ServiceType = typeof(IProweekplanManageService), ServiceLifetime = LifeTime.Transient)]
public class ProweekplanManageService : BaseService<ProWorkorder>, IProweekplanManageService
{
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
{
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);
int year = DateTime.Now.Year;
// 从第6行开始遍历数据行
for (int row = 6; row <= sheet.LastRowNum; row++)
{
IRow currentRow = sheet.GetRow(row);
if (currentRow == null) continue;
int index = row - 5;
// 先创建对象实例(不传入任何参数,即调用无参构造函数)
ProWeeklyPlan proWeeklyPlan = new ProWeeklyPlan();
// 然后逐个属性进行赋值
proWeeklyPlan.Id = SnowFlakeSingle.Instance.NextId();
proWeeklyPlan.PlanCode = "WP" + SnowFlakeSingle.Instance.NextId().ToString("D19").PadLeft(19, '0');
proWeeklyPlan.PlanYear = DateTime.Now.Year;
proWeeklyPlan.PlanWeek = week;
proWeeklyPlan.CreatedTime = DateTime.Now;
proWeeklyPlan.ProductCode = currentRow.GetCell(2)?.ToString();
proWeeklyPlan.ProductName = currentRow.GetCell(3)?.ToString();
proWeeklyPlan.Specification = currentRow.GetCell(4)?.ToString();
proWeeklyPlan.Planner = currentRow.GetCell(6)?.ToString();
proWeeklyPlan.CreatedBy = username;
proWeeklyPlan.PlanQty = (int)(currentRow.GetCell(7)?.NumericCellValue ?? 0);
proWeeklyPlan.CompletedQty = (int)(currentRow.GetCell(8)?.NumericCellValue ?? 0);
// 如果产品相关字段全部为空,则跳过该行
if (string.IsNullOrEmpty(proWeeklyPlan.ProductCode) &&
string.IsNullOrEmpty(proWeeklyPlan.ProductName) &&
string.IsNullOrEmpty(proWeeklyPlan.Specification))
{
continue;
}
//车间计划员
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;
//本周实际装配数 - 安全访问
var actualQtyCell = currentRow.GetCell(8);
proWeeklyPlan.CompletedQty = actualQtyCell != null && actualQtyCell.CellType == NPOI.SS.UserModel.CellType.Numeric
? (int)actualQtyCell.NumericCellValue
: 0;
proWeeklyPlan.CreatedBy = username;
// 处理星期一到星期日第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);
// 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)
{
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;
}
}
}
var proWeeklyDate = new ProWeeklyDate
{
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 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;
// 设置周计划的开始和结束日期
if (dayOfWeek == 0 && weekDate.HasValue)
{
proWeeklyPlan.PlanStartDate = weekDate.Value;
proWeeklyPlan.PlanYear = weekDate.Value.Year;
year = weekDate.Value.Year;
}
if (dayOfWeek == 6 && weekDate.HasValue)
{
proWeeklyPlan.PlanEndDate = weekDate.Value;
}
}
insertProWeekPlanList.Add(proWeeklyPlan);
//产品类型
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)
{
proWeeklyPlan.PlanEndDate = SundayDate.Value;
}
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 > 0)
{
InsertBatchData(insertProWeekPlanList, insertProWeeklyDateList, year, week, username);
}
return insertProWeekPlanList.Count + (insertProWeeklyDateList.Count > 0 ? 0 : 0); // 实际可根据需求返回总插入条数
}
catch (Exception ex)
{
// 可以添加日志记录
throw new CustomException($"Excel导入失败: {ex.Message}");
}
}
}
const int BATCH_SIZE = 500;
/// <summary>
/// 处理一行Excel数据
/// </summary>
/// <param name="row">当前行</param>
/// <param name="index">索引</param>
/// <param name="username">用户名</param>
/// <param name="week">周数</param>
/// <param name="weekDays">星期信息</param>
/// <returns>计划和日期列表</returns>
private (ProWeeklyPlan, List<ProWeeklyDate>) ProcessRow(IRow row, int index, string username, int week, List<(DateTime Date, string DayName, int DateCellIndex)> weekDays)
{
try
{
ProWeeklyPlan proWeeklyPlan = new ProWeeklyPlan();
proWeeklyPlan.Id = SnowFlakeSingle.Instance.NextId();
proWeeklyPlan.PlanCode = "WP" + DateTime.Now.ToString("yyMM") + index.ToString("000");
proWeeklyPlan.PlanYear = weekDays.Any() ? weekDays.First().Date.Year : DateTime.Now.Year;
proWeeklyPlan.PlanWeek = week;
proWeeklyPlan.CreatedTime = DateTime.Now;
proWeeklyPlan.CreatedBy = username;
//班组
proWeeklyPlan.GroupName = row.GetCell(0)?.ToString();
//车型
string part_no = row.GetCell(1)?.ToString();
//产品编码
proWeeklyPlan.ProductCode = row.GetCell(2)?.ToString();
//产品名称
proWeeklyPlan.ProductName = row.GetCell(3)?.ToString();
//产品零件号
proWeeklyPlan.Specification = row.GetCell(4)?.ToString();
//生产状态
string planStatus = row.GetCell(5)?.ToString();
if (!string.IsNullOrEmpty(planStatus))
{
proWeeklyPlan.PlanStatus = planStatus;
}
//车间计划员
proWeeklyPlan.Planner = row.GetCell(6)?.ToString();
//本周计划装配数量
if (row.GetCell(7) != null)
{
double planQty = row.GetCell(7).NumericCellValue;
proWeeklyPlan.PlanQty = (int)planQty;
}
//本周实际装配数
if (row.GetCell(8) != null)
{
double actualQty = row.GetCell(8).NumericCellValue;
proWeeklyPlan.CompletedQty = (int)actualQty;
}
// 设置计划开始和结束日期
if (weekDays.Any())
{
proWeeklyPlan.PlanStartDate = weekDays.First().Date;
proWeeklyPlan.PlanEndDate = weekDays.Last().Date;
}
// 创建每日计划
List<ProWeeklyDate> weeklyDates = new List<ProWeeklyDate>();
foreach (var (date, dayName, colIndex) in weekDays)
{
// 确保列索引有效
if (colIndex + 3 <= row.LastCellNum) // 检查是否有足够的列
{
// 产品类型
string productType = row.GetCell(colIndex)?.ToString();
// 计划数量
int planNum = 0;
if (row.GetCell(colIndex + 1) != null)
{
planNum = (int)row.GetCell(colIndex + 1).NumericCellValue;
}
// 是否变更
string isChange = row.GetCell(colIndex + 2)?.ToString();
// 实际数量
int actualQt = 0;
if (row.GetCell(colIndex + 3) != null)
{
actualQt = (int)row.GetCell(colIndex + 3).NumericCellValue;
}
ProWeeklyDate weeklyDate = new ProWeeklyDate
{
Id = SnowFlakeSingle.Instance.NextId(),
FkWeeklyId = proWeeklyPlan.Id,
PlanCode = proWeeklyPlan.PlanCode,
WeekDate = date,
DayOfWeek = dayName,
ProductType = productType,
PlanNum = planNum,
IsChange = isChange,
ActualQt = actualQt,
CreatedTime = DateTime.Now,
CreateBy = username
};
weeklyDates.Add(weeklyDate);
}
}
return (proWeeklyPlan, weeklyDates);
}
catch (Exception ex)
{
// 记录错误但继续处理其他行
Console.WriteLine($"处理行数据时出错: {ex.Message}");
return (null, null);
}
}
/// <summary>
/// 批量处理数据并执行数据库操作
/// </summary>
/// <param name="weeklyPlans">周计划列表</param>
/// <param name="weeklyDates">日期计划列表</param>
/// <param name="year">年份</param>
/// <param name="week">周数</param>
private void ProcessBatchData(List<ProWeeklyPlan> weeklyPlans, List<ProWeeklyDate> weeklyDates, int year, int week)
{
if (!weeklyPlans.Any()) return;
UseTran2(() =>
{
// 如果是第一批数据,删除本周的旧数据
if (weeklyPlans.Count <= BATCH_SIZE * 2) // 简单判断是否为第一批
{
Context.Deleteable<ProWeeklyPlan>().Where(p => p.PlanYear == year && p.PlanWeek == week).ExecuteCommand();
// 不需要单独删除ProWeeklyDate因为它们通过外键关联会被级联删除
}
// 批量插入周计划
if (weeklyPlans.Any())
{
Context.Insertable(weeklyPlans).ExecuteCommand();
}
// 批量插入日期计划
if (weeklyDates.Any())
{
// 分批插入每批最多2000条记录
const int MAX_BATCH_INSERT = 2000;
for (int i = 0; i < weeklyDates.Count; i += MAX_BATCH_INSERT)
{
var batch = weeklyDates.Skip(i).Take(MAX_BATCH_INSERT).ToList();
if (batch.Any())
{
Context.Insertable(batch).ExecuteCommand();
}
}
}
});
}
public PagedInfo<ProWeeklyPlanChildDateDto> SearchWeekplan(WeekplanQueryDto weekplanQuery)
{
if (weekplanQuery == null)
{
return null;
}
return Context.Queryable<ProWeeklyPlan>()
.WhereIF(weekplanQuery.year > 0, p => p.PlanYear == weekplanQuery.year)
.WhereIF(weekplanQuery.week > 0, p => p.PlanWeek == weekplanQuery.week)
.WhereIF(!string.IsNullOrEmpty(weekplanQuery.partnumber), p => p.ProductCode.Contains(weekplanQuery.partnumber))
.Select(p => new ProWeeklyPlanChildDateDto()
{
Id = p.Id,
PlanCode = p.PlanCode,
PlanYear = p.PlanYear,
PlanWeek = p.PlanWeek,
PlanStartDate = p.PlanStartDate,
PlanEndDate = p.PlanEndDate,
OrderCode = p.OrderCode,
ProductCode = p.ProductCode,
ProductName = p.ProductName,
Specification = p.Specification,
Color = p.Color,
PlanQty = p.PlanQty,
CompletedQty = p.CompletedQty,
RemainingQty = p.PlanQty - p.CompletedQty, // 若数据库中没有,可在此计算
ScrapQty = p.ScrapQty,
WorkshopCode = p.WorkshopCode,
WorkshopName = p.WorkshopName,
LineCode = p.LineCode,
LineName = p.LineName,
GroupCode = p.GroupCode,
GroupName = p.GroupName,
ShiftType = p.ShiftType,
PlanStatus = p.PlanStatus,
Planner = p.Planner,
Priority = p.Priority,
Sort = p.Sort,
MaterialReady = p.MaterialReady,
Remark = p.Remark,
CreatedBy = p.CreatedBy,
CreatedTime = p.CreatedTime, // 假设 p 中有此字段,否则用 DateTime.Now
UpdatedBy = p.UpdatedBy,
UpdatedTime = p.UpdatedTime,
proWeeklyDatechildList = SqlFunc.Subqueryable<ProWeeklyDate>()
.Where(d => d.PlanCode == p.PlanCode)
.ToList()
}).ToPage_NO_Convert(weekplanQuery);
}
public int UpdateActualAssemblyProgress(int year, int week)
{
int result = 0;
// 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 = 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
{
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;
}
private int extractWeek(string title)
{
global::System.Text.RegularExpressions.Match match = Regex.Match(title, @"[(](\d+)[)]");
if (match.Success)
{
string numberStr = match.Groups[1].Value; // 获取第一个捕获组中的内容,即数字部分
if (int.TryParse(numberStr, out int weekNumber))
{
Console.WriteLine("提取到的周数是: " + weekNumber); // 输出: 35
return weekNumber;
}
else
{
Console.WriteLine("括号内不是有效的数字。");
return -1;
}
}
else
{
Console.WriteLine("未找到括号内的数字。");
return -1;
}
}
/// <summary>
/// 导出日计划
/// </summary>
/// <param name="year"></param>
/// <param name="week"></param>
/// <param name="dayofweek"></param>
(byte[] fileBytes, string fileName) IProweekplanManageService.ExportWeekDatePlan(int year, int week, string dayofweek)
{
// 1. 查询数据:周日计划及关联日期数据
List<ProWeeklyPlanAndDateDto> ProWeeklyPlanAndDateList = Context.Queryable<ProWeeklyPlan>()
.LeftJoin<ProWeeklyDate>((p, d) => p.PlanCode == d.PlanCode)
.WhereIF(year > 0, (p, d) => p.PlanYear == year)
.WhereIF(week > 0, (p, d) => p.PlanWeek == week)
.WhereIF(!string.IsNullOrEmpty(dayofweek), (p, d) => d.DayOfWeek == dayofweek)
.Select((p, d) => new ProWeeklyPlanAndDateDto
{
// ProWeeklyPlan 字段p
ProWeeklyPlanId = p.Id,
PlanCode = p.PlanCode,
PlanYear = p.PlanYear,
PlanWeek = p.PlanWeek,
PlanStartDate = p.PlanStartDate,
PlanEndDate = p.PlanEndDate,
OrderCode = p.OrderCode,
ProductCode = p.ProductCode,
ProductName = p.ProductName,
Specification = p.Specification,
Color = p.Color,
PlanQty = p.PlanQty,
CompletedQty = p.CompletedQty,
RemainingQty = p.PlanQty - p.CompletedQty,
ScrapQty = p.ScrapQty,
WorkshopCode = p.WorkshopCode,
WorkshopName = p.WorkshopName,
LineCode = p.LineCode,
LineName = p.LineName,
GroupCode = p.GroupCode,
GroupName = p.GroupName,
ShiftType = p.ShiftType,
PlanStatus = p.PlanStatus,
Planner = p.Planner,
Priority = p.Priority,
Sort = p.Sort,
MaterialReady = p.MaterialReady,
Remark = p.Remark,
ProWeeklyPlanCreatedBy = p.CreatedBy,
ProWeeklyPlanCreatedTime = p.CreatedTime,
ProWeeklyPlanUpdatedBy = p.UpdatedBy,
ProWeeklyPlanUpdatedTime = p.UpdatedTime,
// ProWeeklyDate 字段d
ProWeeklyDateId = d.Id,
FkWeeklyId = d.FkWeeklyId,
ProWeeklyPlanPlanCode = d.PlanCode,
WeekDate = d.WeekDate,
DayOfWeek = d.DayOfWeek,
ProductType = d.ProductType,
PlanNum = d.PlanNum,
IsChange = d.IsChange,
ActualQt = d.ActualQt,
CreateBy = d.CreateBy,
CreatedTime = d.CreatedTime,
UpdateBy = d.UpdateBy,
UpdatedTime = d.UpdatedTime
})
.ToList();
// 2. 转为工单列表(可选,如果你后续要用,目前你只是导出 Excel
List<ProWorkorder> proWorkorderList = new List<ProWorkorder>();
if (ProWeeklyPlanAndDateList != null && ProWeeklyPlanAndDateList.Count > 0)
{
foreach (var item in ProWeeklyPlanAndDateList)
{
ProWorkorder proWorkorder = new ProWorkorder
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
Workorder = string.Empty,
ProductionCode = item.ProductCode,
ProductionName = item.ProductName,
Specification = item.Specification,
DeliveryNum = item.PlanNum
};
proWorkorderList.Add(proWorkorder);
}
}
// 3. 读取 Excel 模板
IWebHostEnvironment webHostEnvironment = (IWebHostEnvironment)App.ServiceProvider.GetService(typeof(IWebHostEnvironment));
string fileName = "workorder"; // 模板文件名(不含扩展名)
string sFileName = $"{fileName}.xlsx";
string fullPath = Path.Combine(webHostEnvironment.WebRootPath, "ImportTemplate", sFileName);
if (!global::System.IO.File.Exists(fullPath))
{
throw new CustomException("Excel 模板文件未找到,请确保 ImportTemplate/workorder.xlsx 存在");
}
// 4. 加载模板 workbook
using (FileStream fileStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read))
{
IWorkbook workbook = new XSSFWorkbook(fileStream);
ISheet sheet = workbook.GetSheet("Sheet1");
if (sheet == null)
{
throw new CustomException("未找到 Sheet1请检查 Excel 模板");
}
// 5. 填充数据从第4行开始即索引 3
int dataRowIndex = 3;
// 可选:在第一行写入当前时间(比如 A2 单元格)
if (sheet.GetRow(1) != null)
{
sheet.GetRow(1).CreateCell(0).SetCellValue(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
}
// 6. 遍历工单数据,填充每一行
foreach (var item in proWorkorderList)
{
IRow dataRow = sheet.GetRow(dataRowIndex) ?? sheet.CreateRow(dataRowIndex);
dataRow.CreateCell(0).SetCellValue(item.ProductionCode); // A列
dataRow.CreateCell(1).SetCellValue(item.ProductionName); // B列
dataRow.CreateCell(2).SetCellValue(item.Specification); // C列
dataRow.CreateCell(4).SetCellValue((double)item.DeliveryNum); // D列
dataRowIndex++;
}
// 7. 写入到 MemoryStream关键不要用 using 包裹,否则流会被释放!)
var memoryStream = new MemoryStream();
workbook.Write(memoryStream);
// 8. 返回 byte[] 和文件名
return (memoryStream.ToArray(), "导出数据.xlsx");
}
}
}
}