SNAPSHOT W7 已部署稳定态 — 凯迪ERP+OA一体化平台 (MET 73.3%)

恢复点(restore point)。别人改崩后可 git reset --hard 回到此提交。

== 此快照内容 ==
- 后端 oa-backend: 734 控制器 / 711 实体 (Spring Boot 3.2.5 + SQLite, 端口8091)
- 前端 modern-ui/app: Vue3+Vite, 约700页 (构建产物已在 oa-backend/src/main/resources/static)
- 数据库 oa-backend/data/oa.db: 含全部演示数据 (强制入库, 6.6MB)
- 交接文档 go.md + go-code-reference/endpoints/entities/database.md
- 多代理建设脚本 .claude/wf-*.js

== 状态 ==
- 对 凯迪科技ERP_20260507.xlsx 合规 MET ~73.3% (PARTIAL 75: 34可建+6种子/bug+35外部硬天花板)
- 安全: 5轮红队+5轮复检, default-deny分级鉴权, 连续零可利用
- W3~W7 累计补完436缺口; W8末轮(40缺口)为半成品(源码树可编译但未集成)
- 运行: cd oa-backend; java -jar build/libs/oa-backend-0.1.0.jar --server.port=8091; admin/123456

== 排除(gitignore, 可再生) ==
node_modules / oa-backend/build / .jdks / *.log / Backup-ERP-* / 弃用的OFBiz核心(只保留modern-ui)
完整文件夹备份见同目录 Backup-ERP-20260615-191517/ (含上述全部, 仅缺 node_modules)

