using FineUIPro; using Model; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Transactions; namespace BLL { /// /// 防腐委托单服务。 /// public static class TwAntiCorrosionTrustService { public static int Count { get; set; } public static List GetListData(AntiCorrosionTrustOutput filter) { filter = filter ?? new AntiCorrosionTrustOutput(); var data = (from t in Funs.DB.Tw_AntiCorrosionTrust join uw in Funs.DB.WBS_UnitWork on t.UnitWorkId equals uw.UnitWorkId into unitWorks from uw in unitWorks.DefaultIfEmpty() join p in Funs.DB.Person_Persons on t.CreateMan equals p.PersonId into persons from p in persons.DefaultIfEmpty() where (string.IsNullOrEmpty(filter.Id) || t.Id == filter.Id) && (string.IsNullOrEmpty(filter.ProjectId) || t.ProjectId == filter.ProjectId) && (string.IsNullOrEmpty(filter.UnitWorkId) || t.UnitWorkId == filter.UnitWorkId) && (string.IsNullOrEmpty(filter.TrustCode) || t.TrustCode.Contains(filter.TrustCode)) && (string.IsNullOrEmpty(filter.WeldTaskCode) || t.WeldTaskCode.Contains(filter.WeldTaskCode)) orderby t.CreateDate descending, t.TrustCode descending select new AntiCorrosionTrustOutput { Id = t.Id, ProjectId = t.ProjectId, UnitWorkId = t.UnitWorkId, UnitWorkName = uw == null ? string.Empty : uw.UnitWorkName, ConstructionPart = t.ConstructionPart, ConstructionProfessional = t.ConstructionProfessional, TrustCode = t.TrustCode, WeldTaskCode = t.WeldTaskCode, HotProessTrustId = t.HotProessTrustId, OutputMasterCode = string.Empty, DemandDate = t.DemandDate, CompleteDate = t.CompleteDate, CreateMan = t.CreateMan, CreateManName = p == null ? string.Empty : p.PersonName, CreateDate = t.CreateDate, Remark = t.Remark }).ToList(); var taskCodes = data.Select(x => x.WeldTaskCode).Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList(); var taskTeams = Funs.DB.HJGL_WeldTask .Where(x => taskCodes.Contains(x.TaskCode)) .Select(x => new { x.ProjectId, x.TaskCode, x.TeamGroupId }) .ToList() .GroupBy(x => x.ProjectId + "|" + x.TaskCode) .ToDictionary(x => x.Key, x => x.Select(y => y.TeamGroupId).FirstOrDefault(y => !string.IsNullOrEmpty(y))); var teamIds = taskTeams.Values.Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList(); var teamNames = Funs.DB.ProjectData_TeamGroup.Where(x => teamIds.Contains(x.TeamGroupId)) .ToDictionary(x => x.TeamGroupId, x => x.TeamGroupName); foreach (var item in data.Where(x => !string.IsNullOrEmpty(x.WeldTaskCode))) { string teamId; if (taskTeams.TryGetValue(item.ProjectId + "|" + item.WeldTaskCode, out teamId)) { item.TeamGroupId = teamId; item.TeamGroupName = !string.IsNullOrEmpty(teamId) && teamNames.ContainsKey(teamId) ? teamNames[teamId] : string.Empty; } } return data; } public static IEnumerable GetListData(AntiCorrosionTrustOutput filter, Grid grid) { var list = GetListData(filter); Count = list.Count; return list.Skip(grid.PageIndex * grid.PageSize).Take(grid.PageSize).ToList(); } public static AntiCorrosionTrustOutput GetById(string id) { return string.IsNullOrEmpty(id) ? null : GetListData(new AntiCorrosionTrustOutput { Id = id }).FirstOrDefault(); } public static bool IsExistTrustCode(string trustCode, string id, string projectId) { return Funs.DB.Tw_AntiCorrosionTrust.Any(x => x.TrustCode == trustCode && x.ProjectId == projectId && (string.IsNullOrEmpty(id) || x.Id != id)); } public static string GenerateTrustCode(string unitWorkId) { var unitWork = UnitWorkService.GetUnitWorkByUnitWorkId(unitWorkId); if (unitWork == null) return string.Empty; string prefix = "SXHJ-ECFF-" + unitWork.UnitWorkName + "-"; // 生成按钮和拆单均在事务中调用;锁定同一单位工程编号范围,避免并发取到相同流水号。 var trustCodes = Funs.DB.ExecuteQuery( "SELECT TrustCode FROM dbo.Tw_AntiCorrosionTrust WITH (UPDLOCK,HOLDLOCK) WHERE UnitWorkId={0}", unitWorkId).ToList(); int maxSerial = trustCodes.Where(x => x != null && x.StartsWith(prefix)) .Select(GetTrustCodeSerial).DefaultIfEmpty(0).Max(); return prefix + (maxSerial + 1).ToString("000"); } public static List GetAvailableWeldTasks(string projectId, string unitWorkId, string currentTrustId) { var used = Funs.DB.Tw_AntiCorrosionTrust .Where(x => x.ProjectId == projectId && x.WeldTaskCode != null && (string.IsNullOrEmpty(currentTrustId) || x.Id != currentTrustId)) .Select(x => x.WeldTaskCode).ToList(); return WeldTaskService.GetTaskListByTeamGroup(projectId, null, unitWorkId) .Where(x => !used.Contains(x.TaskCode)).ToList(); } public static List GetDetailList(string trustId) { return (from d in Funs.DB.Tw_AntiCorrosionTrustDetail join m in Funs.DB.HJGL_MaterialCodeLib on d.MaterialCode equals m.MaterialCode into materials from m in materials.DefaultIfEmpty() where d.TrustId == trustId orderby d.SortIndex select new AntiCorrosionTrustDetailOutput { Id = d.Id, TrustId = d.TrustId, SortIndex = d.SortIndex, MaterialCode = d.MaterialCode, Code = m == null ? string.Empty : m.Code, MaterialName = m == null ? string.Empty : m.MaterialName, MaterialSpec = m == null ? string.Empty : m.MaterialSpec, MaterialDef = m == null ? string.Empty : m.MaterialDef, MaterialUnit = m == null ? string.Empty : m.MaterialUnit, Quantity = d.Quantity, PaintCode = d.PaintCode, Primer = d.Primer, IntermediatePaint = d.IntermediatePaint, Topcoat = d.Topcoat, ColorCode = d.ColorCode, IsPostWeld = d.IsPostWeld, Remark = d.Remark }).ToList(); } public static List GetDetailsByTaskCode(string projectId, string taskCode) { var weldJointIds = Funs.DB.HJGL_WeldTask .Where(x => x.ProjectId == projectId && x.TaskCode == taskCode && x.WeldJointId != null) .Select(x => x.WeldJointId).Distinct().ToList(); return BuildDetailsByWeldJointIds(weldJointIds, false, false); } public static List GetDetailsByHotProessTrustId(string hotProessTrustId) { var weldJointIds = Funs.DB.HJGL_HotProess_TrustItem .Where(x => x.HotProessTrustId == hotProessTrustId && x.IsCompleted == true && Funs.DB.HJGL_HotProess_Report.Any(r => r.HotProessTrustItemId == x.HotProessTrustItemId)) .Select(x => x.WeldJointId).Where(x => x != null).Distinct().ToList(); return BuildDetailsByWeldJointIds(weldJointIds, true, true); } private static List BuildDetailsByWeldJointIds( List weldJointIds, bool isPostWeld, bool fillComponentRemark) { if (weldJointIds == null || weldJointIds.Count == 0) return new List(); var materials = (from pm in Funs.DB.HJGL_PipeLineMat join material in Funs.DB.HJGL_MaterialCodeLib on pm.MaterialCode equals material.MaterialCode join joint in Funs.DB.HJGL_WeldJoint on pm.WeldJointId equals joint.WeldJointId join pipeline in Funs.DB.HJGL_Pipeline on joint.PipelineId equals pipeline.PipelineId into pipelines from pipeline in pipelines.DefaultIfEmpty() join paint in Funs.DB.Tw_PaintCodeDict on pipeline.PaintId equals paint.Id into paints from paint in paints.DefaultIfEmpty() where weldJointIds.Contains(pm.WeldJointId) && pm.MaterialCode != null select new { pm.MaterialCode, pm.Number, pm.PrefabricatedComponents, PaintId = pipeline == null ? null : pipeline.PaintId, PaintCode = paint == null ? null : paint.PaintCode, Primer = paint == null ? null : paint.Primer, IntermediatePaint = paint == null ? null : paint.IntermediatePaint, Topcoat = paint == null ? null : paint.Topcoat, ColorCode = paint == null ? null : paint.ColorCode, material.Code, material.MaterialName, material.MaterialSpec, material.MaterialDef, material.MaterialUnit }).ToList(); int index = 0; return materials.GroupBy(x => new { x.MaterialCode, x.PaintId }) .OrderBy(x => x.Key.MaterialCode).ThenBy(x => x.Key.PaintId) .Select(group => { index++; var first = group.First(); string remark = string.Empty; if (fillComponentRemark) { remark = string.Join("、", group.Select(x => x.PrefabricatedComponents) .Where(x => !string.IsNullOrWhiteSpace(x)).Distinct().OrderBy(x => x)); } return new AntiCorrosionTrustDetailOutput { Id = SQLHelper.GetNewID(), SortIndex = index, MaterialCode = first.MaterialCode, Code = first.Code, MaterialName = first.MaterialName, MaterialSpec = first.MaterialSpec, MaterialDef = first.MaterialDef, MaterialUnit = first.MaterialUnit, Quantity = group.Sum(x => x.Number ?? 0), PaintCode = first.PaintCode, Primer = first.Primer, IntermediatePaint = first.IntermediatePaint, Topcoat = first.Topcoat, ColorCode = first.ColorCode, IsPostWeld = isPostWeld, Remark = remark }; }).ToList(); } public static List GetPaintCodeList() { return Funs.DB.Tw_PaintCodeDict.Where(x => x.IsUsed).OrderBy(x => x.SortIndex).ThenBy(x => x.PaintCode) .Select(x => new PaintCodeDictOutput { Id = x.Id, PaintCode = x.PaintCode, Primer = x.Primer, IntermediatePaint = x.IntermediatePaint, Topcoat = x.Topcoat, ColorCode = x.ColorCode, SortIndex = x.SortIndex }).ToList(); } public static void Save(AntiCorrosionTrustOutput trust, List details, bool splitOnSubmit) { if (trust == null) throw new ArgumentNullException("trust"); var validDetails = (details ?? new List()) .Where(x => !string.IsNullOrWhiteSpace(x.MaterialCode)).OrderBy(x => x.SortIndex ?? int.MaxValue).ToList(); if (validDetails.Count == 0) throw new ArgumentException("防腐委托单明细不能为空。"); using (var scope = new TransactionScope()) { if (string.IsNullOrEmpty(trust.Id)) { // 新单在保存事务内重新取号,页面预览编号不作为最终并发依据。 trust.TrustCode = GenerateTrustCode(trust.UnitWorkId); } if (!splitOnSubmit || validDetails.Select(x => x.IsPostWeld).Distinct().Count() == 1) { var entity = SaveCategory(trust, validDetails, true, splitOnSubmit); trust.Id = entity.Id; } else { bool originalCategory = validDetails.First().IsPostWeld; var originalDetails = validDetails.Where(x => x.IsPostWeld == originalCategory).ToList(); var splitDetails = validDetails.Where(x => x.IsPostWeld != originalCategory).ToList(); var original = SaveCategory(trust, originalDetails, true, true); Funs.DB.SubmitChanges(); var splitTrust = new AntiCorrosionTrustOutput { ProjectId = trust.ProjectId, UnitWorkId = trust.UnitWorkId, ConstructionPart = trust.ConstructionPart, ConstructionProfessional = trust.ConstructionProfessional, TrustCode = GenerateTrustCode(trust.UnitWorkId), DemandDate = trust.DemandDate, CompleteDate = trust.CompleteDate, CreateMan = trust.CreateMan, // 来源ID只保留在原单,保证同一来源可可靠防重。 WeldTaskCode = null, HotProessTrustId = null }; SaveCategory(splitTrust, splitDetails, false, true); trust.Id = original.Id; } Funs.DB.SubmitChanges(); scope.Complete(); } } public static string GenerateByTaskCode(string projectId, string taskCode, string createMan) { using (var scope = new TransactionScope()) { var existingId = Funs.DB.ExecuteQuery( "SELECT Id FROM dbo.Tw_AntiCorrosionTrust WITH (UPDLOCK,HOLDLOCK) WHERE ProjectId={0} AND WeldTaskCode={1}", projectId, taskCode).FirstOrDefault(); if (!string.IsNullOrEmpty(existingId)) { scope.Complete(); return existingId; } var task = WeldTaskService.GetTaskDetail(projectId, taskCode); if (task == null) throw new ArgumentException("焊接任务单不存在。"); var details = GetDetailsByTaskCode(projectId, taskCode); if (details.Count == 0) throw new ArgumentException("任务单没有可生成防腐委托的焊口材料。"); var trust = new AntiCorrosionTrustOutput { ProjectId = projectId, UnitWorkId = task.UnitWorkId, TrustCode = GenerateTrustCode(task.UnitWorkId), WeldTaskCode = taskCode, DemandDate = task.TaskDate, CreateMan = createMan, Remark = "原材料防腐" }; Save(trust, details, true); scope.Complete(); return trust.Id; } } public static string GenerateByHotProessTrustId(string hotProessTrustId, string createMan) { using (var scope = new TransactionScope()) { var existingId = Funs.DB.ExecuteQuery( "SELECT Id FROM dbo.Tw_AntiCorrosionTrust WITH (UPDLOCK,HOLDLOCK) WHERE HotProessTrustId={0}", hotProessTrustId).FirstOrDefault(); if (!string.IsNullOrEmpty(existingId)) { scope.Complete(); return existingId; } var hotTrust = Funs.DB.HJGL_HotProess_Trust.FirstOrDefault(x => x.HotProessTrustId == hotProessTrustId); if (hotTrust == null) throw new ArgumentException("热处理委托不存在。"); var details = GetDetailsByHotProessTrustId(hotProessTrustId); if (details.Count == 0) throw new ArgumentException("当前热处理报告没有可生成防腐委托的已完成焊口材料。"); var trust = new AntiCorrosionTrustOutput { ProjectId = hotTrust.ProjectId, UnitWorkId = hotTrust.UnitWorkId, TrustCode = GenerateTrustCode(hotTrust.UnitWorkId), HotProessTrustId = hotProessTrustId, CreateMan = createMan, Remark = "管段防腐" }; Save(trust, details, true); scope.Complete(); return trust.Id; } } private static Tw_AntiCorrosionTrust SaveCategory( AntiCorrosionTrustOutput trust, List details, bool keepSource, bool applyCategoryRemark) { var entity = string.IsNullOrEmpty(trust.Id) ? null : Funs.DB.Tw_AntiCorrosionTrust.FirstOrDefault(x => x.Id == trust.Id); if (entity == null) { entity = new Tw_AntiCorrosionTrust { Id = SQLHelper.GetNewID(), ProjectId = trust.ProjectId, CreateMan = trust.CreateMan, CreateDate = DateTime.Now }; Funs.DB.Tw_AntiCorrosionTrust.InsertOnSubmit(entity); } bool isPostWeld = details.First().IsPostWeld; entity.UnitWorkId = trust.UnitWorkId; entity.ConstructionPart = trust.ConstructionPart; entity.ConstructionProfessional = trust.ConstructionProfessional; entity.TrustCode = trust.TrustCode; entity.WeldTaskCode = keepSource ? trust.WeldTaskCode : null; entity.HotProessTrustId = keepSource ? trust.HotProessTrustId : null; entity.DemandDate = trust.DemandDate; entity.CompleteDate = trust.CompleteDate; entity.Remark = applyCategoryRemark ? (isPostWeld ? "管段防腐" : "原材料防腐") : trust.Remark; var oldDetails = Funs.DB.Tw_AntiCorrosionTrustDetail.Where(x => x.TrustId == entity.Id).ToList(); Funs.DB.Tw_AntiCorrosionTrustDetail.DeleteAllOnSubmit(oldDetails); var paintMap = GetPaintCodeList().ToDictionary(x => x.PaintCode ?? string.Empty, x => x); int index = 0; foreach (var detail in details) { index++; PaintCodeDictOutput paint; if (!string.IsNullOrEmpty(detail.PaintCode) && paintMap.TryGetValue(detail.PaintCode, out paint)) { detail.Primer = paint.Primer; detail.IntermediatePaint = paint.IntermediatePaint; detail.Topcoat = paint.Topcoat; detail.ColorCode = paint.ColorCode; } Funs.DB.Tw_AntiCorrosionTrustDetail.InsertOnSubmit(new Tw_AntiCorrosionTrustDetail { Id = SQLHelper.GetNewID(), TrustId = entity.Id, SortIndex = detail.SortIndex ?? index, MaterialCode = detail.MaterialCode, Quantity = detail.Quantity, PaintCode = detail.PaintCode, Primer = detail.Primer, IntermediatePaint = detail.IntermediatePaint, Topcoat = detail.Topcoat, ColorCode = detail.ColorCode, IsPostWeld = detail.IsPostWeld, Remark = detail.Remark }); } return entity; } public static void DeleteById(string id) { var details = Funs.DB.Tw_AntiCorrosionTrustDetail.Where(x => x.TrustId == id).ToList(); Funs.DB.Tw_AntiCorrosionTrustDetail.DeleteAllOnSubmit(details); var trust = Funs.DB.Tw_AntiCorrosionTrust.FirstOrDefault(x => x.Id == id); if (trust != null) Funs.DB.Tw_AntiCorrosionTrust.DeleteOnSubmit(trust); Funs.DB.SubmitChanges(); } public static DataTable GetPrintMasterTable(string id) { var query = (from t in Funs.DB.Tw_AntiCorrosionTrust join p in Funs.DB.Base_Project on t.ProjectId equals p.ProjectId into projects from p in projects.DefaultIfEmpty() join uw in Funs.DB.WBS_UnitWork on t.UnitWorkId equals uw.UnitWorkId into unitWorks from uw in unitWorks.DefaultIfEmpty() join person in Funs.DB.Person_Persons on t.CreateMan equals person.PersonId into persons from person in persons.DefaultIfEmpty() where t.Id == id select new { ProjectName = p == null ? string.Empty : p.ProjectName, UnitWorkName = uw == null ? string.Empty : uw.UnitWorkName, UnitWorkCode = uw == null ? string.Empty : uw.UnitWorkCode, t.ConstructionPart, t.ConstructionProfessional, t.TrustCode, OutputMasterCode = string.Empty, t.DemandDate, t.CompleteDate, CreateManName = person == null ? string.Empty : person.PersonName }).ToList().Select(x => new { x.ProjectName, x.UnitWorkName, x.UnitWorkCode, x.ConstructionPart, x.ConstructionProfessional, x.TrustCode, x.OutputMasterCode, DemandDate = x.DemandDate.HasValue ? x.DemandDate.Value.ToString("yyyy-MM-dd") : string.Empty, CompleteDate = x.CompleteDate.HasValue ? x.CompleteDate.Value.ToString("yyyy-MM-dd") : string.Empty, x.CreateManName }); return ToDataTable(query, "Table1"); } public static DataTable GetPrintDetailTable(string id) { var query = GetDetailList(id).Select(x => new { x.SortIndex, x.Code, x.MaterialName, x.MaterialSpec, x.MaterialDef, x.MaterialUnit, x.Quantity, x.PaintCode, x.Primer, x.IntermediatePaint, x.Topcoat, x.ColorCode, IsPostWeld = x.IsPostWeld ? "是" : "否", x.Remark }); // FastReport 防腐委托模板的数据带固定绑定 Data,表名必须与模板保持一致。 return ToDataTable(query, "Data"); } private static int GetTrustCodeSerial(string trustCode) { if (string.IsNullOrEmpty(trustCode)) return 0; int index = trustCode.LastIndexOf('-'); int serial; return index >= 0 && int.TryParse(trustCode.Substring(index + 1), out serial) ? serial : 0; } private static DataTable ToDataTable(IEnumerable data, string tableName) { var table = new DataTable(tableName); var properties = typeof(T).GetProperties(); foreach (var property in properties) { table.Columns.Add(property.Name, Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType); } foreach (var item in data) { var row = table.NewRow(); foreach (var property in properties) { row[property.Name] = property.GetValue(item, null) ?? DBNull.Value; } table.Rows.Add(row); } return table; } } }