Files
ERP/oa-backend/src/main/java/com/kaidi/oa/seed/SewageBenchmarkSeeder.java
T
Qiufeng 1affcd9a5e
Signed Release / release (push) Failing after 5m1s
feat: add PostgreSQL web installation wizard
2026-08-04 07:42:20 +08:00

236 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.kaidi.oa.seed;
import com.kaidi.oa.domain.SewageCostSavingProject;
import com.kaidi.oa.domain.SewagePlantBenchmark;
import com.kaidi.oa.repository.SewageCostSavingProjectRepository;
import com.kaidi.oa.repository.SewagePlantBenchmarkRepository;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
/**
* 城镇污水运营中心·横向对标 + 降本增效项目台账 演示种子数据。
*
* 补深审计 low 缺口(8.绩效与成本分析):
* 1. SewagePlantBenchmark:同区域同类水厂外部横向对标数据(6家水厂,含本厂,湖南区域一级A口径);
* 2. SewageCostSavingProject:节能技改项目独立台账(5个项目,多状态多类型,含基期+实际节约额自动计算)。
*
* 幂等:各表 count == 0 才插入。
*/
@DemoSeed
@Order(206)
public class SewageBenchmarkSeeder implements ApplicationRunner {
private final SewagePlantBenchmarkRepository benchmarkRepo;
private final SewageCostSavingProjectRepository savingRepo;
public SewageBenchmarkSeeder(SewagePlantBenchmarkRepository benchmarkRepo,
SewageCostSavingProjectRepository savingRepo) {
this.benchmarkRepo = benchmarkRepo;
this.savingRepo = savingRepo;
}
@Override
@Transactional
public void run(ApplicationArguments args) {
seedBenchmarks();
seedCostSavingProjects();
}
// ------------------------------------------------------------------ 同类水厂横向对标
private void seedBenchmarks() {
if (benchmarkRepo.count() > 0) return;
// 本厂(凯迪科技·城镇污水一厂,标注 isSelf=true
benchmark("凯迪科技城镇污水一厂", "湖南省·岳阳市", 5.0, "一级A", "2025",
0.312, 18.5, "0.058", "1.85",
97.2, 96.8, "自填", true, "王芳");
// 区域同类水厂 A(处理规模相近)
benchmark("岳阳滨水污水处理有限公司", "湖南省·岳阳市", 4.0, "一级A", "2025",
0.298, 16.2, "0.052", "1.72",
98.1, 97.5, "政府公开", false, "刘洋");
// 区域同类水厂 B(区域最优,吨水电耗最低)
benchmark("岳阳君山水务股份有限公司", "湖南省·岳阳市", 6.0, "一级A", "2025",
0.275, 15.8, "0.048", "1.63",
98.5, 98.2, "行业报告·住建部2025年城镇排水年报", false, "刘洋");
// 区域同类水厂 C(规模稍大)
benchmark("湘阴城乡水务集团第二污水厂", "湖南省·岳阳市", 8.0, "一级A", "2025",
0.305, 17.3, "0.055", "1.78",
96.8, 95.5, "集团汇总", false, "陈静");
// 区域同类水厂 D(较差样本,拉开分布)
benchmark("临湘市污水处理厂", "湖南省·岳阳市", 3.0, "一级A", "2025",
0.338, 20.6, "0.068", "2.05",
94.2, 93.1, "政府公开", false, "陈静");
// 省级对标样本(规模最大,指标优异)
benchmark("长沙第二污水处理厂", "湖南省·长沙市", 20.0, "地方特别限值", "2025",
0.258, 14.1, "0.042", "1.52",
99.0, 98.8, "行业报告·2025湖南省城镇污水处理年报", false, "王芳");
}
private void benchmark(String plantName, String region, double capacity, String dischargeStd,
String statPeriod, double unitPower, double unitReagent,
String unitRepairCost, String unitTotalCost,
double complianceRate, double equipIntactRate,
String dataSrc, boolean isSelf, String maintainer) {
SewagePlantBenchmark b = new SewagePlantBenchmark();
b.setPlantName(plantName);
b.setRegion(region);
b.setCapacity(capacity);
b.setDischargeStd(dischargeStd);
b.setStatPeriod(statPeriod);
b.setUnitPower(unitPower);
b.setUnitReagent(unitReagent);
b.setUnitRepairCost(new java.math.BigDecimal(unitRepairCost));
b.setUnitTotalCost(new java.math.BigDecimal(unitTotalCost));
b.setComplianceRate(complianceRate);
b.setEquipIntactRate(equipIntactRate);
b.setDataSrc(dataSrc);
b.setIsSelf(isSelf);
b.setMaintainer(maintainer);
b.setCreatedAt(Instant.now());
b.setUpdatedAt(Instant.now());
benchmarkRepo.save(b);
}
// ------------------------------------------------------------------ 降本增效项目台账
private void seedCostSavingProjects() {
if (savingRepo.count() > 0) return;
// 项目1:曝气变频改造——已完结,节约可观
// 基期:吨水电耗 0.32 kWh/m³,月均水量 150000 m³
// 改造后:吨水电耗 0.275 kWh/m³,验证 6 个月
// 节约电量/月 = (0.32-0.275) × 150000 = 6750 kWh/月
// 节约电费 = 6750 × 6 × 0.58 = 23490 元
costSavingProject("JNJ-0001", "曝气系统变频节能改造", "节能改造", "水厂1号",
"2024-03-01", "2024-08-31", "2024-09-15",
"98000", 3,
0.32, 22.5, 150000.0,
6, 0.275, 22.0, 155000.0,
"0.58", "8.50",
"已完结", "王芳",
"对3台提升泵+曝气风机加装变频器,实现精确曝气控制。已通过3个月基期+6个月效果验证,累计节约电量40500 kWh,节约电费23490元,静态回收期约25个月。");
// 项目2:精确加药系统升级——已完结,药耗降低
// 基期:吨水药耗 20 g/m³,月均水量 150000 m³,药剂单价 8.5 元/kg
// 改造后:吨水药耗 17.5 g/m³,验证 3 个月
// 节约药量/月 = (20-17.5)/1000 × 150000 = 375 kg/月
// 节约药费 = 375 × 3 × 8.5 = 9562.5 元
costSavingProject("JNJ-0002", "在线水质联动精确加药系统", "精确加药", "水厂1号",
"2024-06-01", "2024-10-31", "2024-11-10",
"65000", 3,
0.31, 20.0, 150000.0,
3, 0.31, 17.5, 152000.0,
"0.58", "8.50",
"已完结", "刘洋",
"引入在线氨氮/TP传感器与加药泵PLC联动,实现PAC/PAM按需投加。药耗下降12.5%,月节约药剂375 kg,节约费用约3187元/月。");
// 项目3:PAM替换为改性淀粉基助凝剂(药剂替代)——效果验证中
// 基期:吨水药耗 5.2 g/m³(PAM),药剂单价 12 元/kg
// 替换后:预期吨水药耗 4.5 g/m³,药剂单价 7.8 元/kg(改性淀粉)
costSavingProject("JNJ-0003", "PAM替代:改性淀粉基助凝剂中试", "药剂替代", "水厂1号",
"2025-03-01", "2025-08-31", null,
"28000", 3,
0.31, 5.2, 148000.0,
3, 0.31, 4.5, 148000.0,
"0.58", "7.80",
"效果验证", "陈静",
"试用改性淀粉基绿色助凝剂替代PAM,环保指标更优且成本更低。目前已完成3个月中试,吨水药耗从5.2降至4.5 g/m³,进入效果验证阶段。");
// 项目4:污泥脱水系统能效提升——改造中
costSavingProject("JNJ-0004", "污泥脱水机变频节能改造", "节能改造", "水厂2号",
"2025-08-01", "2025-12-31", null,
"45000", 3,
0.29, 18.0, 120000.0,
3, 0.265, 18.0, 120000.0,
"0.58", "8.50",
"改造中", "王芳",
"对2台带式压滤机驱动电机实施变频改造,预计吨水电耗降低0.025 kWh/m³,月节约电量3000 kWh。目前设备已进场,安装调试中。");
// 项目5:峰谷用电策略优化——立项中
costSavingProject("JNJ-0005", "峰谷电价优化运行策略", "工艺优化", "全站",
"2025-11-01", "2026-03-31", null,
"5000", 3,
0.32, 19.5, 270000.0,
6, 0.305, 19.5, 270000.0,
"0.58", "8.50",
"立项中", "刘洋",
"分析峰谷用电时段,将非核心用电负荷(污泥脱水、曝气辅机)移至谷段运行。通过调整运行策略降低电费(综合电价从0.58降至平均0.55元/kWh),无设备改造,主要是运行制度优化。");
}
private void costSavingProject(String code, String projectName, String projectType, String plant,
String kickoffDate, String planFinishDate, String actualFinishDate,
String investCost, int baseMonths,
double baseUnitPower, double baseUnitReagent, double baseMonthlyWater,
int verifyMonths, double actualUnitPower, double actualUnitReagent, double actualMonthlyWater,
String powerPrice, String reagentPrice,
String projStatus, String owner, String remark) {
SewageCostSavingProject p = new SewageCostSavingProject();
p.setCode(code);
p.setProjectName(projectName);
p.setProjectType(projectType);
p.setPlant(plant);
p.setKickoffDate(kickoffDate);
p.setPlanFinishDate(planFinishDate);
p.setActualFinishDate(actualFinishDate);
p.setInvestCost(new BigDecimal(investCost));
p.setBaseMonths(baseMonths);
p.setBaseUnitPower(baseUnitPower);
p.setBaseUnitReagent(baseUnitReagent);
p.setBaseMonthlyWater(baseMonthlyWater);
p.setVerifyMonths(verifyMonths);
p.setActualUnitPower(actualUnitPower);
p.setActualUnitReagent(actualUnitReagent);
p.setActualMonthlyWater(actualMonthlyWater);
p.setPowerPrice(new BigDecimal(powerPrice));
p.setReagentPrice(new BigDecimal(reagentPrice));
p.setProjStatus(projStatus);
p.setOwner(owner);
p.setRemark(remark);
p.setCreatedAt(Instant.now());
p.setUpdatedAt(Instant.now());
// 自动计算节约量
double deltaUnitPower = baseUnitPower - actualUnitPower;
double savedKwhPerM = Math.max(0, deltaUnitPower * actualMonthlyWater);
double savedKwhTotal = savedKwhPerM * verifyMonths;
double deltaUnitReagent = baseUnitReagent - actualUnitReagent;
double savedReagentKgPerM = Math.max(0, deltaUnitReagent / 1000.0 * actualMonthlyWater);
BigDecimal pp = new BigDecimal(powerPrice);
BigDecimal rp = new BigDecimal(reagentPrice);
BigDecimal savedPowerCost = BigDecimal.valueOf(savedKwhTotal).multiply(pp)
.setScale(2, RoundingMode.HALF_UP);
BigDecimal savedReagentCost = BigDecimal.valueOf(savedReagentKgPerM * verifyMonths).multiply(rp)
.setScale(2, RoundingMode.HALF_UP);
BigDecimal savedTotal = savedPowerCost.add(savedReagentCost);
p.setSavedKwhPerMonth(Math.round(savedKwhPerM * 100.0) / 100.0);
p.setSavedKwhTotal(Math.round(savedKwhTotal * 100.0) / 100.0);
p.setSavedReagentKgPerMonth(Math.round(savedReagentKgPerM * 100.0) / 100.0);
p.setSavedPowerCost(savedPowerCost);
p.setSavedReagentCost(savedReagentCost);
p.setSavedTotalCost(savedTotal);
BigDecimal invest = new BigDecimal(investCost);
if (savedTotal.compareTo(BigDecimal.ZERO) > 0 && verifyMonths > 0) {
BigDecimal monthlyRate = savedTotal.divide(BigDecimal.valueOf(verifyMonths), 4, RoundingMode.HALF_UP);
if (monthlyRate.compareTo(BigDecimal.ZERO) > 0) {
double pb = invest.divide(monthlyRate, 2, RoundingMode.HALF_UP).doubleValue();
p.setPaybackMonths(pb);
}
}
savingRepo.save(p);
}
}