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
@@ -47,7 +47,9 @@ namespace BLL
where m.WeldJointId == weldJointId
select new Model.PreWeldMaterialItem
{
MaterialCode = lib.MaterialCode,
PipeLineMatId = m.PipeLineMatId,
MainCode = m.MaterialCode,
MaterialCode = m.MaterialCode,
MaterialName = lib.MaterialName,
MaterialSpec = lib.MaterialSpec,
MaterialMade = lib.MaterialMade,
@@ -55,12 +57,16 @@ namespace BLL
MaterialUnit = lib.MaterialUnit,
HeatNo = lib.HeatNo,
BatchNo = lib.BatchNo,
}).ToList()
}).ToList()
};
var item = query.FirstOrDefault();
if (item != null)
{
for (int index = 0; index < item.preWeldMaterialItems.Count; index++)
{
item.preWeldMaterialItems[index].MaterialSide = index + 1;
}
SetInspectionAttachUrl(db, item);
}
@@ -73,44 +79,7 @@ namespace BLL
/// </summary>
public static List<Model.PreWeldCuttingCheckItem> GetCuttingChecksByWeldJointId(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
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,
AttachUrl1 = null,
CheckResult = c.CheckResult,
UnqualifiedReason = c.UnqualifiedReason,
RectifyRequirement = c.RectifyRequirement,
Remark = c.Remark
}).ToList();
foreach (var item in data)
{
item.AttachUrl1 = GetAttachUrl(db, Const.HJGL_PreWeldCuttingCheckMenuId, item.CuttingCheckId);
}
return data;
}
return PreWeldInspectionService.GetCuttingCheckItemsByWeldJointId(weldJointId);
}
/// <summary>
@@ -189,6 +158,26 @@ namespace BLL
return PreWeldInspectionService.SaveCuttingCheck(item);
}
public static string ReviewCuttingCheck(Model.PreWeldCuttingCheckReviewInput item)
{
return PreWeldInspectionService.ReviewCuttingCheck(item);
}
public static List<Model.BaseInfoItem> GetSpecialReviewers(string projectId)
{
using (Model.SGGLDB db = new Model.SGGLDB(Funs.ConnString))
{
return (from x in db.SitePerson_Person
where x.ProjectId == projectId && x.States == Const.ProjectPersonStates_1
orderby x.PersonName
select new Model.BaseInfoItem
{
BaseInfoId = x.PersonId,
BaseInfoName = x.PersonName
}).Distinct().ToList();
}
}
/// <summary>
/// 保存组对检查
/// </summary>
@@ -289,7 +289,14 @@ namespace BLL
return "参数不能为空";
}
string res = BLL.WeldingDailyService.SaveWeldingDailyTempDetailByMobile(newItem.WeldJointId, newItem.Personid, newItem.time, newItem.weldingLocation, newItem.welderType);
string res = BLL.WeldingDailyService.SaveWeldingDailyTempDetailByMobile(
newItem.WeldJointId,
newItem.Personid,
newItem.time,
newItem.weldingLocation,
newItem.welderType,
newItem.WeldingMethodId,
newItem.WeldTypeId);
if (!string.IsNullOrEmpty(res))
{
return res;
+1
View File
@@ -464,6 +464,7 @@
<Compile Include="HJGL\WeldingManage\PipelineMatService.cs" />
<Compile Include="HJGL\WeldingManage\PipelineService.cs" />
<Compile Include="HJGL\WeldingManage\PreWeldInspectionService.cs" />
<Compile Include="HJGL\WeldingManage\WeldAppearanceCheckService.cs" />
<Compile Include="HJGL\WeldingManage\WeldingDailyService.cs" />
<Compile Include="HJGL\WeldingManage\WeldJointService.cs" />
<Compile Include="HJGL\WeldingManage\WeldTaskService.cs" />
+80 -9
View File
@@ -42,6 +42,18 @@ namespace BLL
g.Key,
RealNum = g.Sum(x => x.ActNum) ?? 0,
}).ToList();
///实际材料出库数量列表
var RealOutMateriaList = (from x in db.Tw_OutputDetail
join master in db.Tw_OutputMaster on x.OutputMasterId equals master.Id
where master.ProjectId == projectid && master.WarehouseId == WarehouseId
group x by x.MaterialCode
into g
where (string.IsNullOrEmpty(materialCode) || g.Key.Contains(materialCode))
select new
{
g.Key,
OutputNum = g.Sum(x => x.ActNum) ?? 0,
}).ToList();
//库存数量
var tw_MaterialStock = (from x in db.Tw_MaterialStock
where x.WarehouseId == WarehouseId && x.ProjectId == projectid
@@ -50,6 +62,7 @@ namespace BLL
var needMateriaList = NeedOutMateriaList.ToList();
var materialCodeList = needMateriaList.Select(x => x.Key)
.Union(RealInMateriaList.Select(x => x.Key))
.Union(RealOutMateriaList.Select(x => x.Key))
.Distinct()
.ToList();
@@ -62,6 +75,8 @@ namespace BLL
from x in needGroup.DefaultIfEmpty()
join y in RealInMateriaList on code equals y.Key into realGroup
from y in realGroup.DefaultIfEmpty()
join o in RealOutMateriaList on code equals o.Key into outputGroup
from o in outputGroup.DefaultIfEmpty()
join z in materialInfoList on code equals z.MaterialCode into infoGroup
from z in infoGroup.DefaultIfEmpty()
join m in tw_MaterialStock on code equals m.PipeLineMatCode into stockGroup
@@ -73,6 +88,7 @@ namespace BLL
StockNum = m == null ? 0 : (decimal)m.StockNum,
NeedNum = x == null ? 0 : x.NeedNum,
RealNum = y == null ? 0 : y.RealNum,
OutputNum = o == null ? 0 : o.OutputNum,
Code = z == null ? null : z.Code,
HeatNo = z == null ? null : z.HeatNo,
BatchNo = z == null ? null : z.BatchNo,
@@ -449,7 +465,8 @@ namespace BLL
}
/// <summary>
/// 获取单位工程下当前区域内同时存在已焊口和未焊口的组件汇总。
/// 获取单位工程下当前区域的组件导出汇总。
/// 每个组件返回一行;未焊达因量按未焊口统计,材料信息按当前区域组件材料明细统计。
/// </summary>
public static List<Tw_PartialWeldedComponentOutput> GetPartialWeldedComponents(string projectId, string unitWorkId, string pipeArea, string warehouseCode)
{
@@ -476,17 +493,53 @@ namespace BLL
z.UnitWorkId,
m.UnitWorkName,
x.PrefabricatedComponents,
x.MaterialCode,
x.MaterialCode2,
x.Number,
w.WeldJointId,
w.Size,
w.WeldingDailyId
}).ToList();
var partialComponents = componentWeldRows
var materialCodes = componentWeldRows
.Where(x => !string.IsNullOrEmpty(x.MaterialCode))
.Select(x => x.MaterialCode)
.Distinct()
.ToList();
var materialCodeLibByMaterialCode = materialCodes.Any()
? db.HJGL_MaterialCodeLib
.Where(x => materialCodes.Contains(x.MaterialCode))
.ToList()
.GroupBy(x => x.MaterialCode)
.ToDictionary(x => x.Key, x => x.First())
: new Dictionary<string, HJGL_MaterialCodeLib>();
var componentExports = componentWeldRows
.GroupBy(x => new { x.PipelineId, x.PipelineCode, x.UnitWorkId, x.UnitWorkName, x.PrefabricatedComponents })
.Select(group =>
{
var weldJoints = group.GroupBy(x => x.WeldJointId).Select(x => x.First()).ToList();
int weldedCount = weldJoints.Count(x => !string.IsNullOrEmpty(x.WeldingDailyId));
int totalCount = weldJoints.Count;
// 材料编码优先采用匹配页面使用的 MaterialCode2,数量按当前区域组件材料明细汇总。
var componentMaterialRows = group
.Where(x => (x.Number ?? 0) > 0)
.ToList();
var materialGroups = componentMaterialRows
.Select(x => new
{
MaterialCode = GetExportMaterialCode(x.MaterialCode, x.MaterialCode2, materialCodeLibByMaterialCode),
Quantity = x.Number ?? 0
})
.Where(x => !string.IsNullOrEmpty(x.MaterialCode))
.GroupBy(x => x.MaterialCode)
.OrderBy(x => x.Key)
.Select(x => new
{
MaterialCode = x.Key,
Quantity = x.Sum(y => y.Quantity)
})
.ToList();
return new Tw_PartialWeldedComponentOutput
{
UnitWorkId = group.Key.UnitWorkId,
@@ -498,26 +551,30 @@ namespace BLL
PipeAreaText = pipeArea == PipelineService.PipeArea_SHOP ? "工厂预制" : "现场安装",
TotalWeldJointCount = totalCount,
WeldedWeldJointCount = weldedCount,
UnweldedWeldJointCount = totalCount - weldedCount
UnweldedWeldJointCount = totalCount - weldedCount,
UnweldedDin = weldJoints
.Where(x => string.IsNullOrEmpty(x.WeldingDailyId))
.Sum(x => x.Size ?? 0),
MaterialCode = string.Join("\n", materialGroups.Select(x => x.MaterialCode)),
MaterialQuantity = string.Join("\n", materialGroups.Select(x => x.Quantity.ToString()))
};
})
.Where(x => x.WeldedWeldJointCount > 0 && x.UnweldedWeldJointCount > 0)
.OrderBy(x => x.PipelineCode)
.ThenBy(x => x.PrefabricatedComponents)
.ToList();
if (!partialComponents.Any())
if (!componentExports.Any())
{
return partialComponents;
return componentExports;
}
// 导出匹配率复用页面匹配规则,保证区域、未焊口及续作组件优先级完全一致。
var pipelineIds = partialComponents.Select(x => x.PipelineId).Distinct().ToList();
var pipelineIds = componentExports.Select(x => x.PipelineId).Distinct().ToList();
var matchOutputs = GetPipeMatMatch(projectId, pipelineIds, warehouseCode, null, pipeArea);
var componentRates = matchOutputs
.GroupBy(x => GetComponentKey(x.PipelineId, x.PrefabricatedComponents))
.ToDictionary(x => x.Key, x => x.First().ComponentMatchRate ?? 0);
foreach (var component in partialComponents)
foreach (var component in componentExports)
{
decimal componentRate;
componentRates.TryGetValue(GetComponentKey(component.PipelineId, component.PrefabricatedComponents), out componentRate);
@@ -525,10 +582,24 @@ namespace BLL
component.ComponentMatchRateString = Math.Round(componentRate * 100, 2).ToString() + "%";
}
return partialComponents;
return componentExports;
}
}
private static string GetExportMaterialCode(string materialCode, string materialCode2, Dictionary<string, HJGL_MaterialCodeLib> materialCodeLibByMaterialCode)
{
if (!string.IsNullOrEmpty(materialCode2))
{
return materialCode2;
}
HJGL_MaterialCodeLib materialLib;
return !string.IsNullOrEmpty(materialCode)
&& materialCodeLibByMaterialCode.TryGetValue(materialCode, out materialLib)
? materialLib.Code
: materialCode;
}
private static string GetJointAttributeByPipeArea(string pipeArea)
{
if (pipeArea == PipelineService.PipeArea_SHOP)
+28 -2
View File
@@ -133,11 +133,19 @@ namespace BLL
join mat in Funs.DB.HJGL_MaterialCodeLib on x.MaterialCode equals mat.MaterialCode into mm
from mat in mm.DefaultIfEmpty()
join y in Funs.DB.Tw_InputMaster on x.InputMasterId equals y.Id
join warehouse in Funs.DB.Base_Warehouse on y.WarehouseId equals warehouse.WarehouseId into warehouses
from warehouse in warehouses.DefaultIfEmpty()
join person in Funs.DB.Person_Persons on y.CreateMan equals person.PersonId into persons
from person in persons.DefaultIfEmpty()
where inputMasterIds.Contains(x.InputMasterId)
orderby y.CusBillCode, x.SortIndex
select new
{
= y.CusBillCode,
y.CusBillCode,
WarehouseName = warehouse == null ? y.WarehouseCode : warehouse.WarehouseName,
y.TypeInt,
CreateManName = person == null ? y.CreateMan : person.PersonName,
y.CreateDate,
= x.MaterialCode,
= mat.Code,
= mat.HeatNo,
@@ -146,8 +154,26 @@ namespace BLL
= mat.MaterialDef,
= x.PlanNum,
= x.ActNum,
y.Remark
};
return q;
// 类型字典无法转换为 SQL,先完成数据库查询,再生成固定顺序的 Excel 列。
return q.ToList().Select(x => new
{
= x.CusBillCode,
= x.WarehouseName,
= TwConst.TypeIntMap.FirstOrDefault(y => y.Value == x.TypeInt).Key,
= x.CreateManName,
= x.CreateDate,
x.,
x.,
x.,
x.,
x.,
x.,
x.,
x.,
= x.Remark
}).ToList();
}
}
}
+38 -3
View File
@@ -151,13 +151,26 @@ namespace BLL
public static IEnumerable GetPrintListByOutputMasterIds(List<string> outputMasterIds)
{
var q = from x in Funs.DB.Tw_OutputDetail
join y in Funs.DB.HJGL_MaterialCodeLib on x.MaterialCode equals y.MaterialCode
join y in Funs.DB.HJGL_MaterialCodeLib on x.MaterialCode equals y.MaterialCode into materials
from y in materials.DefaultIfEmpty()
join master in Funs.DB.Tw_OutputMaster on x.OutputMasterId equals master.Id
join plan in Funs.DB.Tw_InOutPlanMaster on master.InOutPlanMasterId equals plan.Id into plans
from plan in plans.DefaultIfEmpty()
join warehouse in Funs.DB.Base_Warehouse on master.WarehouseId equals warehouse.WarehouseId into warehouses
from warehouse in warehouses.DefaultIfEmpty()
join person in Funs.DB.Person_Persons on master.CreateMan equals person.PersonId into persons
from person in persons.DefaultIfEmpty()
join unit in Funs.DB.Base_Unit on master.ReqUnitId equals unit.UnitId into units
from unit in units.DefaultIfEmpty()
where outputMasterIds.Contains(x.OutputMasterId)
orderby master.CusBillCode
select new
{
= master.CusBillCode,
master.CusBillCode,
WarehouseName = warehouse == null ? master.WarehouseCode : warehouse.WarehouseName,
master.TypeInt,
CreateManName = person == null ? master.CreateMan : person.PersonName,
master.CreateDate,
= x.MaterialCode,
= y.Code,
= y.HeatNo,
@@ -166,8 +179,30 @@ namespace BLL
= y.MaterialDef,
= x.PlanNum,
= x.ActNum,
master.WarehouseDate,
ReqUnitName = unit == null ? master.ReqUnitId : unit.UnitName,
Remark = plan == null ? null : plan.Remark
};
return q;
// 类型字典无法转换为 SQL,先完成数据库查询,再生成固定顺序的 Excel 列。
return q.ToList().Select(x => new
{
= x.CusBillCode,
= x.WarehouseName,
= TwConst.TypeIntMap.FirstOrDefault(y => y.Value == x.TypeInt).Key,
= x.CreateManName,
= x.CreateDate,
x.,
x.,
x.,
x.,
x.,
x.,
x.,
x.,
= x.WarehouseDate,
= x.ReqUnitName,
= x.Remark
}).ToList();
}
}
+2
View File
@@ -2944,6 +2944,8 @@ namespace BLL
/// 下料抽检记录台账
/// </summary>
public const string HJGL_PreWeldCuttingCheckMenuId = "D1B5A8B7-5D2A-4C51-9B7E-6A2F15B7F002";
/// <summary>焊缝外观检测记录菜单ID</summary>
public const string HJGL_WeldAppearanceCheckMenuId = "A4C8F8A1-1A27-4B63-A6DF-3F8AAE67C901";
/// <summary>
/// 组对抽检列表台账
@@ -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>
@@ -0,0 +1,292 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace BLL
{
/// <summary>
/// 焊缝外观检测业务服务。
/// </summary>
public static class WeldAppearanceCheckService
{
/// <summary>
/// 分页查询焊缝外观检测记录。
/// </summary>
/// <param name="projectId">项目ID。</param>
/// <param name="pipelineCode">管线号查询条件。</param>
/// <param name="weldJointCode">焊口号查询条件。</param>
/// <param name="qualified">合格状态,1为合格,0为不合格,空为全部。</param>
/// <param name="pageIndex">页码,从0开始。</param>
/// <param name="pageSize">每页记录数。</param>
/// <returns>外观检测记录及总记录数。</returns>
public static Tuple<List<Model.WeldAppearanceCheckItem>, int> GetList(string projectId,
string pipelineCode, string weldJointCode, string qualified, int pageIndex, int pageSize)
{
var db = Funs.DB;
var query = from c in db.HJGL_WeldAppearanceCheck
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 string.IsNullOrEmpty(projectId) || c.ProjectId == projectId
select new { c, w, CheckPersonName = p == null ? string.Empty : p.PersonName };
if (!string.IsNullOrWhiteSpace(pipelineCode))
{
query = query.Where(x => x.w.PipelineCode.Contains(pipelineCode));
}
if (!string.IsNullOrWhiteSpace(weldJointCode))
{
query = query.Where(x => x.w.WeldJointCode.Contains(weldJointCode));
}
if (qualified == "1" || qualified == "0")
{
bool isQualified = qualified == "1";
query = query.Where(x => x.c.IsQualified == isQualified);
}
int total = query.Count();
var data = query.OrderByDescending(x => x.c.CheckTime)
.ThenByDescending(x => x.c.CreateTime)
.Skip(pageIndex * pageSize)
.Take(pageSize)
.Select(x => new Model.WeldAppearanceCheckItem
{
AppearanceCheckId = x.c.AppearanceCheckId,
ProjectId = x.c.ProjectId,
WeldJointId = x.c.WeldJointId,
PipelineCode = x.w.PipelineCode,
WeldJointCode = x.w.WeldJointCode,
IsQualified = x.c.IsQualified,
QualifiedText = x.c.IsQualified ? "合格" : "不合格",
CheckPerson = x.c.CheckPerson,
CheckPersonName = x.CheckPersonName,
CheckTime = x.c.CheckTime,
Remark = x.c.Remark,
CreateTime = x.c.CreateTime
}).ToList();
PopulateAttachUrls(data);
return Tuple.Create(data, total);
}
/// <summary>
/// 分页查询当前项目中已焊接的焊口。
/// </summary>
/// <param name="projectId">项目ID。</param>
/// <param name="pipelineCode">管线号查询条件。</param>
/// <param name="weldJointCode">焊口号查询条件。</param>
/// <param name="pageIndex">页码,从0开始。</param>
/// <param name="pageSize">每页记录数。</param>
/// <returns>已焊接焊口列表。</returns>
public static List<Model.WeldAppearanceJointItem> GetWeldedJoints(string projectId,
string pipelineCode, string weldJointCode, int pageIndex, int pageSize)
{
var db = Funs.DB;
var query = db.View_HJGL_WeldJoint.Where(x => x.ProjectId == projectId && x.WeldingDailyId != null);
if (!string.IsNullOrWhiteSpace(pipelineCode))
{
query = query.Where(x => x.PipelineCode.Contains(pipelineCode));
}
if (!string.IsNullOrWhiteSpace(weldJointCode))
{
query = query.Where(x => x.WeldJointCode.Contains(weldJointCode));
}
return query.OrderBy(x => x.PipelineCode).ThenBy(x => x.WeldJointCode)
.Skip(pageIndex * pageSize).Take(pageSize)
.Select(x => new Model.WeldAppearanceJointItem
{
WeldJointId = x.WeldJointId,
ProjectId = x.ProjectId,
PipelineCode = x.PipelineCode,
WeldJointCode = x.WeldJointCode,
WeldTypeCode = x.WeldTypeCode,
WeldingMethodCode = x.WeldingMethodCode,
WeldingDate = x.WeldingDateD
}).ToList();
}
/// <summary>
/// 查询焊口基础信息及历史外观检测记录。
/// </summary>
/// <param name="weldJointId">焊口ID。</param>
/// <returns>焊口详情及外观检测历史。</returns>
public static Model.WeldAppearanceJointItem GetJointDetail(string weldJointId)
{
var db = Funs.DB;
var joint = db.View_HJGL_WeldJoint.Where(x => x.WeldJointId == weldJointId)
.Select(x => new Model.WeldAppearanceJointItem
{
WeldJointId = x.WeldJointId,
ProjectId = x.ProjectId,
PipelineCode = x.PipelineCode,
WeldJointCode = x.WeldJointCode,
WeldTypeCode = x.WeldTypeCode,
WeldingMethodCode = x.WeldingMethodCode,
WeldingDate = x.WeldingDateD
}).FirstOrDefault();
if (joint != null)
{
joint.History = GetHistory(weldJointId);
}
return joint;
}
/// <summary>
/// 根据记录ID查询焊缝外观检测记录。
/// </summary>
/// <param name="appearanceCheckId">外观检测记录ID。</param>
/// <returns>焊缝外观检测记录。</returns>
public static Model.WeldAppearanceCheckItem GetById(string appearanceCheckId)
{
var item = GetHistoryQuery().FirstOrDefault(x => x.AppearanceCheckId == appearanceCheckId);
if (item != null)
{
item.AttachUrl = GetAttachUrl(item.AppearanceCheckId);
}
return item;
}
/// <summary>
/// 新增或修改焊缝外观检测记录。
/// </summary>
/// <param name="item">外观检测结果及附件信息。</param>
/// <returns>外观检测记录ID。</returns>
public static string Save(Model.WeldAppearanceCheckInput item)
{
if (item == null || string.IsNullOrWhiteSpace(item.WeldJointId))
{
throw new ArgumentException("焊口不能为空。");
}
var db = Funs.DB;
var joint = db.HJGL_WeldJoint.FirstOrDefault(x => x.WeldJointId == item.WeldJointId);
if (joint == null || joint.WeldingDailyId == null)
{
throw new ArgumentException("只能对已焊接焊口进行外观检测。");
}
string id = string.IsNullOrWhiteSpace(item.AppearanceCheckId)
? Guid.NewGuid().ToString()
: item.AppearanceCheckId;
var check = db.HJGL_WeldAppearanceCheck.FirstOrDefault(x => x.AppearanceCheckId == id);
bool hasExistingPhoto = db.AttachFile.Any(x => x.MenuId == Const.HJGL_WeldAppearanceCheckMenuId && x.ToKeyId == id);
if (string.IsNullOrWhiteSpace(item.AttachUrl) && !hasExistingPhoto)
{
throw new ArgumentException("请至少上传一张外观检测照片。");
}
if (check == null)
{
check = new Model.HJGL_WeldAppearanceCheck
{
AppearanceCheckId = id,
CreateTime = DateTime.Now,
CreateUser = string.IsNullOrEmpty(item.CreateUser) ? item.CheckPerson : item.CreateUser
};
db.HJGL_WeldAppearanceCheck.InsertOnSubmit(check);
}
else
{
check.ModifyUser = string.IsNullOrEmpty(item.CreateUser) ? item.CheckPerson : item.CreateUser;
check.ModifyTime = DateTime.Now;
}
check.ProjectId = string.IsNullOrEmpty(item.ProjectId) ? joint.ProjectId : item.ProjectId;
check.WeldJointId = item.WeldJointId;
check.IsQualified = item.IsQualified;
check.CheckPerson = item.CheckPerson;
check.CheckTime = item.CheckTime ?? DateTime.Now;
check.Remark = item.Remark;
db.SubmitChanges();
if (!string.IsNullOrWhiteSpace(item.AttachUrl))
{
UploadFileService.SaveAttachUrl(UploadFileService.GetSourceByAttachUrl(item.AttachUrl, 10, null),
item.AttachUrl, Const.HJGL_WeldAppearanceCheckMenuId, id);
}
return id;
}
/// <summary>
/// 删除焊缝外观检测记录及其附件。
/// </summary>
/// <param name="appearanceCheckId">外观检测记录ID。</param>
public static void Delete(string appearanceCheckId)
{
var db = Funs.DB;
var check = db.HJGL_WeldAppearanceCheck.FirstOrDefault(x => x.AppearanceCheckId == appearanceCheckId);
if (check == null)
{
return;
}
db.HJGL_WeldAppearanceCheck.DeleteOnSubmit(check);
db.SubmitChanges();
CommonService.DeleteAttachFileById(Const.HJGL_WeldAppearanceCheckMenuId, appearanceCheckId);
}
/// <summary>
/// 查询指定焊口的历史外观检测记录。
/// </summary>
/// <param name="weldJointId">焊口ID。</param>
/// <returns>按检测时间倒序排列的历史记录。</returns>
private static List<Model.WeldAppearanceCheckItem> GetHistory(string weldJointId)
{
var data = GetHistoryQuery().Where(x => x.WeldJointId == weldJointId)
.OrderByDescending(x => x.CheckTime).ThenByDescending(x => x.CreateTime).ToList();
PopulateAttachUrls(data);
return data;
}
/// <summary>
/// 构建焊缝外观检测记录查询。
/// </summary>
/// <returns>焊缝外观检测记录查询对象。</returns>
private static IQueryable<Model.WeldAppearanceCheckItem> GetHistoryQuery()
{
var db = Funs.DB;
return from c in db.HJGL_WeldAppearanceCheck
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()
select new Model.WeldAppearanceCheckItem
{
AppearanceCheckId = c.AppearanceCheckId,
ProjectId = c.ProjectId,
WeldJointId = c.WeldJointId,
PipelineCode = w.PipelineCode,
WeldJointCode = w.WeldJointCode,
IsQualified = c.IsQualified,
QualifiedText = c.IsQualified ? "合格" : "不合格",
CheckPerson = c.CheckPerson,
CheckPersonName = p == null ? string.Empty : p.PersonName,
CheckTime = c.CheckTime,
Remark = c.Remark,
CreateTime = c.CreateTime
};
}
/// <summary>
/// 为外观检测记录补充附件地址。
/// </summary>
/// <param name="data">外观检测记录。</param>
private static void PopulateAttachUrls(IList<Model.WeldAppearanceCheckItem> data)
{
foreach (var item in data)
{
item.AttachUrl = GetAttachUrl(item.AppearanceCheckId);
}
}
/// <summary>
/// 查询外观检测记录的附件地址。
/// </summary>
/// <param name="id">外观检测记录ID。</param>
/// <returns>附件地址。</returns>
private static string GetAttachUrl(string id)
{
var db = Funs.DB;
var url = db.AttachFile.Where(x => x.MenuId == Const.HJGL_WeldAppearanceCheckMenuId && x.ToKeyId == id)
.Select(x => x.AttachUrl).FirstOrDefault();
return string.IsNullOrEmpty(url) ? url : url.Replace('\\', '/');
}
}
}
@@ -478,6 +478,15 @@ namespace BLL
/// <param name="welderType">焊工类型 0 全部 1 打底 2 盖面</param>
/// <returns>错误信息</returns>
public static string SaveWeldingDailyTempDetailByMobile(string weldJointId, string personId, string time, string weldingLocationId, int welderType)
{
return SaveWeldingDailyTempDetailByMobile(weldJointId, personId, time, weldingLocationId, welderType, null, null);
}
/// <summary>
/// 移动端按焊口保存焊接日报待审核明细,并按需同步焊接方法和焊缝类型。
/// </summary>
public static string SaveWeldingDailyTempDetailByMobile(string weldJointId, string personId, string time,
string weldingLocationId, int welderType, string weldingMethodId, string weldTypeId)
{
string res = string.Empty;
using (Model.SGGLDB db = new Model.SGGLDB(Funs.ConnString))
@@ -506,6 +515,13 @@ namespace BLL
var weldTask = db.HJGL_WeldTask.FirstOrDefault(x => x.WeldJointId == joint.WeldJointId);
var weldJoint = db.HJGL_WeldJoint.FirstOrDefault(x => x.WeldJointId == joint.WeldJointId);
// 兼容旧版小程序:只有两个参数同时存在时才成对更新,避免焊口工艺信息出现半更新。
if (!string.IsNullOrWhiteSpace(weldingMethodId) && !string.IsNullOrWhiteSpace(weldTypeId))
{
weldJoint.WeldingMethodId = weldingMethodId;
weldJoint.WeldTypeId = weldTypeId;
}
var pending = GetPendingTempDetail(db, weldJointId, weldingDate);
string coverWelderId = pending != null ? pending.CoverWelderId : weldJoint.CoverWelderId;