feat: 完善焊接质量检查和材料管理

补齐焊前专项审核和焊缝外观检测流程,统一质检查询、附件处理与材料明细导出,提升业务数据追溯和组件匹配使用效率。
This commit is contained in:
2026-08-10 17:58:55 +08:00
parent bd73295ff8
commit 2de696fad2
48 changed files with 2252 additions and 131 deletions
@@ -9,6 +9,9 @@ namespace BLL
/// </summary>
public static class PreWeldInspectionService
{
public const int CuttingReviewCompleted = 0;
public const int CuttingReviewPending = 1;
public const int CuttingReviewApproved = 2;
/// <summary>
/// 获取下料检查台账
/// </summary>
@@ -62,13 +65,14 @@ namespace BLL
CheckResult = x.c.CheckResult,
UnqualifiedReason = x.c.UnqualifiedReason,
RectifyRequirement = x.c.RectifyRequirement,
Remark = x.c.Remark
Remark = x.c.Remark,
ReviewState = x.c.ReviewState,
SpecialReviewerId = x.c.SpecialReviewerId,
ReviewerId = x.c.ReviewerId,
ReviewTime = x.c.ReviewTime
})
.ToList();
foreach (var item in data)
{
item.AttachUrl1 = GetInspectionAttachUrl(db, Const.HJGL_PreWeldCuttingCheckMenuId, item.CuttingCheckId);
}
PopulateCuttingCheckDetails(db, data);
return Tuple.Create(data, total);
}
@@ -195,6 +199,48 @@ namespace BLL
}
}
public static List<Model.PreWeldCuttingCheckItem> GetCuttingCheckItemsByWeldJointId(string weldJointId)
{
using (Model.SGGLDB db = new Model.SGGLDB(Funs.ConnString))
{
var data = (from c in db.HJGL_PreWeldCuttingCheck
join w in db.HJGL_WeldJoint on c.WeldJointId equals w.WeldJointId
join p in db.Person_Persons on c.CheckPerson equals p.PersonId into persons
from p in persons.DefaultIfEmpty()
where c.WeldJointId == weldJointId
orderby c.CheckTime descending, c.CreateTime descending
select new Model.PreWeldCuttingCheckItem
{
CuttingCheckId = c.CuttingCheckId,
ProjectId = c.ProjectId,
WeldJointId = c.WeldJointId,
PipelineCode = w.PipelineCode,
WeldJointCode = w.WeldJointCode,
CuttingLength = c.CuttingLength,
GrooveForm = c.GrooveForm,
GrooveAngle = c.GrooveAngle,
IsMaterialCodeBatchNoAccurate = c.IsMaterialCodeBatchNoAccurate,
IsMaterialQuantityAccurate = c.IsMaterialQuantityAccurate,
IsQualified = c.IsQualified,
CheckPerson = c.CheckPerson,
CheckPersonName = p == null ? string.Empty : p.PersonName,
CheckTime = c.CheckTime,
CreateUser = c.CreateUser,
CreateTime = c.CreateTime,
CheckResult = c.CheckResult,
UnqualifiedReason = c.UnqualifiedReason,
RectifyRequirement = c.RectifyRequirement,
Remark = c.Remark,
ReviewState = c.ReviewState,
SpecialReviewerId = c.SpecialReviewerId,
ReviewerId = c.ReviewerId,
ReviewTime = c.ReviewTime
}).ToList();
PopulateCuttingCheckDetails(db, data);
return data;
}
}
/// <summary>
/// 按焊口获取组对记录
/// </summary>
@@ -259,12 +305,69 @@ namespace BLL
check.UnqualifiedReason = item.UnqualifiedReason;
check.RectifyRequirement = item.RectifyRequirement;
check.Remark = item.Remark;
bool requiresSpecialReview = !item.IsMaterialCodeBatchNoAccurate;
if (requiresSpecialReview && string.IsNullOrWhiteSpace(item.SpecialReviewerId))
{
throw new ArgumentException("材料编码或批次不准确时必须选择专项审核办理人。");
}
if (requiresSpecialReview && !db.SitePerson_Person.Any(x => x.ProjectId == check.ProjectId
&& x.PersonId == item.SpecialReviewerId && x.States == Const.ProjectPersonStates_1))
{
throw new ArgumentException("专项审核办理人不属于当前项目或已停用。");
}
check.ReviewState = requiresSpecialReview ? CuttingReviewPending : CuttingReviewCompleted;
check.SpecialReviewerId = requiresSpecialReview ? item.SpecialReviewerId : null;
check.ReviewerId = null;
check.ReviewTime = null;
SaveCuttingMaterialSnapshots(db, check, item.Materials);
SyncCuttingReviewTodo(db, check, item.CreateUser ?? item.CheckPerson);
db.SubmitChanges();
SaveInspectionAttachUrl(item.AttachUrl1, Const.HJGL_PreWeldCuttingCheckMenuId, check.CuttingCheckId);
return check.CuttingCheckId;
}
}
public static string ReviewCuttingCheck(Model.PreWeldCuttingCheckReviewInput item)
{
if (item == null || string.IsNullOrWhiteSpace(item.CuttingCheckId))
{
throw new ArgumentException("下料检查记录ID不能为空。");
}
using (Model.SGGLDB db = new Model.SGGLDB(Funs.ConnString))
{
var check = db.HJGL_PreWeldCuttingCheck.FirstOrDefault(x => x.CuttingCheckId == item.CuttingCheckId);
if (check == null)
{
throw new ArgumentException("未找到下料检查记录。");
}
if (check.ReviewState != CuttingReviewPending)
{
throw new InvalidOperationException("该专项审核已办理或无需办理。");
}
if (string.IsNullOrWhiteSpace(item.ReviewerId) || check.SpecialReviewerId != item.ReviewerId)
{
throw new InvalidOperationException("当前人员不是该专项审核的办理人。");
}
if (item.Materials != null)
{
SaveCuttingMaterialSnapshots(db, check, item.Materials);
}
if (!string.IsNullOrWhiteSpace(item.Remark))
{
check.Remark = item.Remark;
}
check.ReviewState = CuttingReviewApproved;
check.ReviewerId = item.ReviewerId;
check.ReviewTime = item.ReviewTime ?? DateTime.Now;
CompleteCuttingReviewTodo(db, check.CuttingCheckId, item.ReviewerId);
db.SubmitChanges();
return check.CuttingCheckId;
}
}
/// <summary>
/// 保存组对检查;传入主键时修改对应记录,否则新增一条记录
/// </summary>
@@ -711,6 +814,133 @@ namespace BLL
}
}
private static void SaveCuttingMaterialSnapshots(Model.SGGLDB db, Model.HJGL_PreWeldCuttingCheck check,
IList<Model.PreWeldCuttingMaterialInput> materials)
{
var currentMaterials = db.HJGL_PipeLineMat
.Where(x => x.WeldJointId == check.WeldJointId)
.OrderBy(x => x.PipeLineMatId)
.ToList();
var inputs = materials ?? currentMaterials.Select((x, index) => new Model.PreWeldCuttingMaterialInput
{
PipeLineMatId = x.PipeLineMatId,
MaterialSide = index + 1,
ReportedMainCode = x.MaterialCode
}).ToList();
var existing = db.HJGL_PreWeldCuttingCheckMaterial
.Where(x => x.CuttingCheckId == check.CuttingCheckId)
.ToList();
var originalCodeMap = existing.GroupBy(x => x.PipeLineMatId)
.ToDictionary(x => x.Key, x => x.First().OriginalMainCode);
db.HJGL_PreWeldCuttingCheckMaterial.DeleteAllOnSubmit(existing);
int side = 0;
foreach (var input in inputs)
{
side++;
var material = currentMaterials.FirstOrDefault(x => x.PipeLineMatId == input.PipeLineMatId);
if (material == null)
{
throw new ArgumentException("反馈材料不属于当前焊口。");
}
string reportedMainCode = string.IsNullOrWhiteSpace(input.ReportedMainCode)
? material.MaterialCode
: input.ReportedMainCode.Trim();
db.HJGL_PreWeldCuttingCheckMaterial.InsertOnSubmit(new Model.HJGL_PreWeldCuttingCheckMaterial
{
CuttingCheckMaterialId = Guid.NewGuid().ToString(),
CuttingCheckId = check.CuttingCheckId,
PipeLineMatId = material.PipeLineMatId,
MaterialSide = input.MaterialSide > 0 ? input.MaterialSide : side,
// 专项审核再次保存时保留首次提交快照,避免原始主编码被当前正式数据覆盖。
OriginalMainCode = originalCodeMap.ContainsKey(material.PipeLineMatId)
? originalCodeMap[material.PipeLineMatId]
: material.MaterialCode,
ReportedMainCode = reportedMainCode,
IsBatchChanged = !string.Equals(material.MaterialCode, reportedMainCode, StringComparison.OrdinalIgnoreCase)
});
}
}
private static void SyncCuttingReviewTodo(Model.SGGLDB db, Model.HJGL_PreWeldCuttingCheck check, string creator)
{
var todos = db.Workflow_TodoItems.Where(x => x.FlowId == check.CuttingCheckId
&& x.WorkflowName == "下料抽检专项审核").ToList();
db.Workflow_TodoItems.DeleteAllOnSubmit(todos);
if (check.ReviewState != CuttingReviewPending)
{
return;
}
db.Workflow_TodoItems.InsertOnSubmit(new Model.Workflow_TodoItems
{
Id = SQLHelper.GetNewID(),
SysCode = WorkflowTodoitemsService.SysCode,
FlowId = check.CuttingCheckId,
RequestName = "下料抽检结果不准确,请专项审核",
WorkflowName = "下料抽检专项审核",
NodeName = "专项审核",
PCUrl = "HJGL/PreWeld/CuttingCheckEdit.aspx?CuttingCheckId=" + check.CuttingCheckId + "&review=1",
AppUrl = "/pages/hjgl/preWeld/cuttingCheckReview?cuttingCheckId=" + check.CuttingCheckId,
Creator = creator,
CreateDateTime = DateTime.Now,
Receiver = check.SpecialReviewerId,
ReceiveDateTime = DateTime.Now,
Status = (int)WorkflowTodoitemsService.Status.
});
}
private static void CompleteCuttingReviewTodo(Model.SGGLDB db, string cuttingCheckId, string reviewerId)
{
var todo = db.Workflow_TodoItems.FirstOrDefault(x => x.FlowId == cuttingCheckId
&& x.Receiver == reviewerId
&& x.WorkflowName == "下料抽检专项审核"
&& x.Status == (int)WorkflowTodoitemsService.Status.);
if (todo != null)
{
todo.Status = (int)WorkflowTodoitemsService.Status.;
}
}
private static void PopulateCuttingCheckDetails(Model.SGGLDB db, IList<Model.PreWeldCuttingCheckItem> data)
{
if (data == null || data.Count == 0)
{
return;
}
var ids = data.Select(x => x.CuttingCheckId).ToList();
var snapshots = db.HJGL_PreWeldCuttingCheckMaterial
.Where(x => ids.Contains(x.CuttingCheckId))
.ToList();
var personIds = data.SelectMany(x => new[] { x.SpecialReviewerId, x.ReviewerId })
.Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList();
var personNames = db.Person_Persons.Where(x => personIds.Contains(x.PersonId))
.ToDictionary(x => x.PersonId, x => x.PersonName);
foreach (var item in data)
{
item.AttachUrl1 = GetInspectionAttachUrl(db, Const.HJGL_PreWeldCuttingCheckMenuId, item.CuttingCheckId);
item.ReviewStateText = item.ReviewState == CuttingReviewPending
? "待专项审核"
: item.ReviewState == CuttingReviewApproved ? "专项审核完成" : "普通完成";
string name;
item.SpecialReviewerName = personNames.TryGetValue(item.SpecialReviewerId ?? string.Empty, out name) ? name : string.Empty;
item.ReviewerName = personNames.TryGetValue(item.ReviewerId ?? string.Empty, out name) ? name : string.Empty;
item.Materials = snapshots.Where(x => x.CuttingCheckId == item.CuttingCheckId)
.OrderBy(x => x.MaterialSide)
.Select(x => new Model.PreWeldCuttingMaterialItem
{
PipeLineMatId = x.PipeLineMatId,
MaterialSide = x.MaterialSide,
OriginalMainCode = x.OriginalMainCode,
ReportedMainCode = x.ReportedMainCode,
IsBatchChanged = x.IsBatchChanged
}).ToList();
}
}
/// <summary>
/// 根据菜单和记录ID获取检查附件地址
/// </summary>