shgx_tz_mom/ZR.Service/mes/qc/QcGp12Service.cs

931 lines
37 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 System;
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Transactions;
using Aliyun.OSS;
using AutoMapper;
using Infrastructure.Attribute;
using Infrastructure.Extensions;
using JinianNet.JNTemplate;
using Microsoft.AspNetCore.Http.HttpResults;
using SqlSugar;
using ZR.Model;
using ZR.Model.Business;
using ZR.Model.Dto;
using ZR.Model.MES.wms;
using ZR.Repository;
using ZR.Service.Business.IBusinessService;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace ZR.Service.Business
{
/// <summary>
/// 质量GP12工单业务模块Service业务层处理
/// </summary>
[AppService(ServiceType = typeof(IQcGp12Service), ServiceLifetime = LifeTime.Transient)]
public class QcGp12Service : BaseService<QcGp12ServiceWorkorder>, IQcGp12Service
{
public QcGp12LabelAnalysisDto AnalyzeLabelToDto(string label, int type)
{
QcGp12LabelAnalysisDto labelAnalysisDto =
new()
{
IsOk = true,
Msg = "解析成功!",
LabelCode = label,
};
// 判断内外箱标签
// 解析零件号
labelAnalysisDto.Partnumber = DoAnalyzePartnumber(label);
// 解析数量
labelAnalysisDto.Number = DoAnalyzeQuantity(label);
if (string.IsNullOrEmpty(labelAnalysisDto.Partnumber))
{
labelAnalysisDto.IsOk = false;
labelAnalysisDto.Msg = "标签,零件号解析异常!";
}
// TYPE === 1 时,同时根据物料清单获取详细信息
if (type == 1)
{
WmMaterial material = Context
.Queryable<WmMaterial>()
.Where(it => it.Partnumber == labelAnalysisDto.Partnumber)
.Where(it => it.Type == 1)
.Where(it => it.Status == 1)
.First();
if (material == null)
{
labelAnalysisDto.IsOk = false;
labelAnalysisDto.Msg = "物料清单内无此零件号!请检查物料清单:" + labelAnalysisDto.Partnumber;
}
else
{
labelAnalysisDto.Color = material.Color;
labelAnalysisDto.Specification = material.Specification;
labelAnalysisDto.Description = !string.IsNullOrEmpty(material.Description)
? material.Description
: material.ProductName;
}
}
return labelAnalysisDto;
}
// 标签的零件号解析
public string DoAnalyzePartnumber(string label)
{
// 通用规则下的标签零件号抓取
var predicate = Expressionable
.Create<QcGp12BaseLabelAnalysis>()
.And(it => it.Code == "PartNumber")
.And(it => it.Status == "1");
List<QcGp12BaseLabelAnalysis> analysisList = Context
.Queryable<QcGp12BaseLabelAnalysis>()
.Where(predicate.ToExpression())
.ToList();
foreach (QcGp12BaseLabelAnalysis analysis in analysisList)
{
if (string.IsNullOrEmpty(analysis.Expression))
{
continue;
}
// 零件号正则表达式
Regex pattern = new(@analysis.Expression);
Match match = pattern.Match(label);
if (match.Success && match.Groups.Count > 1)
{
return match.Groups[1].Value;
}
}
// 非通用规则下的标签零件号抓取
// 解析T58门把手产品标签
try
{
// 直接从标签中截取前 15 个字符作为零件号
if (!string.IsNullOrEmpty(label) && label.Length >= 40 && label.EndsWith('$'))
{
return label.Substring(0, 17);
}
}
catch (Exception)
{
return "";
}
return "";
}
// 标签的数量解析
public int DoAnalyzeQuantity(string label)
{
int result = 0;
// 标签零件号抓取
var predicate = Expressionable
.Create<QcGp12BaseLabelAnalysis>()
.And(it => it.Code == "Quantity")
.And(it => it.Status == "1");
List<QcGp12BaseLabelAnalysis> analysisList = Context
.Queryable<QcGp12BaseLabelAnalysis>()
.Where(predicate.ToExpression())
.ToList();
foreach (QcGp12BaseLabelAnalysis analysis in analysisList)
{
if (string.IsNullOrEmpty(analysis.Expression))
{
continue;
}
// 零件号正则表达式
Regex pattern = new(@analysis.Expression);
Match match = pattern.Match(label);
if (match.Success && match.Groups.Count > 1)
{
if (Int32.TryParse(match.Groups[1].Value, out result))
{
return result;
}
else
{
return -1;
}
}
}
return -1;
}
public List<QcGp12AlterationDefectDto> GetDefectInitOptions()
{
List<QcGp12AlterationDefectDto> defectList = new();
var predicate = Expressionable.Create<QcGp12BaseDefect>().And(it => it.Status == "1");
/*List<string> groupList = Context
.Queryable<QcGp12BaseDefect>()
.Where(predicate.ToExpression())
.GroupBy(it => it.Group)
.Select(it => it.Group)
.ToList();*/
List<string> groupList = new()
{
"油漆",
"设备",
"毛坯",
"程序",
"班组操作"
};
foreach (string group in groupList)
{
QcGp12AlterationDefectDto defectDto = new();
defectDto.GroupName = group;
List<QcGp12ChildrenDefectDto> children = Context
.Queryable<QcGp12BaseDefect>()
.Where(it => it.Group == group)
.Where(predicate.ToExpression())
.Select(it => new QcGp12ChildrenDefectDto
{
Name = it.Name,
Code = it.Code,
Type = it.Type,
Num = 0
})
.ToList();
defectDto.Children = children;
defectList.Add(defectDto);
}
return defectList;
}
public List<QcGp12AlterationDefectDto> GetDefectTableOptions()
{
List<QcGp12AlterationDefectDto> defectList = new();
var predicate = Expressionable
.Create<QcGp12BaseDefect>()
.And(it => it.Type == "打磨")
.And(it => it.Status == "1");
/* List<string> groupList = Context
.Queryable<QcGp12BaseDefect>()
.Where(predicate.ToExpression())
.GroupBy(it => it.Group)
.Select(it => it.Group)
.ToList();*/
List<string> groupList = new()
{
"油漆",
"设备",
"毛坯",
"程序",
"班组操作"
};
foreach (string group in groupList)
{
QcGp12AlterationDefectDto defectDto = new();
defectDto.GroupName = group;
List<QcGp12ChildrenDefectDto> children = Context
.Queryable<QcGp12BaseDefect>()
.Where(it => it.Group == group)
.Where(predicate.ToExpression())
.Select(it => new QcGp12ChildrenDefectDto
{
Name = it.Name,
Code = SqlFunc.IIF(
SqlFunc.Length(it.Code) >= 2,
SqlFunc.MergeString(
SqlFunc.Substring(it.Code, 0, 1), // 获取第一个字符注意SQL 中索引通常从1开始
SqlFunc.Substring(it.Code, SqlFunc.Length(it.Code) - 1, 1) // 获取最后一个字符
),
it.Code
),
Type = it.Type,
Num = 0
})
.ToList();
defectDto.Children = children;
defectList.Add(defectDto);
}
return defectList;
}
public List<QcGp12BaseGroupDto> GetGroupOptions()
{
var predicate = Expressionable.Create<QcGp12BaseGroup>().And(it => it.Status == "1");
var response = Context
.Queryable<QcGp12BaseGroup>()
.Where(predicate.ToExpression())
.Select(it => new QcGp12BaseGroupDto())
.ToList();
return response;
}
public List<QcGp12BaseSiteDto> GetStieOptions()
{
var predicate = Expressionable.Create<QcGp12BaseSite>().And(it => it.Status == "1");
var response = Context
.Queryable<QcGp12BaseSite>()
.Where(predicate.ToExpression())
.Select(it => new QcGp12BaseSiteDto())
.ToList();
return response;
}
public QcGp12ServiceWorkorder StartGP12WorkOrder(QcGp12WorkorderDetailDto data)
{
// 检查是否是已扫过的外箱标签
QcGp12ServiceWorkorder oldWorkOrder = Context
.Queryable<QcGp12ServiceWorkorder>()
.Where(it => it.Label == data.Label)
.First();
if (oldWorkOrder != null)
{
return oldWorkOrder;
}
// 没有旧记录则开启新的记录
try
{
// 检查箱标签是否当内标签扫过
bool isInnerLabelScan = Context
.Queryable<QcGp12RecordLabelScan>()
.Where(it => it.Label == data.Label)
.Where(it => it.LabelType == 2)
.Any();
if (isInnerLabelScan)
{
throw new Exception("标签异常,该标签已经当内标签扫过!");
}
Context.Ado.BeginTran();
DateTime nowTime = DateTime.Now;
// 创建新工单号
QcGp12WorkorderDetailDto workorderInfo = GetNewWorkOrderCreate(data);
// 赋值
data.WorkOrder = workorderInfo.WorkOrder;
data.SerialNumber = workorderInfo.SerialNumber;
data.StartTime = nowTime;
QcGp12ServiceWorkorder newModel = GetNewWorkOrderInfo(data);
QcGp12ServiceWorkorder result = Context.Insertable(newModel).ExecuteReturnEntity();
if (result == null)
{
Context.Ado.RollbackTran();
throw new Exception("插入新工单异常");
}
// 工单开始记录
QcGp12RecordLabelScan newScanLabelRecord =
new()
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
WorkOrder = result.WorkOrder,
PartNumber = result.PartNumber,
Team = result.Team,
SiteNo = result.SiteNo,
ComNo = result.ComNo,
Label = result.Label,
LabelType = 1,
LabelSort = 1,
ScanTime = $"{nowTime:yyyy-MM-dd HH:mm:ss}",
Type = "1",
Status = "1",
Remark = "新工单创建扫描箱标签",
CreatedBy = "后台系统",
CreatedTime = nowTime,
};
int res = Context.Insertable(newScanLabelRecord).ExecuteCommand();
if (res == 0)
{
Context.Ado.RollbackTran();
throw new Exception("插入标签记录异常");
}
QcGp12LogWorkorder qcGp12Log =
new()
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
Name = "工单开始",
Content = $"工单:{result.WorkOrder}开始,开始时间{nowTime:yyyy-MM-dd HH:mm:ss}",
Type = "100",
Status = "1",
Remark = "触摸屏操作记录",
CreatedBy = "系统",
CreatedTime = nowTime
};
Context.Insertable(qcGp12Log).ExecuteCommand();
Context.Ado.CommitTran();
return result;
}
catch (Exception ex)
{
Context.Ado.RollbackTran();
throw new Exception(ex.Message);
}
}
// 创建新工单号
public QcGp12WorkorderDetailDto GetNewWorkOrderCreate(QcGp12WorkorderDetailDto data)
{
QcGp12WorkorderDetailDto result = new();
string newWorkOrder = "";
DateTime today = DateTime.Today;
// 检查是否是已扫过的外箱标签
QcGp12ServiceWorkorder lastWorkOrder = Context
.Queryable<QcGp12ServiceWorkorder>()
.Where(it => it.CreatedTime.Value.Date == today)
.OrderByDescending(it => it.SerialNumber)
.First();
if (lastWorkOrder != null)
{
// 递增序列号
int sequenceNumber = lastWorkOrder.SerialNumber + 1;
if (data.IsOnetime == 1)
{
newWorkOrder = $"W{today:yyyyMMdd}{sequenceNumber:D3}";
}
else if (data.IsPolish == 1)
{
newWorkOrder = $"P{today:yyyyMMdd}{sequenceNumber:D3}";
}
else
{
newWorkOrder = $"{today:yyyyMMdd}{sequenceNumber:D3}";
}
result.SerialNumber = sequenceNumber;
}
else
{
// 如果今天还没有创建过工单,则从 "001" 开始
if (data.IsOnetime == 1)
{
newWorkOrder = $"W{today:yyyyMMdd}001";
}
else if (data.IsPolish == 1)
{
newWorkOrder = $"P{today:yyyyMMdd}001";
}
else
{
newWorkOrder = $"{today:yyyyMMdd}001";
}
result.SerialNumber = 1;
}
result.WorkOrder = newWorkOrder;
return result;
}
public static QcGp12ServiceWorkorder GetNewWorkOrderInfo(QcGp12WorkorderDetailDto data)
{
// 新工单
QcGp12ServiceWorkorder model =
new()
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
WorkOrder = data.WorkOrder,
SerialNumber = data.SerialNumber,
PartNumber = data.PartNumber,
Specification = data.Specification,
Color = data.Color,
Description = data.Description,
Team = data.Team,
SiteNo = data.SiteNo,
ComNo = data.ComNo,
IsOnetime = data.IsOnetime,
IsPolish = data.IsPolish,
IsBack = data.IsBack,
IsOut = data.IsOut,
StartTime = data.StartTime,
EndTime = null,
Label = data.Label,
RequireNumber = 0,
QualifiedNumber = 0,
PolishNumber = 0,
DamoNumber = 0,
BaofeiNumber = 0,
Type = "1",
Status = "1",
Remark = "系统新增工单",
CreatedBy = data.CreatedBy,
CreatedTime = data.CreatedTime,
UpdatedBy = data.UpdatedBy,
UpdatedTime = data.UpdatedTime
};
return model;
}
public QcGp12ServiceWorkorder ChangeWorkOrderDefect(QcGp12WorkorderDefectDto data)
{
try
{
if(string.IsNullOrEmpty(data.DefectCode))
{
throw new Exception("缺陷项传入为空!");
}
Context.Ado.BeginTran();
DateTime nowTime = DateTime.Now;
// 获取缺陷信息
QcGp12BaseDefect defect = Context
.Queryable<QcGp12BaseDefect>()
.Where(it => it.Code == data.DefectCode && it.Status == "1")
.First();
if (defect == null)
{
throw new Exception("缺陷项不在缺陷清单中!");
}
// 工单信息修改
QcGp12ServiceWorkorder qcGp12Workorder = Context
.Queryable<QcGp12ServiceWorkorder>()
.Where(it => it.WorkOrder == data.WorkOrder)
.First();
if (qcGp12Workorder == null)
{
throw new Exception("工单不存在!");
}
// 获取当前工作单缺陷记录
QcGp12RecordWorkorderDefect workOrderDefect = Context
.Queryable<QcGp12RecordWorkorderDefect>()
.Where(it => it.WorkOrder == data.WorkOrder && it.DefectCode == data.DefectCode)
.First();
if (data.Type == "1")
{
// Type === 1 短按新增
if (workOrderDefect != null)
{
// 数据库中有记录DefectNum + 1
workOrderDefect.DefectNum += 1;
workOrderDefect.UpdatedTime = data.CreatedTime;
workOrderDefect.UpdatedBy = data.CreatedBy;
Context.Updateable(workOrderDefect).ExecuteCommand();
}
else
{
// 数据库中无记录,新增记录并设置 DefectNum = 1
workOrderDefect = new QcGp12RecordWorkorderDefect
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
WorkOrder = data.WorkOrder,
PartNumber = qcGp12Workorder.PartNumber,
Team = qcGp12Workorder.Team,
SiteNo = qcGp12Workorder.SiteNo,
ComNo = qcGp12Workorder.ComNo,
DefectName = defect.Name,
DefectCode = data.DefectCode,
DefectType = defect.Type,
ClickTime = $"{nowTime:yyyy-MM-dd HH:mm:ss}",
Type = "1",
Status = "1",
Remark = "",
CreatedBy = data.CreatedBy,
CreatedTime = data.CreatedTime,
DefectNum = 1
};
Context.Insertable(workOrderDefect).ExecuteCommand();
}
}
else if (data.Type == "2")
{
// Type == 2 长按修改
if (workOrderDefect != null)
{
// 数据库中有记录,直接赋值
workOrderDefect.UpdatedTime = data.CreatedTime;
workOrderDefect.UpdatedBy = data.CreatedBy;
workOrderDefect.DefectNum = data.DefectNum; // 假设 data.DefectNum 存在
Context.Updateable(workOrderDefect).ExecuteCommand();
}
else
{
// 数据库中无记录,新增记录
workOrderDefect = new QcGp12RecordWorkorderDefect
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
WorkOrder = data.WorkOrder,
PartNumber = qcGp12Workorder.PartNumber,
Team = qcGp12Workorder.Team,
SiteNo = qcGp12Workorder.SiteNo,
ComNo = qcGp12Workorder.ComNo,
DefectName = defect.Name,
DefectCode = data.DefectCode,
DefectType = defect.Type,
ClickTime = $"{nowTime:yyyy-MM-dd HH:mm:ss}",
Type = "1",
Status = "1",
Remark = "",
CreatedBy = data.CreatedBy,
CreatedTime = data.CreatedTime,
DefectNum = data.DefectNum // 假设 data.DefectNum 存在
};
Context.Insertable(workOrderDefect).ExecuteCommand();
}
}
UpdateWorkOrderDetail(data.WorkOrder);
// 提交事务
Context.Ado.CommitTran();
return qcGp12Workorder;
}
catch (Exception ex)
{
// 回滚事务
Context.Ado.RollbackTran();
throw new Exception("操作失败!", ex);
}
}
public List<QcGp12RecordWorkorderDefect> GetWorkOrderDefectList(string workorder)
{
return Context
.Queryable<QcGp12RecordWorkorderDefect>()
.Where(it => it.WorkOrder == workorder)
.ToList();
}
public QcGp12ServiceWorkorder UpdateWorkOrderDetail(string workorder)
{
QcGp12ServiceWorkorder qcGp12Workorder = Context
.Queryable<QcGp12ServiceWorkorder>()
.Where(it => it.WorkOrder == workorder)
// .Where(it=>it.Status == "1")
.First();
// 更新工单中的统计数据
qcGp12Workorder.QualifiedNumber = Context
.Queryable<QcGp12RecordLabelScan>()
.Where(it => it.WorkOrder == workorder)
.Where(it => it.LabelType == 2)
.Count();
qcGp12Workorder.PolishNumber =
Context
.Queryable<QcGp12RecordWorkorderDefect>()
.Where(it => it.WorkOrder == workorder && it.DefectType == "抛光")
.Sum(it => it.DefectNum) ?? 0;
qcGp12Workorder.DamoNumber =
Context
.Queryable<QcGp12RecordWorkorderDefect>()
.Where(it => it.WorkOrder == workorder && it.DefectType == "打磨")
.Sum(it => it.DefectNum) ?? 0;
qcGp12Workorder.BaofeiNumber =
Context
.Queryable<QcGp12RecordWorkorderDefect>()
.Where(it => it.WorkOrder == workorder && it.DefectType == "报废")
.Sum(it => it.DefectNum) ?? 0;
qcGp12Workorder.RequireNumber =
qcGp12Workorder.PolishNumber
+ qcGp12Workorder.DamoNumber
+ qcGp12Workorder.BaofeiNumber
+ (qcGp12Workorder.QualifiedNumber ?? 0);
// 更新工单统计信息到数据库
Context
.Updateable(qcGp12Workorder)
.UpdateColumns(it => new
{
it.RequireNumber,
it.QualifiedNumber,
it.PolishNumber,
it.DamoNumber,
it.BaofeiNumber
})
.ExecuteCommand();
return qcGp12Workorder;
}
public string ScanInnerLabel(QcGp12LabelScanDto data)
{
DateTime nowTime = DateTime.Now;
// 标签防错 (内标签零件号)
string partNumber = DoAnalyzePartnumber(data.Label);
// 内标签包含外标签
if (!partNumber.Contains(data.PartNumber))
{
return "内标签零件号与外箱标签不一致!";
}
bool hasAny = Context
.Queryable<QcGp12RecordLabelScan>()
.Where(it => it.Label == data.Label)
.Any();
if (hasAny)
{
return "重复扫码!";
}
// 标签录入
int sort = 0;
QcGp12RecordLabelScan labelScan = Context
.Queryable<QcGp12RecordLabelScan>()
.Where(it => it.WorkOrder == data.WorkOrder)
.Where(it => it.LabelType == 2)
.OrderByDescending(it => it.LabelSort)
.First();
if (labelScan != null)
{
sort = labelScan.LabelSort ?? 0;
}
QcGp12RecordLabelScan newLabelScran =
new()
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
WorkOrder = data.WorkOrder,
PartNumber = data.PartNumber,
Team = data.Team,
SiteNo = data.SiteNo,
ComNo = data.ComNo,
Label = data.Label,
LabelType = 2,
LabelSort = sort + 1,
ScanTime = $"{nowTime:yyyy-MM-dd HH:mm:ss}",
Type = "1",
Status = "1",
Remark = "扫描标签",
CreatedBy = data.CreatedBy,
CreatedTime = data.CreatedTime,
};
int res = Context.Insertable(newLabelScran).ExecuteCommand();
if (res == 0)
{
return "标签录入系统失败!";
}
return "ok";
}
public string EndGP12WorkOrderAndCreateStatistics(string workorder)
{
try
{
Context.Ado.BeginTran();
DateTime nowTime = DateTime.Now;
// 工单信息修改
QcGp12ServiceWorkorder qcGp12Workorder = Context
.Queryable<QcGp12ServiceWorkorder>()
.Where(it => it.WorkOrder == workorder)
.First();
if (qcGp12Workorder == null)
{
throw new Exception("工单不存在!");
}
qcGp12Workorder.EndTime = nowTime;
qcGp12Workorder.Type = "2";
if (!qcGp12Workorder.Remark.Contains("已生成过报表"))
{
qcGp12Workorder.Remark += "已生成过报表";
}
Context.Updateable(qcGp12Workorder).ExecuteCommand();
// 生成报表记录
List<QcGp12ServiceStatistics> addList = new();
string groupCode = SnowFlakeSingle.Instance.NextId().ToString();
addList.Add(CreateNewStatistics(qcGp12Workorder, groupCode, 1));
addList.Add(CreateNewStatistics(qcGp12Workorder, groupCode, 2));
addList.Add(CreateNewStatistics(qcGp12Workorder, groupCode, 3));
Context
.Deleteable<QcGp12ServiceStatistics>()
.Where(it => it.WorkOrder == workorder)
.ExecuteCommand();
Context.Insertable(addList).ExecuteCommand();
QcGp12LogWorkorder qcGp12Log =
new()
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
Name = "工单结束",
Content = $"工单:{workorder}结束,结束时间{nowTime:yyyy-MM-dd HH:mm:ss}",
Type = "200",
Status = "1",
Remark = "触摸屏操作记录",
CreatedBy = "系统",
CreatedTime = nowTime
};
Context.Insertable(qcGp12Log).ExecuteCommand();
// 提交事务
Context.Ado.CommitTran();
return "ok";
}
catch (Exception ex)
{
// 回滚事务
Context.Ado.RollbackTran();
return ex.Message;
}
}
public QcGp12ServiceStatistics CreateNewStatistics(
QcGp12ServiceWorkorder data,
string groupCode,
int groupSort
)
{
List<QcGp12RecordWorkorderDefect> defectList = Context
.Queryable<QcGp12RecordWorkorderDefect>()
.Where(it => it.WorkOrder == data.WorkOrder)
.WhereIF(groupSort == 1, it => it.DefectType == "抛光")
.WhereIF(groupSort == 2, it => it.DefectType == "打磨")
.WhereIF(groupSort == 3, it => it.DefectType == "报废")
.ToList();
string JsonString = JsonSerializer.Serialize(defectList);
// 计算合格率
string qualifiedRate = CalculateQualifiedRate(data);
DateTime nowTime = DateTime.Now;
QcGp12ServiceStatistics workorderStatistics =
new()
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
WorkOrder = data.WorkOrder,
PartNumber = data.PartNumber,
Specification = data.Specification,
Color = data.Color,
Description = data.Description,
Team = data.Team,
SiteNo = data.SiteNo,
ComNo = data.ComNo,
IsOnetime = data.IsOnetime,
IsPolish = data.IsPolish,
IsBack = data.IsBack,
IsOut = data.IsOut,
StartTime = data.StartTime,
EndTime = data.EndTime,
Label = data.Label,
RequireNumber = data.RequireNumber,
QualifiedNumber = data.QualifiedNumber,
QualifiedRate = qualifiedRate,
PolishNumber = data.PolishNumber,
DamoNumber = data.DamoNumber,
BaofeiNumber = data.BaofeiNumber,
GroupCode = groupCode,
GroupSort = groupSort,
GroupDefectJson = JsonString,
Type = "1",
Status = "1",
Remark = "结束工单系统新增质量报表",
CreatedBy = "后端",
CreatedTime = nowTime,
};
return workorderStatistics;
}
public static string CalculateQualifiedRate(QcGp12ServiceWorkorder data)
{
if (data == null || data.RequireNumber <= 0)
{
return "0%";
}
double qualifiedRate =
(double)data.QualifiedNumber.Value / data.RequireNumber.Value * 100;
return $"{qualifiedRate:F1}%";
}
public QcGp12ServiceWorkorder GenerateVirtualLabel(QcGp12WorkorderDetailDto workorderDetail)
{
try
{
Context.Ado.BeginTran();
// 检查当前工单已扫码合格数
int qualifiedNumber = workorderDetail.QualifiedNumber ?? -1;
if (qualifiedNumber < 0)
{
throw new ArgumentException("传入合格数异常!", nameof(workorderDetail.QualifiedNumber));
}
int labelCount = GetLabelCountForWorkOrder(workorderDetail.WorkOrder);
if (labelCount < qualifiedNumber)
{
GenerateVirtualLabels(workorderDetail, qualifiedNumber - labelCount);
}
else if (labelCount > qualifiedNumber)
{
DeleteExcessLabels(workorderDetail.WorkOrder, labelCount - qualifiedNumber);
}
Context.Ado.CommitTran();
return UpdateWorkOrderDetail(workorderDetail.WorkOrder);
}
catch (Exception e)
{
Context.Ado.RollbackTran();
throw new Exception($"生成虚拟标签时出错: {e.Message}", e);
}
}
private int GetLabelCountForWorkOrder(string workOrder)
{
return Context.Queryable<QcGp12RecordLabelScan>()
.Where(it => it.WorkOrder == workOrder && it.LabelType == 2)
.Count();
}
private void GenerateVirtualLabels(QcGp12WorkorderDetailDto workOrderDetail, int countToGenerate)
{
List<QcGp12RecordLabelScan> virtualLabels = new List<QcGp12RecordLabelScan>();
int nextLabelNumber = GetNextLabelNumber(workOrderDetail.WorkOrder);
for (int i = 0; i < countToGenerate; i++)
{
string uniqueLabel = GenerateUniqueSequentialLabel(workOrderDetail.WorkOrder, nextLabelNumber++);
virtualLabels.Add(new QcGp12RecordLabelScan
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
WorkOrder = workOrderDetail.WorkOrder,
PartNumber = workOrderDetail.PartNumber,
Team = workOrderDetail.Team,
SiteNo = workOrderDetail.SiteNo,
ComNo = workOrderDetail.ComNo,
ScanTime = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"),
Type = "2",
Status = "1",
Remark = "虚拟标签",
CreatedTime = DateTime.UtcNow,
CreatedBy = "系统",
LabelType = 2,
LabelSort = nextLabelNumber,
Label = uniqueLabel
});
}
Context.Insertable(virtualLabels).ExecuteCommand();
}
private void DeleteExcessLabels(string workOrder, int countToDelete)
{
var labelsToDelete = Context.Queryable<QcGp12RecordLabelScan>()
.Where(it => it.WorkOrder == workOrder && it.LabelType == 2)
.OrderByDescending(it => it.LabelSort)
.Take(countToDelete)
.ToList();
Context.Deleteable(labelsToDelete).ExecuteCommand();
}
private int GetNextLabelNumber(string workOrder)
{
return Context.Queryable<QcGp12RecordLabelScan>()
.Where(it => it.WorkOrder == workOrder && it.LabelType == 2)
.Max(it => it.LabelSort ?? 0);
}
private string GenerateUniqueSequentialLabel(string workOrder, int number)
{
const string prefix = "VIRT";
string baseLabel = $"{prefix}-{GenerateUniqueId()}-{number:D5}";
string uniqueLabel = baseLabel;
while (IsLabelExists(workOrder, uniqueLabel))
{
uniqueLabel = $"{baseLabel}-{GenerateUniqueId()}";
}
return uniqueLabel;
}
private bool IsLabelExists(string workOrder, string label)
{
return Context.Queryable<QcGp12RecordLabelScan>()
.Any(it => it.WorkOrder == workOrder && it.LabelType == 2 && it.Label == label);
}
private string GenerateUniqueId()
{
return Guid.NewGuid().ToString("N").Substring(0, 10); // Generate a 10-character unique ID
}
}
}