shgx_tz_mom/ZR.Service/mes/qc/backend/QcBackEndService.cs

1071 lines
43 KiB
C#
Raw Normal View History

2025-01-03 16:43:02 +08:00
using System;
2025-01-07 17:25:08 +08:00
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
2025-01-07 17:25:08 +08:00
using System.Transactions;
using Aliyun.OSS;
using AutoMapper;
2025-01-03 16:43:02 +08:00
using Infrastructure.Attribute;
using Infrastructure.Extensions;
2025-01-07 17:25:08 +08:00
using JinianNet.JNTemplate;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.Extensions.Logging;
using MQTTnet.Protocol;
2025-01-07 17:25:08 +08:00
using SqlSugar;
using ZR.Common.MqttHelper;
2025-01-03 16:43:02 +08:00
using ZR.Model;
using ZR.Model.Business;
2025-01-07 17:25:08 +08:00
using ZR.Model.Dto;
using ZR.Model.MES.wms;
2025-01-03 16:43:02 +08:00
using ZR.Repository;
using ZR.Service.Business.IBusinessService;
2025-01-07 17:25:08 +08:00
using static System.Runtime.InteropServices.JavaScript.JSType;
2025-01-03 16:43:02 +08:00
namespace ZR.Service.Business
{
/// <summary>
2025-05-07 08:20:08 +08:00
/// 质量BackEnd工单业务模块Service业务层处理
2025-01-03 16:43:02 +08:00
/// </summary>
2025-05-07 08:20:08 +08:00
[AppService(ServiceType = typeof(IQcBackEndService), ServiceLifetime = LifeTime.Transient)]
public class QcBackEndService : BaseService<QcBackEndServiceWorkorder>, IQcBackEndService
2025-01-03 16:43:02 +08:00
{
private readonly MqttService _mqttService; // 注入MqttService
private readonly ILogger<QcBackEndService> _logger;
public QcBackEndService(MqttService mqttService, ILogger<QcBackEndService> logger)
{
_mqttService = mqttService;
_logger = logger;
}
2025-05-07 08:20:08 +08:00
public QcBackEndLabelAnalysisDto AnalyzeLabelToDto(string label, int type)
2025-01-03 16:43:02 +08:00
{
2025-05-07 08:20:08 +08:00
QcBackEndLabelAnalysisDto labelAnalysisDto =
2025-01-07 17:25:08 +08:00
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;
}
2025-01-14 09:40:33 +08:00
// 标签的零件号解析
2025-01-07 17:25:08 +08:00
public string DoAnalyzePartnumber(string label)
{
2025-04-23 16:33:36 +08:00
// 通用规则下的标签零件号抓取
2025-01-07 17:25:08 +08:00
var predicate = Expressionable
2025-05-07 08:20:08 +08:00
.Create<QcBackEndBaseLabelAnalysis>()
2025-01-03 16:43:02 +08:00
.And(it => it.Code == "PartNumber")
.And(it => it.Status == "1");
2025-05-07 08:20:08 +08:00
List<QcBackEndBaseLabelAnalysis> analysisList = Context
.Queryable<QcBackEndBaseLabelAnalysis>()
2025-01-03 16:43:02 +08:00
.Where(predicate.ToExpression())
.ToList();
2025-05-07 08:20:08 +08:00
foreach (QcBackEndBaseLabelAnalysis analysis in analysisList)
2025-01-03 16:43:02 +08:00
{
2025-01-07 17:25:08 +08:00
if (string.IsNullOrEmpty(analysis.Expression))
2025-01-03 16:43:02 +08:00
{
continue;
}
// 零件号正则表达式
2025-01-07 17:25:08 +08:00
Regex pattern = new(@analysis.Expression);
2025-01-03 16:43:02 +08:00
Match match = pattern.Match(label);
if (match.Success && match.Groups.Count > 1)
{
2025-01-07 17:25:08 +08:00
return match.Groups[1].Value;
2025-01-03 16:43:02 +08:00
}
}
2025-04-23 16:33:36 +08:00
// 非通用规则下的标签零件号抓取
// 解析T58门把手产品标签
try
{
// 直接从标签中截取前 15 个字符作为零件号
if (!string.IsNullOrEmpty(label) && label.Length >= 40 && label.EndsWith('$'))
{
return label.Substring(0, 17);
}
}
catch (Exception)
{
return "";
}
2025-01-07 17:25:08 +08:00
return "";
}
2025-01-14 09:40:33 +08:00
// 标签的数量解析
2025-01-07 17:25:08 +08:00
public int DoAnalyzeQuantity(string label)
{
int result = 0;
2025-01-14 09:40:33 +08:00
// 标签零件号抓取
2025-01-07 17:25:08 +08:00
var predicate = Expressionable
2025-05-07 08:20:08 +08:00
.Create<QcBackEndBaseLabelAnalysis>()
2025-01-07 17:25:08 +08:00
.And(it => it.Code == "Quantity")
.And(it => it.Status == "1");
2025-05-07 08:20:08 +08:00
List<QcBackEndBaseLabelAnalysis> analysisList = Context
.Queryable<QcBackEndBaseLabelAnalysis>()
2025-01-07 17:25:08 +08:00
.Where(predicate.ToExpression())
.ToList();
2025-05-07 08:20:08 +08:00
foreach (QcBackEndBaseLabelAnalysis analysis in analysisList)
2025-01-03 16:43:02 +08:00
{
2025-01-07 17:25:08 +08:00
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;
}
}
2025-01-03 16:43:02 +08:00
}
2025-01-07 17:25:08 +08:00
return -1;
2025-01-03 16:43:02 +08:00
}
2025-05-07 08:20:08 +08:00
public List<QcBackEndAlterationDefectDto> GetDefectInitOptions()
2025-01-03 16:43:02 +08:00
{
2025-05-07 08:20:08 +08:00
List<QcBackEndAlterationDefectDto> defectList = new();
var predicate = Expressionable
.Create<QcBackEndBaseDefect>()
.And(it => it.Status == "1");
2025-02-22 14:28:28 +08:00
/*List<string> groupList = Context
2025-05-07 08:20:08 +08:00
.Queryable<QcBackEndBaseDefect>()
2025-01-03 16:43:02 +08:00
.Where(predicate.ToExpression())
2025-01-07 17:25:08 +08:00
.GroupBy(it => it.Group)
2025-01-03 16:43:02 +08:00
.Select(it => it.Group)
2025-02-22 14:28:28 +08:00
.ToList();*/
List<string> groupList = new() { "油漆", "设备", "毛坯", "程序", "班组操作" };
2025-01-03 16:43:02 +08:00
foreach (string group in groupList)
{
2025-05-07 08:20:08 +08:00
QcBackEndAlterationDefectDto defectDto = new();
2025-01-03 16:43:02 +08:00
defectDto.GroupName = group;
2025-05-07 08:20:08 +08:00
List<QcBackEndChildrenDefectDto> children = Context
.Queryable<QcBackEndBaseDefect>()
2025-01-07 17:25:08 +08:00
.Where(it => it.Group == group)
.Where(predicate.ToExpression())
2025-05-07 08:20:08 +08:00
.Select(it => new QcBackEndChildrenDefectDto
2025-01-07 17:25:08 +08:00
{
Name = it.Name,
Code = it.Code,
Type = it.Type,
Num = 0
})
.ToList();
2025-01-03 16:43:02 +08:00
defectDto.Children = children;
defectList.Add(defectDto);
}
return defectList;
}
2025-05-07 08:20:08 +08:00
public List<QcBackEndAlterationDefectDto> GetDefectTableOptions()
2025-01-21 15:58:27 +08:00
{
2025-05-07 08:20:08 +08:00
List<QcBackEndAlterationDefectDto> defectList = new();
2025-01-21 15:58:27 +08:00
var predicate = Expressionable
2025-05-07 08:20:08 +08:00
.Create<QcBackEndBaseDefect>()
2025-01-21 15:58:27 +08:00
.And(it => it.Type == "打磨")
.And(it => it.Status == "1");
/* List<string> groupList = Context
.Queryable<QcBackEndBaseDefect>()
.Where(predicate.ToExpression())
.GroupBy(it => it.Group)
.Select(it => it.Group)
.ToList();*/
List<string> groupList = new() { "油漆", "设备", "毛坯", "程序", "班组操作" };
2025-01-21 15:58:27 +08:00
foreach (string group in groupList)
{
2025-05-07 08:20:08 +08:00
QcBackEndAlterationDefectDto defectDto = new();
2025-01-21 15:58:27 +08:00
defectDto.GroupName = group;
2025-05-07 08:20:08 +08:00
List<QcBackEndChildrenDefectDto> children = Context
.Queryable<QcBackEndBaseDefect>()
2025-01-21 15:58:27 +08:00
.Where(it => it.Group == group)
.Where(predicate.ToExpression())
2025-05-07 08:20:08 +08:00
.Select(it => new QcBackEndChildrenDefectDto
2025-01-21 15:58:27 +08:00
{
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;
}
2025-05-07 08:20:08 +08:00
public List<QcBackEndBaseGroupDto> GetGroupOptions()
2025-01-03 16:43:02 +08:00
{
2025-05-07 08:20:08 +08:00
var predicate = Expressionable.Create<QcBackEndBaseGroup>().And(it => it.Status == "1");
2025-01-03 16:43:02 +08:00
2025-01-07 17:25:08 +08:00
var response = Context
2025-05-07 08:20:08 +08:00
.Queryable<QcBackEndBaseGroup>()
2025-01-03 16:43:02 +08:00
.Where(predicate.ToExpression())
2025-05-07 08:20:08 +08:00
.Select(it => new QcBackEndBaseGroupDto())
2025-01-03 16:43:02 +08:00
.ToList();
return response;
}
2025-05-07 08:20:08 +08:00
public List<QcBackEndBaseSiteDto> GetStieOptions()
2025-01-03 16:43:02 +08:00
{
2025-05-07 08:20:08 +08:00
var predicate = Expressionable.Create<QcBackEndBaseSite>().And(it => it.Status == "1");
2025-01-03 16:43:02 +08:00
2025-01-07 17:25:08 +08:00
var response = Context
2025-05-07 08:20:08 +08:00
.Queryable<QcBackEndBaseSite>()
2025-01-03 16:43:02 +08:00
.Where(predicate.ToExpression())
2025-05-07 08:20:08 +08:00
.Select(it => new QcBackEndBaseSiteDto())
2025-01-03 16:43:02 +08:00
.ToList();
return response;
}
2025-01-07 17:25:08 +08:00
2025-05-07 08:20:08 +08:00
public QcBackEndServiceWorkorder StartBackEndWorkOrder(QcBackEndWorkorderDetailDto data)
2025-01-07 17:25:08 +08:00
{
// 检查是否是已扫过的外箱标签
2025-05-07 08:20:08 +08:00
QcBackEndServiceWorkorder oldWorkOrder = Context
.Queryable<QcBackEndServiceWorkorder>()
2025-01-07 17:25:08 +08:00
.Where(it => it.Label == data.Label)
.First();
if (oldWorkOrder != null)
{
return oldWorkOrder;
}
// 没有旧记录则开启新的记录
try
{
2025-02-14 17:26:56 +08:00
// 检查箱标签是否当内标签扫过
bool isInnerLabelScan = Context
2025-05-07 08:20:08 +08:00
.Queryable<QcBackEndRecordLabelScan>()
2025-02-14 17:26:56 +08:00
.Where(it => it.Label == data.Label)
.Where(it => it.LabelType == 2)
.Any();
if (isInnerLabelScan)
{
throw new Exception("标签异常,该标签已经当内标签扫过!");
}
2025-01-07 17:25:08 +08:00
Context.Ado.BeginTran();
DateTime nowTime = DateTime.Now;
// 创建新工单号
2025-05-07 08:20:08 +08:00
QcBackEndWorkorderDetailDto workorderInfo = GetNewWorkOrderCreate(data);
2025-01-07 17:25:08 +08:00
// 赋值
data.WorkOrder = workorderInfo.WorkOrder;
data.SerialNumber = workorderInfo.SerialNumber;
data.StartTime = nowTime;
2025-05-07 08:20:08 +08:00
QcBackEndServiceWorkorder newModel = GetNewWorkOrderInfo(data);
QcBackEndServiceWorkorder result = Context
.Insertable(newModel)
.ExecuteReturnEntity();
2025-01-07 17:25:08 +08:00
if (result == null)
{
Context.Ado.RollbackTran();
throw new Exception("插入新工单异常");
}
// 工单开始记录
2025-05-07 08:20:08 +08:00
QcBackEndRecordLabelScan newScanLabelRecord =
2025-01-07 17:25:08 +08:00
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("插入标签记录异常");
}
2025-05-07 08:20:08 +08:00
QcBackEndLogWorkorder qcBackEndLog =
2025-01-21 15:58:27 +08:00
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
};
2025-05-07 08:20:08 +08:00
Context.Insertable(qcBackEndLog).ExecuteCommand();
2025-01-07 17:25:08 +08:00
Context.Ado.CommitTran();
return result;
}
catch (Exception ex)
{
Context.Ado.RollbackTran();
throw new Exception(ex.Message);
}
}
// 创建新工单号
2025-05-07 08:20:08 +08:00
public QcBackEndWorkorderDetailDto GetNewWorkOrderCreate(QcBackEndWorkorderDetailDto data)
2025-01-07 17:25:08 +08:00
{
2025-05-07 08:20:08 +08:00
QcBackEndWorkorderDetailDto result = new();
2025-01-07 17:25:08 +08:00
string newWorkOrder = "";
DateTime today = DateTime.Today;
// 检查是否是已扫过的外箱标签
2025-05-07 08:20:08 +08:00
QcBackEndServiceWorkorder lastWorkOrder = Context
.Queryable<QcBackEndServiceWorkorder>()
2025-01-07 17:25:08 +08:00
.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 QcBackEndServiceWorkorder GetNewWorkOrderInfo(
QcBackEndWorkorderDetailDto data
)
2025-01-07 17:25:08 +08:00
{
// 新工单
2025-05-07 08:20:08 +08:00
QcBackEndServiceWorkorder model =
2025-01-07 17:25:08 +08:00
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;
}
2025-05-07 08:20:08 +08:00
public QcBackEndServiceWorkorder ChangeWorkOrderDefect(QcBackEndWorkorderDefectDto data)
2025-01-07 17:25:08 +08:00
{
try
{
if (string.IsNullOrEmpty(data.DefectCode))
2025-04-15 14:34:04 +08:00
{
throw new Exception("缺陷项传入为空!");
}
2025-01-07 17:25:08 +08:00
Context.Ado.BeginTran();
DateTime nowTime = DateTime.Now;
// 获取缺陷信息
2025-05-07 08:20:08 +08:00
QcBackEndBaseDefect defect = Context
.Queryable<QcBackEndBaseDefect>()
2025-01-07 17:25:08 +08:00
.Where(it => it.Code == data.DefectCode && it.Status == "1")
.First();
if (defect == null)
{
throw new Exception("缺陷项不在缺陷清单中!");
}
// 工单信息修改
2025-05-07 08:20:08 +08:00
QcBackEndServiceWorkorder qcBackEndWorkorder = Context
.Queryable<QcBackEndServiceWorkorder>()
2025-01-07 17:25:08 +08:00
.Where(it => it.WorkOrder == data.WorkOrder)
.First();
2025-05-07 08:20:08 +08:00
if (qcBackEndWorkorder == null)
2025-01-07 17:25:08 +08:00
{
throw new Exception("工单不存在!");
}
// 获取当前工作单缺陷记录
2025-05-07 08:20:08 +08:00
QcBackEndRecordWorkorderDefect workOrderDefect = Context
.Queryable<QcBackEndRecordWorkorderDefect>()
2025-01-07 17:25:08 +08:00
.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
2025-05-07 08:20:08 +08:00
workOrderDefect = new QcBackEndRecordWorkorderDefect
2025-01-07 17:25:08 +08:00
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
WorkOrder = data.WorkOrder,
2025-05-07 08:20:08 +08:00
PartNumber = qcBackEndWorkorder.PartNumber,
Team = qcBackEndWorkorder.Team,
SiteNo = qcBackEndWorkorder.SiteNo,
ComNo = qcBackEndWorkorder.ComNo,
2025-01-07 17:25:08 +08:00
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
{
// 数据库中无记录,新增记录
2025-05-07 08:20:08 +08:00
workOrderDefect = new QcBackEndRecordWorkorderDefect
2025-01-07 17:25:08 +08:00
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
WorkOrder = data.WorkOrder,
2025-05-07 08:20:08 +08:00
PartNumber = qcBackEndWorkorder.PartNumber,
Team = qcBackEndWorkorder.Team,
SiteNo = qcBackEndWorkorder.SiteNo,
ComNo = qcBackEndWorkorder.ComNo,
2025-01-07 17:25:08 +08:00
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();
2025-05-07 08:20:08 +08:00
return qcBackEndWorkorder;
2025-01-07 17:25:08 +08:00
}
catch (Exception ex)
{
// 回滚事务
Context.Ado.RollbackTran();
throw new Exception("操作失败!", ex);
}
}
2025-05-07 08:20:08 +08:00
public List<QcBackEndRecordWorkorderDefect> GetWorkOrderDefectList(string workorder)
2025-01-07 17:25:08 +08:00
{
return Context
2025-05-07 08:20:08 +08:00
.Queryable<QcBackEndRecordWorkorderDefect>()
2025-01-07 17:25:08 +08:00
.Where(it => it.WorkOrder == workorder)
.ToList();
}
2025-05-07 08:20:08 +08:00
public QcBackEndServiceWorkorder UpdateWorkOrderDetail(string workorder)
2025-01-07 17:25:08 +08:00
{
2025-05-07 08:20:08 +08:00
QcBackEndServiceWorkorder qcBackEndWorkorder = Context
.Queryable<QcBackEndServiceWorkorder>()
2025-01-07 17:25:08 +08:00
.Where(it => it.WorkOrder == workorder)
// .Where(it=>it.Status == "1")
.First();
// 更新工单中的统计数据
2025-05-07 08:20:08 +08:00
qcBackEndWorkorder.QualifiedNumber = Context
.Queryable<QcBackEndRecordLabelScan>()
2025-01-07 17:25:08 +08:00
.Where(it => it.WorkOrder == workorder)
.Where(it => it.LabelType == 2)
.Count();
2025-05-07 08:20:08 +08:00
qcBackEndWorkorder.PolishNumber =
2025-01-07 17:25:08 +08:00
Context
2025-05-07 08:20:08 +08:00
.Queryable<QcBackEndRecordWorkorderDefect>()
2025-01-07 17:25:08 +08:00
.Where(it => it.WorkOrder == workorder && it.DefectType == "抛光")
.Sum(it => it.DefectNum) ?? 0;
2025-05-07 08:20:08 +08:00
qcBackEndWorkorder.DamoNumber =
2025-01-07 17:25:08 +08:00
Context
2025-05-07 08:20:08 +08:00
.Queryable<QcBackEndRecordWorkorderDefect>()
2025-01-07 17:25:08 +08:00
.Where(it => it.WorkOrder == workorder && it.DefectType == "打磨")
.Sum(it => it.DefectNum) ?? 0;
2025-05-07 08:20:08 +08:00
qcBackEndWorkorder.BaofeiNumber =
2025-01-07 17:25:08 +08:00
Context
2025-05-07 08:20:08 +08:00
.Queryable<QcBackEndRecordWorkorderDefect>()
2025-01-07 17:25:08 +08:00
.Where(it => it.WorkOrder == workorder && it.DefectType == "报废")
.Sum(it => it.DefectNum) ?? 0;
2025-05-07 08:20:08 +08:00
qcBackEndWorkorder.RequireNumber =
qcBackEndWorkorder.PolishNumber
+ qcBackEndWorkorder.DamoNumber
+ qcBackEndWorkorder.BaofeiNumber
+ (qcBackEndWorkorder.QualifiedNumber ?? 0);
2025-01-07 17:25:08 +08:00
// 更新工单统计信息到数据库
Context
2025-05-07 08:20:08 +08:00
.Updateable(qcBackEndWorkorder)
2025-01-07 17:25:08 +08:00
.UpdateColumns(it => new
{
it.RequireNumber,
it.QualifiedNumber,
it.PolishNumber,
it.DamoNumber,
it.BaofeiNumber
})
.ExecuteCommand();
2025-05-07 08:20:08 +08:00
return qcBackEndWorkorder;
2025-01-07 17:25:08 +08:00
}
2025-05-07 08:20:08 +08:00
public string ScanInnerLabel(QcBackEndLabelScanDto data)
2025-01-07 17:25:08 +08:00
{
DateTime nowTime = DateTime.Now;
// 标签防错 (内标签零件号)
2025-01-07 17:25:08 +08:00
string partNumber = DoAnalyzePartnumber(data.Label);
// 内标签包含外标签
if (!partNumber.Contains(data.PartNumber))
2025-01-07 17:25:08 +08:00
{
2025-05-07 08:20:08 +08:00
return "内标签零件号与工单零件号不一致!";
2025-01-07 17:25:08 +08:00
}
2025-01-09 17:11:32 +08:00
bool hasAny = Context
2025-05-07 08:20:08 +08:00
.Queryable<QcBackEndRecordLabelScan>()
2025-01-09 17:11:32 +08:00
.Where(it => it.Label == data.Label)
.Where(it => it.LabelType == 2)
2025-01-09 17:11:32 +08:00
.Any();
if (hasAny)
{
return "内标签重复扫码!";
2025-01-09 17:11:32 +08:00
}
// 标签录入
2025-01-07 17:25:08 +08:00
int sort = 0;
2025-05-07 08:20:08 +08:00
QcBackEndRecordLabelScan labelScan = Context
.Queryable<QcBackEndRecordLabelScan>()
2025-01-07 17:25:08 +08:00
.Where(it => it.WorkOrder == data.WorkOrder)
.Where(it => it.LabelType == 2)
.OrderByDescending(it => it.LabelSort)
.First();
if (labelScan != null)
{
sort = labelScan.LabelSort ?? 0;
}
2025-05-07 08:20:08 +08:00
QcBackEndRecordLabelScan newLabelScran =
2025-01-07 17:25:08 +08:00
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 "标签录入系统失败!";
}
2025-05-07 08:20:08 +08:00
//TODO 触发箱标签判定
CheckAndPrintPackageLabel(newLabelScran);
return "ok";
}
/// <summary>
/// 判断是否需要自动出满箱标签
/// </summary>
/// <param name="workorder"></param>
public void CheckAndPrintPackageLabel(QcBackEndRecordLabelScan newLabelScran)
{
DateTime nowTime = DateTime.Now;
// 找到最大箱容量与模板
QcBackEndServiceWorkorder workorder = Context
.Queryable<QcBackEndServiceWorkorder>()
.Where(it => it.WorkOrder == newLabelScran.WorkOrder)
.First();
QcBackendBaseOutpackage packageLabelConfig = Context
.Queryable<QcBackendBaseOutpackage>()
.Where(it => workorder.Description.Contains(it.CheckStr))
.First();
if (workorder == null)
{
throw new Exception("工单异常");
}
if (packageLabelConfig == null)
{
throw new Exception("该标签打印参数未配置");
}
int checkSort = newLabelScran.LabelSort ?? 0;
int maxPackage = packageLabelConfig.PackageNum ?? 0;
if (checkSort >= maxPackage && checkSort % maxPackage == 0)
2025-05-07 08:20:08 +08:00
{
int packageSort = 0;
2025-05-07 08:20:08 +08:00
QcBackEndRecordLabelScan packagelabelScan = Context
.Queryable<QcBackEndRecordLabelScan>()
.Where(it => it.WorkOrder == newLabelScran.WorkOrder)
2025-05-07 08:20:08 +08:00
.Where(it => it.LabelType == 1)
.OrderByDescending(it => it.LabelSort)
.First();
if (packagelabelScan != null)
2025-05-07 08:20:08 +08:00
{
packageSort = packagelabelScan.LabelSort ?? 0;
}
QcBackEndRecordLabelScan newPackagePrintLabel =
new()
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
WorkOrder = newLabelScran.WorkOrder,
PartNumber = newLabelScran.PartNumber,
Team = newLabelScran.Team,
SiteNo = newLabelScran.SiteNo,
ComNo = newLabelScran.ComNo,
Label =
$"Code=BN{newLabelScran.WorkOrder}_{newLabelScran.Team}{packageSort + 1}^ItemNumber={newLabelScran.PartNumber}^Order={newLabelScran.WorkOrder}^Qty={maxPackage}^Type=packageLabel",
LabelType = 1,
LabelSort = packageSort + 1,
ScanTime = $"{nowTime:yyyy-MM-dd HH:mm:ss}",
Type = "1",
Status = "1",
Remark = "自动出满箱标签",
CreatedBy = newLabelScran.CreatedBy,
CreatedTime = newLabelScran.CreatedTime,
};
int res = Context.Insertable(newPackagePrintLabel).ExecuteCommand();
if (res > 0)
2025-05-07 08:20:08 +08:00
{
SendPrintPackageLabelAsync(newLabelScran, packageLabelConfig.FileUrl).Wait();
}
}
}
/// <summary>
/// 发送打印后道外箱标签的mqtt信息
/// </summary>
public async Task SendPrintPackageLabelAsync(
QcBackEndRecordLabelScan newLabelScran,
string path
)
{
try
{
// 构造主题和消息内容
string topic = $"shgg_mes/backEnd/print/{newLabelScran.SiteNo}";
QcBackEndPrintMqttEventDto mqttEventDto =
new()
{
Path = path,
SiteNo = newLabelScran.SiteNo,
Name = newLabelScran.PartNumber,
WorkOrder = newLabelScran.WorkOrder,
Team = newLabelScran.Team,
Sort = (newLabelScran.LabelSort + 1) ?? 1,
BatchCode = DateTime.Now.ToString("yyyyMMdd"),
PackageNum = 24,
LabelType = newLabelScran.LabelType ?? 1,
CreatedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
};
var payload = JsonSerializer.Serialize(mqttEventDto);
// 调用MqttService的发布方法支持异步调用
await _mqttService.PublishAsync(
topic,
payload,
MqttQualityOfServiceLevel.ExactlyOnce,
// 可选:设置消息保留
retain: false
);
_logger.LogInformation($"发送后道外箱标签打印成功:{topic}");
}
catch (Exception ex)
{
_logger.LogError(ex, $"发送后道外箱标签打印失败:{ex.Message}");
throw; // 或根据业务需求处理异常
2025-05-07 08:20:08 +08:00
}
2025-01-07 17:25:08 +08:00
}
2025-05-07 08:20:08 +08:00
public string EndBackEndWorkOrderAndCreateStatistics(string workorder)
2025-01-07 17:25:08 +08:00
{
try
{
Context.Ado.BeginTran();
DateTime nowTime = DateTime.Now;
// 工单信息修改
2025-05-07 08:20:08 +08:00
QcBackEndServiceWorkorder qcBackEndWorkorder = Context
.Queryable<QcBackEndServiceWorkorder>()
2025-01-07 17:25:08 +08:00
.Where(it => it.WorkOrder == workorder)
.First();
2025-05-07 08:20:08 +08:00
if (qcBackEndWorkorder == null)
2025-01-07 17:25:08 +08:00
{
throw new Exception("工单不存在!");
}
2025-05-07 08:20:08 +08:00
qcBackEndWorkorder.EndTime = nowTime;
qcBackEndWorkorder.Type = "2";
if (!qcBackEndWorkorder.Remark.Contains("已生成过报表"))
2025-04-23 16:33:36 +08:00
{
2025-05-07 08:20:08 +08:00
qcBackEndWorkorder.Remark += "已生成过报表";
2025-04-23 16:33:36 +08:00
}
2025-05-07 08:20:08 +08:00
Context.Updateable(qcBackEndWorkorder).ExecuteCommand();
2025-01-07 17:25:08 +08:00
// 生成报表记录
2025-05-07 08:20:08 +08:00
List<QcBackEndServiceStatistics> addList = new();
2025-01-07 17:25:08 +08:00
string groupCode = SnowFlakeSingle.Instance.NextId().ToString();
2025-05-07 08:20:08 +08:00
addList.Add(CreateNewStatistics(qcBackEndWorkorder, groupCode, 1));
addList.Add(CreateNewStatistics(qcBackEndWorkorder, groupCode, 2));
addList.Add(CreateNewStatistics(qcBackEndWorkorder, groupCode, 3));
2025-01-07 17:25:08 +08:00
Context
2025-05-07 08:20:08 +08:00
.Deleteable<QcBackEndServiceStatistics>()
2025-01-07 17:25:08 +08:00
.Where(it => it.WorkOrder == workorder)
.ExecuteCommand();
Context.Insertable(addList).ExecuteCommand();
2025-05-07 08:20:08 +08:00
QcBackEndLogWorkorder qcBackEndLog =
2025-01-21 15:58:27 +08:00
new()
{
Id = SnowFlakeSingle.Instance.NextId().ToString(),
Name = "工单结束",
Content = $"工单:{workorder}结束,结束时间{nowTime:yyyy-MM-dd HH:mm:ss}",
Type = "200",
Status = "1",
Remark = "触摸屏操作记录",
CreatedBy = "系统",
CreatedTime = nowTime
};
2025-05-07 08:20:08 +08:00
Context.Insertable(qcBackEndLog).ExecuteCommand();
2025-01-07 17:25:08 +08:00
// 提交事务
Context.Ado.CommitTran();
return "ok";
}
catch (Exception ex)
{
// 回滚事务
Context.Ado.RollbackTran();
return ex.Message;
}
}
2025-05-07 08:20:08 +08:00
public QcBackEndServiceStatistics CreateNewStatistics(
QcBackEndServiceWorkorder data,
2025-01-07 17:25:08 +08:00
string groupCode,
int groupSort
)
{
2025-05-07 08:20:08 +08:00
List<QcBackEndRecordWorkorderDefect> defectList = Context
.Queryable<QcBackEndRecordWorkorderDefect>()
2025-01-07 17:25:08 +08:00
.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;
2025-05-07 08:20:08 +08:00
QcBackEndServiceStatistics workorderStatistics =
2025-01-07 17:25:08 +08:00
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;
}
2025-05-07 08:20:08 +08:00
public static string CalculateQualifiedRate(QcBackEndServiceWorkorder data)
2025-01-07 17:25:08 +08:00
{
if (data == null || data.RequireNumber <= 0)
{
return "0%";
}
double qualifiedRate =
(double)data.QualifiedNumber.Value / data.RequireNumber.Value * 100;
return $"{qualifiedRate:F1}%";
}
2025-02-14 17:26:56 +08:00
public QcBackEndServiceWorkorder GenerateVirtualLabel(
QcBackEndWorkorderDetailDto workorderDetail
)
2025-02-14 17:26:56 +08:00
{
try
{
Context.Ado.BeginTran();
// 检查当前工单已扫码合格数
int qualifiedNumber = workorderDetail.QualifiedNumber ?? -1;
if (qualifiedNumber < 0)
{
throw new ArgumentException(
"传入合格数异常!",
nameof(workorderDetail.QualifiedNumber)
);
2025-02-14 17:26:56 +08:00
}
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<QcBackEndRecordLabelScan>()
.Where(it => it.WorkOrder == workOrder && it.LabelType == 2)
.Count();
2025-02-14 17:26:56 +08:00
}
private void GenerateVirtualLabels(
QcBackEndWorkorderDetailDto workOrderDetail,
int countToGenerate
)
2025-02-14 17:26:56 +08:00
{
2025-05-07 08:20:08 +08:00
List<QcBackEndRecordLabelScan> virtualLabels = new List<QcBackEndRecordLabelScan>();
2025-02-14 17:26:56 +08:00
int nextLabelNumber = GetNextLabelNumber(workOrderDetail.WorkOrder);
for (int i = 0; i < countToGenerate; i++)
{
string uniqueLabel = GenerateUniqueSequentialLabel(
workOrderDetail.WorkOrder,
nextLabelNumber++
);
virtualLabels.Add(
new QcBackEndRecordLabelScan
{
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
}
);
2025-02-14 17:26:56 +08:00
}
Context.Insertable(virtualLabels).ExecuteCommand();
}
private void DeleteExcessLabels(string workOrder, int countToDelete)
{
var labelsToDelete = Context
.Queryable<QcBackEndRecordLabelScan>()
.Where(it => it.WorkOrder == workOrder && it.LabelType == 2)
.OrderByDescending(it => it.LabelSort)
.Take(countToDelete)
.ToList();
2025-02-14 17:26:56 +08:00
Context.Deleteable(labelsToDelete).ExecuteCommand();
}
private int GetNextLabelNumber(string workOrder)
{
return Context
.Queryable<QcBackEndRecordLabelScan>()
.Where(it => it.WorkOrder == workOrder && it.LabelType == 2)
.Max(it => it.LabelSort ?? 0);
2025-02-14 17:26:56 +08:00
}
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<QcBackEndRecordLabelScan>()
.Any(it => it.WorkOrder == workOrder && it.LabelType == 2 && it.Label == label);
2025-02-14 17:26:56 +08:00
}
private string GenerateUniqueId()
{
return Guid.NewGuid().ToString("N").Substring(0, 10); // Generate a 10-character unique ID
}
2025-01-03 16:43:02 +08:00
}
2025-01-07 17:25:08 +08:00
}