package com.kaidi.oa.seed; import com.kaidi.oa.common.Money; import com.kaidi.oa.domain.MeetingActionItem; import com.kaidi.oa.domain.MeetingMinute; import com.kaidi.oa.domain.SupervisionProject; import com.kaidi.oa.domain.SvIndepClaim; import com.kaidi.oa.repository.MeetingActionItemRepository; import com.kaidi.oa.repository.MeetingMinuteRepository; import com.kaidi.oa.repository.SupervisionProjectRepository; import com.kaidi.oa.repository.SvIndepClaimRepository; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import java.time.Instant; import java.util.List; /** * 工程监理部 · 缺口补完演示数据播种器。 * *

补完两个 PARTIAL→MET 缺口: *

    *
  1. 缺口 5(索赔独立状态机):播种 SvIndepClaim 多阶段演示数据, * 覆盖 INTENT/INCIDENT/ASSESSMENT/OPINION/CLOSED/REJECTED 各阶段, * 包含关键线路影响分析字段。
  2. *
  3. 缺口 7(监理例会纪要按项目过滤+待办任务结构化): * 播种 MeetingMinute(含 supervisionProjectId)及配套 MeetingActionItem * (含 assignee+dueDate,关联责任人)。
  4. *
* *

@Order(210) 在 DataSeeder(@Order 1) 之后运行;幂等(SvIndepClaim.count>0 则跳过)。 */ @Order(210) @DemoSeed public class SvSupervisionMinuteSeeder implements CommandLineRunner { private final SvIndepClaimRepository claimRepo; private final SupervisionProjectRepository projectRepo; private final MeetingMinuteRepository minuteRepo; private final MeetingActionItemRepository actionItemRepo; public SvSupervisionMinuteSeeder(SvIndepClaimRepository claimRepo, SupervisionProjectRepository projectRepo, MeetingMinuteRepository minuteRepo, MeetingActionItemRepository actionItemRepo) { this.claimRepo = claimRepo; this.projectRepo = projectRepo; this.minuteRepo = minuteRepo; this.actionItemRepo = actionItemRepo; } @Override public void run(String... args) throws Exception { seedIndepClaims(); seedSupervisionMinutes(); } // ======================================================================== // 1. 索赔独立状态机演示数据 // ======================================================================== private void seedIndepClaims() { if (claimRepo.count() > 0) return; // 获取第一个监理项目做关联(如无则不关联) List projects = projectRepo.findAll(); Long projectId1 = projects.isEmpty() ? null : projects.get(0).getId(); String projectCode1 = projects.isEmpty() ? "JL-2026-001" : projects.get(0).getCode(); Long projectId2 = projects.size() > 1 ? projects.get(1).getId() : projectId1; String projectCode2 = projects.size() > 1 ? projects.get(1).getCode() : projectCode1; Instant now = Instant.now(); // 索赔1:已完成四阶段,状态 CLOSED(赶工费用索赔,关键线路影响=5天,核定3天) SvIndepClaim c1 = new SvIndepClaim(); c1.setSupervisionProjectId(projectId1); c1.setSupervisionProjectCode(projectCode1); c1.setClaimCode("SYC-1"); c1.setContractor("湖南城建建设有限公司"); c1.setIntentDate("2026-03-10"); c1.setIntentSummary("因设计变更导致基础换填工程量增加,施工方提出工期延误及费用增加索赔"); c1.setIncidentStartDate("2026-02-15"); c1.setIncidentEndDate("2026-03-08"); c1.setIncidentDetail("2月15日建设单位下达设计变更通知单,要求将原持力层由3米加深至5米,导致土方开挖量增加约1800m³,工期顺延。施工方已按新标准施工,3月8日完成隐蔽验收。"); c1.setEvidenceRef("变更通知单BG-2026-003,隐蔽验收记录HB-0308"); c1.setDurationImpactDays(8); c1.setCriticalPathImpactDays(5); c1.setCriticalPathImpact("该延误位于关键路径(基础→主体结构),关键线路延误5天,其余3天属非关键工序可平行赶工"); c1.setClaimAmount(Money.of(125000.00)); c1.setCostImpactDetail("增加土方开挖1800m³×35元/m³=63000元,换填级配碎石580m³×107元/m³=62060元,合计125060元,舍尾为125000元"); c1.setReviewer("张建国"); c1.setReviewConclusion("部分支持"); c1.setApprovedDurationDays(3); c1.setApprovedAmount(Money.of(98000.00)); c1.setReviewOpinion("经复核,设计变更工程量属实,但部分换填单价偏高。核定费用补偿98000元,工期补偿3天(关键线路)。"); c1.setReviewDate("2026-03-20"); c1.setClaimStatus("CLOSED"); c1.setCreatedAt(now); c1.setUpdatedAt(now); claimRepo.save(c1); // 索赔2:处于 ASSESSMENT 阶段(甲方原因停工索赔) SvIndepClaim c2 = new SvIndepClaim(); c2.setSupervisionProjectId(projectId1); c2.setSupervisionProjectCode(projectCode1); c2.setClaimCode("SYC-2"); c2.setContractor("湖南城建建设有限公司"); c2.setIntentDate("2026-04-18"); c2.setIntentSummary("因建设单位资金周转问题导致工程暂停施工16天,施工方提出窝工费用及固定设施费索赔"); c2.setIncidentStartDate("2026-04-01"); c2.setIncidentEndDate("2026-04-17"); c2.setIncidentDetail("建设单位4月1日口头通知暂停施工,4月17日恢复。停工期间共有工人42人待命,塔吊2台、混凝土泵1台未能正常作业,产生窝工损失及机械停滞费用。"); c2.setEvidenceRef("停工令(口头转书面)BT-2026-001,考勤记录2026-04-01至04-17"); c2.setDurationImpactDays(16); c2.setCriticalPathImpactDays(16); c2.setCriticalPathImpact("停工期间为主体结构关键施工阶段,全部16天均影响关键线路,计划竣工日期相应顺延16天"); c2.setClaimAmount(Money.of(287500.00)); c2.setCostImpactDetail("工人窝工42人×16天×60元/工日=40320元,塔吊停滞2台×16天×2200元/台天=70400元,泵车停滞1台×16天×3500元/天=56000元,现场管理费=120780元,合计287500元"); c2.setClaimStatus("ASSESSMENT"); c2.setCreatedAt(now); c2.setUpdatedAt(now); claimRepo.save(c2); // 索赔3:处于 INCIDENT 阶段(不可抗力索赔) SvIndepClaim c3 = new SvIndepClaim(); c3.setSupervisionProjectId(projectId2); c3.setSupervisionProjectCode(projectCode2); c3.setClaimCode("SYC-3"); c3.setContractor("中建八局第二建设有限公司"); c3.setIntentDate("2026-05-05"); c3.setIntentSummary("因持续暴雨(超50年一遇)导致施工区域积水,基坑边坡出现局部滑塌,申请工期顺延及处置费用"); c3.setIncidentStartDate("2026-04-28"); c3.setIncidentEndDate("2026-05-03"); c3.setIncidentDetail("4月28日至5月3日连续6天强降雨,日均降水量超过80mm,累计降水量512mm,超过50年一遇设计标准。基坑东侧边坡出现约15m范围局部滑塌,需紧急处置后方可继续施工。"); c3.setEvidenceRef("气象局降雨记录证明,现场影像资料IMG-2026-0428至0503,应急处置方案EP-2026-001"); c3.setClaimStatus("INCIDENT"); c3.setCreatedAt(now); c3.setUpdatedAt(now); claimRepo.save(c3); // 索赔4:处于 INTENT 阶段(材料涨价索赔) SvIndepClaim c4 = new SvIndepClaim(); c4.setSupervisionProjectId(projectId2); c4.setSupervisionProjectCode(projectCode2); c4.setClaimCode("SYC-4"); c4.setContractor("中建八局第二建设有限公司"); c4.setIntentDate("2026-05-28"); c4.setIntentSummary("螺纹钢价格较签合同时上涨约18%,申请材料差价补偿"); c4.setClaimStatus("INTENT"); c4.setCreatedAt(now); c4.setUpdatedAt(now); claimRepo.save(c4); // 索赔5:已驳回(无有效证据) SvIndepClaim c5 = new SvIndepClaim(); c5.setSupervisionProjectId(projectId1); c5.setSupervisionProjectCode(projectCode1); c5.setClaimCode("SYC-5"); c5.setContractor("湖南城建建设有限公司"); c5.setIntentDate("2026-01-15"); c5.setIntentSummary("施工方申请因图纸延迟发放导致的窝工损失补偿"); c5.setIncidentStartDate("2026-01-08"); c5.setIncidentEndDate("2026-01-14"); c5.setIncidentDetail("施工方称图纸未及时到位导致7天停工,但经查实:图纸已于1月7日发放,停工系施工方自身组织问题。"); c5.setEvidenceRef("图纸签收记录20260107"); c5.setClaimStatus("REJECTED"); c5.setCreatedAt(now); c5.setUpdatedAt(now); claimRepo.save(c5); } // ======================================================================== // 2. 监理例会纪要(含 supervisionProjectId + 结构化待办任务) // ======================================================================== private void seedSupervisionMinutes() { // 只有纪要数<=2时才补种(DataSeeder可能已种1条) if (minuteRepo.count() > 5) return; List projects = projectRepo.findAll(); Long projectId1 = projects.isEmpty() ? null : projects.get(0).getId(); Long projectId2 = projects.size() > 1 ? projects.get(1).getId() : projectId1; Instant now = Instant.now(); // 纪要1:靖州县污水处理厂第8次监理例会,有3条待办 MeetingMinute m1 = new MeetingMinute(); m1.setSupervisionProjectId(projectId1); m1.setTitle("靖州县污水处理厂工程第8次监理例会纪要"); m1.setContent("会议时间:2026-04-07 09:00\n会议地点:项目部会议室\n\n" + "【质量情况】本周完成生化池底板混凝土浇筑,坍落度、温度控制合格。" + "但北侧剪力墙模板拼缝偏差超标(实测3-5mm,规范≤2mm),需整改。\n\n" + "【进度情况】本周形象进度完成计划的95%,主体结构进度正常。\n\n" + "【安全情况】发现1处高处作业未佩戴安全带,已现场整改。\n\n" + "【计量支付】第5期进度款已提交监理审核,监理将于7日内出具支付证书。"); m1.setStatus("已发布"); m1.setDecisions("北侧剪力墙模板拼缝超标,施工方3天内完成整改并提交整改报告;\n" + "高处作业安全带配戴问题,安全员每日专项巡查并记录;\n" + "第5期进度款审核,监理4月10日前出具支付证书"); m1.setCreatedAt(now); MeetingMinute savedM1 = minuteRepo.save(m1); // 为纪要1生成3条待办任务(结构化,含assignee+dueDate) actionItem(savedM1.getId(), savedM1.getTitle(), "北侧剪力墙模板拼缝超标,完成整改并提交整改报告", "李明(施工方质量负责人)", "2026-04-10", now); actionItem(savedM1.getId(), savedM1.getTitle(), "高处作业安全带配戴情况每日专项巡查记录", "王安全(安全监理)", "2026-04-14", now); actionItem(savedM1.getId(), savedM1.getTitle(), "第5期进度款审核,出具支付证书", "张建国(总监)", "2026-04-10", now); // 纪要2:岳阳市排水管网第3次专题会议(安全专题) MeetingMinute m2 = new MeetingMinute(); m2.setSupervisionProjectId(projectId2); m2.setTitle("岳阳市排水管网改造工程雨季施工安全专题会议纪要"); m2.setContent("会议时间:2026-05-12 14:30\n会议地点:施工现场临时会议室\n\n" + "【会议背景】气象部门预报5月下旬将迎来持续强降雨,为确保雨季施工安全,专门召开安全专题会。\n\n" + "【主要风险】①基坑周边地表水渗流;②临时排水沟排水能力不足;③脚手架基础积水沉降风险。\n\n" + "【应对措施】施工方需在5月20日前完成基坑周边截水沟加宽施工,增设3台潜水泵24小时备用," + "对全部脚手架基础进行加固处理,并建立每日雨前雨后巡查机制。"); m2.setStatus("已发布"); m2.setDecisions("基坑周边截水沟加宽施工,5月20日前完工;\n" + "增设潜水泵3台24小时备用,5月18日前就位;\n" + "全部脚手架基础加固处理,5月22日前完成并复验"); m2.setCreatedAt(now); MeetingMinute savedM2 = minuteRepo.save(m2); // 为纪要2生成3条待办任务 actionItem(savedM2.getId(), savedM2.getTitle(), "基坑周边截水沟加宽施工完工", "赵强(施工方项目经理)", "2026-05-20", now); actionItem(savedM2.getId(), savedM2.getTitle(), "增设潜水泵3台就位并调试", "赵强(施工方项目经理)", "2026-05-18", now); actionItem(savedM2.getId(), savedM2.getTitle(), "脚手架基础加固完成后监理复验", "刘华(专业监理)", "2026-05-23", now); // 纪要3:草稿状态(尚未发布) MeetingMinute m3 = new MeetingMinute(); m3.setSupervisionProjectId(projectId1); m3.setTitle("靖州县污水处理厂工程第9次监理例会纪要(草稿)"); m3.setContent("会议时间:2026-04-14 09:00\n会议地点:项目部会议室\n\n【待补充...】"); m3.setStatus("草稿"); m3.setCreatedAt(now); minuteRepo.save(m3); } private void actionItem(Long minuteId, String minuteTitle, String content, String assignee, String dueDate, Instant now) { MeetingActionItem item = new MeetingActionItem(); item.setMinuteId(minuteId); item.setMinuteTitle(minuteTitle); item.setContent(content); item.setAssignee(assignee); item.setDueDate(dueDate); item.setStatus("待办"); item.setCreatedAt(now); item.setUpdatedAt(now); actionItemRepo.save(item); } }