时间戳: 20260615-191517

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Qiufeng
2026-06-15 19:19:15 +08:00
co-authored by Claude Opus 4.8
commit 5e51dc3f56
10584 changed files with 2501339 additions and 0 deletions
@@ -0,0 +1,280 @@
package com.kaidi.oa.seed;
import com.kaidi.oa.common.Money;
import com.kaidi.oa.domain.SewageCrossDeptLinkage;
import com.kaidi.oa.domain.SewageExtLabCommission;
import com.kaidi.oa.repository.SewageCrossDeptLinkageRepository;
import com.kaidi.oa.repository.SewageExtLabCommissionRepository;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
/**
* 城镇污水运营·跨部门联动触发器 & 外部实验室委托检测 演示种子数据。
*
* 补深审计 low 缺口(11.与其他部门接口要求):让联动台账与外委检测台账活体可见,
* 覆盖多种状态(成功/失败/待触发 / 合格/超标/待判定),演示完整业务链路。
*
* 幂等:linkageRepo.count() == 0 才插入;commRepo.count() == 0 才插入。
*/
@Component
@Order(30)
public class SewageCrossDeptSeeder implements ApplicationRunner {
private final SewageCrossDeptLinkageRepository linkageRepo;
private final SewageExtLabCommissionRepository commRepo;
public SewageCrossDeptSeeder(SewageCrossDeptLinkageRepository linkageRepo,
SewageExtLabCommissionRepository commRepo) {
this.linkageRepo = linkageRepo;
this.commRepo = commRepo;
}
@Override
@Transactional
public void run(ApplicationArguments args) {
seedLinkages();
seedExtLabCommissions();
}
// ------------------------------------------------------------------ 跨部门联动触发器演示数据
private void seedLinkages() {
if (linkageRepo.count() > 0) return;
Instant now = Instant.now();
// 1. 成功联动:药剂低库存→采购工单(真实写入)
SewageCrossDeptLinkage lk1 = new SewageCrossDeptLinkage();
lk1.setEventKey("REAGENT_LOW_STOCK");
lk1.setSourceId(1L);
lk1.setSourceModule("sewage_reagent_stock");
lk1.setEventDesc("聚合氯化铝(PAC)(凯迪一污水厂)库存 280 kg 低于安全库存 500 kg,需补货");
lk1.setTargetDept("采购部");
lk1.setLinkageAction("生成采购工单");
lk1.setStatus("成功");
lk1.setTargetEntityType("mfg_purchase_order");
lk1.setTargetEntityId(1001L);
lk1.setResultNote("已真实创建采购工单 MfgPurchaseOrder#1001(来源:sewage_reagent_stock/1");
lk1.setOwner("系统自动");
lk1.setTriggeredAt(now.minus(3, ChronoUnit.DAYS));
lk1.setCompletedAt(now.minus(3, ChronoUnit.DAYS).plus(2, ChronoUnit.SECONDS));
lk1.setCreatedAt(now.minus(3, ChronoUnit.DAYS));
lk1.setUpdatedAt(now.minus(3, ChronoUnit.DAYS));
linkageRepo.save(lk1);
// 2. 成功联动:月度成本归集完成→财务凭证(真实写入)
SewageCrossDeptLinkage lk2 = new SewageCrossDeptLinkage();
lk2.setEventKey("COST_MONTH_COMPLETE");
lk2.setSourceId(2L);
lk2.setSourceModule("sewage_cost_month");
lk2.setEventDesc("2026-04 凯迪一污水厂 月度完全成本 ¥386500.00 完成,触发财务过账");
lk2.setTargetDept("财务部");
lk2.setLinkageAction("成本过账");
lk2.setStatus("成功");
lk2.setTargetEntityType("voucher");
lk2.setTargetEntityId(2001L);
lk2.setResultNote("已真实创建记账凭证 Voucher#2001(来源:sewage_cost_month/2)科目:5001-运营成本←2201-应付账款");
lk2.setOwner("系统自动");
lk2.setTriggeredAt(now.minus(10, ChronoUnit.DAYS));
lk2.setCompletedAt(now.minus(10, ChronoUnit.DAYS).plus(1, ChronoUnit.SECONDS));
lk2.setCreatedAt(now.minus(10, ChronoUnit.DAYS));
lk2.setUpdatedAt(now.minus(10, ChronoUnit.DAYS));
linkageRepo.save(lk2);
// 3. 成功联动:检测报告签发→申报服务部数据包
SewageCrossDeptLinkage lk3 = new SewageCrossDeptLinkage();
lk3.setEventKey("DETECT_REPORT_SIGNED");
lk3.setSourceId(5L);
lk3.setSourceModule("sewage_detection_report");
lk3.setEventDesc("2026-05 月度水质检测报告已签发,COD削减量 42.8吨,氨氮削减量 8.6吨");
lk3.setTargetDept("申报服务部");
lk3.setLinkageAction("发送运营数据包");
lk3.setStatus("成功");
lk3.setTargetEntityType("ops_data_package");
lk3.setTargetEntityId(5L);
lk3.setResultNote("已将运营数据(检测报告 sourceId=5)打包推送至申报服务部,含减排贡献数据");
lk3.setOwner("王运营");
lk3.setTriggeredAt(now.minus(5, ChronoUnit.DAYS));
lk3.setCompletedAt(now.minus(5, ChronoUnit.DAYS).plus(1, ChronoUnit.SECONDS));
lk3.setCreatedAt(now.minus(5, ChronoUnit.DAYS));
lk3.setUpdatedAt(now.minus(5, ChronoUnit.DAYS));
linkageRepo.save(lk3);
// 4. 失败联动:月度成本归集→财务部(待重试)
SewageCrossDeptLinkage lk4 = new SewageCrossDeptLinkage();
lk4.setEventKey("COST_MONTH_COMPLETE");
lk4.setSourceId(3L);
lk4.setSourceModule("sewage_cost_month");
lk4.setEventDesc("2026-05 凯迪二污水厂 月度完全成本 ¥312000.00 完成,触发财务过账");
lk4.setTargetDept("财务部");
lk4.setLinkageAction("成本过账");
lk4.setStatus("失败");
lk4.setResultNote("联动执行失败: 财务部凭证接口超时,请稍后重试");
lk4.setOwner("系统自动");
lk4.setTriggeredAt(now.minus(1, ChronoUnit.DAYS));
lk4.setCreatedAt(now.minus(1, ChronoUnit.DAYS));
lk4.setUpdatedAt(now.minus(1, ChronoUnit.DAYS));
linkageRepo.save(lk4);
// 5. 待触发:运营记录自动归档
SewageCrossDeptLinkage lk5 = new SewageCrossDeptLinkage();
lk5.setEventKey("DETECTION_REPORT_ARCHIVE");
lk5.setSourceId(7L);
lk5.setSourceModule("sewage_detection_report");
lk5.setEventDesc("2026-05 水质检测原始记录待归档至资料室");
lk5.setTargetDept("资料室");
lk5.setLinkageAction("自动归档");
lk5.setStatus("待触发");
lk5.setOwner("李化验");
lk5.setTriggeredAt(now);
lk5.setCreatedAt(now);
lk5.setUpdatedAt(now);
linkageRepo.save(lk5);
// 6. 成功联动:外委检测超标→法务风险部(真实写入 LegalRiskEvent
SewageCrossDeptLinkage lk6 = new SewageCrossDeptLinkage();
lk6.setEventKey("EXT_LAB_EXCEED_LEGAL");
lk6.setSourceId(1L);
lk6.setSourceModule("sewage_ext_lab_commission");
lk6.setEventDesc("EXT-LAB-0001 超标(总磷 0.82mg/L),已推送至法务风险部(LegalRiskEvent#3001");
lk6.setTargetDept("法务风险部");
lk6.setLinkageAction("创建环保处罚风险事件");
lk6.setStatus("成功");
lk6.setTargetEntityType("legal_risk_event");
lk6.setTargetEntityId(3001L);
lk6.setResultNote("真实写入 LegalRiskEvent id=3001,类型=行政处罚,状态=待分析");
lk6.setOwner("张水质");
lk6.setTriggeredAt(now.minus(2, ChronoUnit.DAYS));
lk6.setCompletedAt(now.minus(2, ChronoUnit.DAYS).plus(1, ChronoUnit.SECONDS));
lk6.setCreatedAt(now.minus(2, ChronoUnit.DAYS));
lk6.setUpdatedAt(now.minus(2, ChronoUnit.DAYS));
linkageRepo.save(lk6);
}
// ------------------------------------------------------------------ 外部实验室委托检测演示数据
private void seedExtLabCommissions() {
if (commRepo.count() > 0) return;
Instant now = Instant.now();
// 1. 超标整改状态(总磷超标,已推送法务)
SewageExtLabCommission c1 = new SewageExtLabCommission();
c1.setCommissionNo("EXT-LAB-0001");
c1.setPlant("凯迪一污水厂");
c1.setCommissionDate("2026-05-10");
c1.setPlannedReportDate("2026-05-18");
c1.setActualReportDate("2026-05-17");
c1.setLabName("省环境检测技术中心");
c1.setLabCertNo("CMA(2024)川字第12345号");
c1.setSampleType("出水");
c1.setSampleDate("2026-05-10");
c1.setSampleNo("SMP-20260510-001");
c1.setTestItems("COD,氨氮,总磷,总氮,SS,pH");
c1.setResultSummary("COD=8.5mg/L;氨氮=0.42mg/L;总磷=0.82mg/L;总氮=10.6mg/L;SS=6mg/L;pH=7.2");
c1.setComplianceResult("超标");
c1.setExceedItems("总磷");
c1.setCorrectionNote("总磷实测0.82 mg/L,超出GB18918一级A标准0.5 mg/L,需检查深度除磷单元,加强PAC加药量");
c1.setStatus("超标整改");
c1.setAmount(Money.of(3800.0));
c1.setLinkageId(3001L);
c1.setOwner("张水质");
c1.setRemark("第三方年度水质监督性抽检");
c1.setCreatedAt(now.minus(25, ChronoUnit.DAYS));
c1.setUpdatedAt(now.minus(8, ChronoUnit.DAYS));
commRepo.save(c1);
// 2. 合格状态,已归档
SewageExtLabCommission c2 = new SewageExtLabCommission();
c2.setCommissionNo("EXT-LAB-0002");
c2.setPlant("凯迪二污水厂");
c2.setCommissionDate("2026-04-15");
c2.setPlannedReportDate("2026-04-22");
c2.setActualReportDate("2026-04-21");
c2.setLabName("市水质监测站");
c2.setLabCertNo("CNAS L1234");
c2.setSampleType("出水");
c2.setSampleDate("2026-04-15");
c2.setSampleNo("SMP-20260415-002");
c2.setTestItems("COD,氨氮,总磷,总氮,SS");
c2.setResultSummary("COD=6.2mg/L;氨氮=0.18mg/L;总磷=0.32mg/L;总氮=8.4mg/L;SS=4mg/L");
c2.setComplianceResult("合格");
c2.setStatus("已归档");
c2.setAmount(Money.of(2500.0));
c2.setOwner("李化验");
c2.setRemark("季度合规性检测");
c2.setCreatedAt(now.minus(60, ChronoUnit.DAYS));
c2.setUpdatedAt(now.minus(45, ChronoUnit.DAYS));
commRepo.save(c2);
// 3. 检测中(刚发样,尚未出结果)
SewageExtLabCommission c3 = new SewageExtLabCommission();
c3.setCommissionNo("EXT-LAB-0003");
c3.setPlant("凯迪一污水厂");
c3.setCommissionDate("2026-06-05");
c3.setPlannedReportDate("2026-06-15");
c3.setLabName("省环境检测技术中心");
c3.setLabCertNo("CMA(2024)川字第12345号");
c3.setSampleType("工艺段(A/O末端)");
c3.setSampleDate("2026-06-05");
c3.setSampleNo("SMP-20260605-003");
c3.setTestItems("溶解氧,氨氮,总磷,总氮,MLSS");
c3.setComplianceResult("待判定");
c3.setStatus("检测中");
c3.setAmount(Money.of(4200.0));
c3.setOwner("张水质");
c3.setRemark("A/O生化段专项监测,配合工艺优化调整");
c3.setCreatedAt(now.minus(10, ChronoUnit.DAYS));
c3.setUpdatedAt(now.minus(10, ChronoUnit.DAYS));
commRepo.save(c3);
// 4. 待发样(刚创建)
SewageExtLabCommission c4 = new SewageExtLabCommission();
c4.setCommissionNo("EXT-LAB-0004");
c4.setPlant("凯迪三污水厂");
c4.setCommissionDate("2026-06-12");
c4.setPlannedReportDate("2026-06-20");
c4.setLabName("某市第三方水质检测机构");
c4.setSampleType("污泥滤液");
c4.setSampleDate("2026-06-12");
c4.setSampleNo("SMP-20260612-004");
c4.setTestItems("COD,氨氮,重金属(铅,镉,铬)");
c4.setComplianceResult("待判定");
c4.setStatus("待发样");
c4.setAmount(Money.of(5600.0));
c4.setOwner("赵厂长");
c4.setRemark("污泥处置前合规性检测,确认重金属含量符合处置要求");
c4.setCreatedAt(now.minus(3, ChronoUnit.DAYS));
c4.setUpdatedAt(now.minus(3, ChronoUnit.DAYS));
commRepo.save(c4);
// 5. 已出报告-合格(重金属检测通过)
SewageExtLabCommission c5 = new SewageExtLabCommission();
c5.setCommissionNo("EXT-LAB-0005");
c5.setPlant("凯迪二污水厂");
c5.setCommissionDate("2026-05-20");
c5.setPlannedReportDate("2026-05-28");
c5.setActualReportDate("2026-05-27");
c5.setLabName("省环境检测技术中心");
c5.setLabCertNo("CMA(2024)川字第12345号");
c5.setSampleType("进水");
c5.setSampleDate("2026-05-20");
c5.setSampleNo("SMP-20260520-005");
c5.setTestItems("COD,氨氮,总磷,总氮,SS,重金属筛查");
c5.setResultSummary("COD=245mg/L;氨氮=28.6mg/L;总磷=3.2mg/L;总氮=36.4mg/L;SS=180mg/L;重金属未检出");
c5.setComplianceResult("合格");
c5.setStatus("已出报告");
c5.setAmount(Money.of(6800.0));
c5.setOwner("李化验");
c5.setRemark("重要工业用户纳管排查配套检测");
c5.setCreatedAt(now.minus(26, ChronoUnit.DAYS));
c5.setUpdatedAt(now.minus(19, ChronoUnit.DAYS));
commRepo.save(c5);
}
}