881 lines
44 KiB
C#
881 lines
44 KiB
C#
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");
|
||
}
|
||
}
|
||
}
|
||
}
|