diff --git a/sql/energy/energy_alter_frontend.sql b/sql/energy/energy_alter_frontend.sql
new file mode 100644
index 0000000..84f8bce
--- /dev/null
+++ b/sql/energy/energy_alter_frontend.sql
@@ -0,0 +1,3 @@
+-- energy_alter_frontend.sql
+ALTER TABLE energy_bill ADD COLUMN cooperation_type TINYINT DEFAULT NULL COMMENT '合作模式(1=预充值 2=月结算)' AFTER station_name;
+ALTER TABLE energy_station_config ADD COLUMN auto_match TINYINT DEFAULT 1 COMMENT '自动匹配开关(0=关闭 1=开启)' AFTER cooperation_type;
diff --git a/yudao-module-energy/pom.xml b/yudao-module-energy/pom.xml
new file mode 100644
index 0000000..0954d4f
--- /dev/null
+++ b/yudao-module-energy/pom.xml
@@ -0,0 +1,23 @@
+
+
+
+ cn.iocoder.cloud
+ yudao
+ ${revision}
+
+ 4.0.0
+ yudao-module-energy
+ pom
+
+ ${project.artifactId}
+ 能源账单模块,包含加氢记录、费用明细、账单管理、账户管理等功能
+ https://github.com/YunaiV/yudao-cloud
+
+
+ yudao-module-energy-api
+ yudao-module-energy-server
+
+
+
diff --git a/yudao-module-energy/yudao-module-energy-api/pom.xml b/yudao-module-energy/yudao-module-energy-api/pom.xml
new file mode 100644
index 0000000..c0cb88b
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/pom.xml
@@ -0,0 +1,39 @@
+
+
+
+ yudao-module-energy
+ cn.iocoder.cloud
+ ${revision}
+
+ 4.0.0
+ yudao-module-energy-api
+ jar
+
+ ${project.artifactId}
+ 能源账单 API,定义枚举、错误码等
+ https://github.com/YunaiV/yudao-cloud
+
+
+
+ cn.iocoder.cloud
+ yudao-common
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-web
+ provided
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+ true
+
+
+
+
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/AccountStatusEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/AccountStatusEnum.java
new file mode 100644
index 0000000..c118053
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/AccountStatusEnum.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum AccountStatusEnum {
+ NORMAL(0, "正常"),
+ WARNING(1, "预警"),
+ OVERDUE(2, "欠费");
+
+ private final Integer status;
+ private final String name;
+
+ public static AccountStatusEnum valueOf(Integer status) {
+ return Arrays.stream(values())
+ .filter(item -> item.getStatus().equals(status))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/AdjustmentTypeEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/AdjustmentTypeEnum.java
new file mode 100644
index 0000000..207f4e8
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/AdjustmentTypeEnum.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum AdjustmentTypeEnum {
+ INCREASE(0, "调增"),
+ DECREASE(1, "调减");
+
+ private final Integer type;
+ private final String name;
+
+ public static AdjustmentTypeEnum valueOf(Integer type) {
+ return Arrays.stream(values())
+ .filter(item -> item.getType().equals(type))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/AuditStatusEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/AuditStatusEnum.java
new file mode 100644
index 0000000..9501e24
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/AuditStatusEnum.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum AuditStatusEnum {
+ PENDING(0, "待审核"),
+ APPROVED(1, "已通过"),
+ REJECTED(2, "已驳回");
+
+ private final Integer status;
+ private final String name;
+
+ public static AuditStatusEnum valueOf(Integer status) {
+ return Arrays.stream(values())
+ .filter(item -> item.getStatus().equals(status))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BillAuditStatusEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BillAuditStatusEnum.java
new file mode 100644
index 0000000..0cd4360
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BillAuditStatusEnum.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum BillAuditStatusEnum {
+ PENDING(0, "待审核"),
+ APPROVED(1, "已通过"),
+ REJECTED(2, "已驳回");
+
+ private final Integer status;
+ private final String name;
+
+ public static BillAuditStatusEnum valueOf(Integer status) {
+ return Arrays.stream(values())
+ .filter(item -> item.getStatus().equals(status))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BillStatusEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BillStatusEnum.java
new file mode 100644
index 0000000..e22cf71
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BillStatusEnum.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum BillStatusEnum {
+ DRAFT(0, "草稿"),
+ GENERATED(1, "已生成"),
+ VOID(2, "已作废");
+
+ private final Integer status;
+ private final String name;
+
+ public static BillStatusEnum valueOf(Integer status) {
+ return Arrays.stream(values())
+ .filter(item -> item.getStatus().equals(status))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BillSubmitStatusEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BillSubmitStatusEnum.java
new file mode 100644
index 0000000..8c42eb0
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BillSubmitStatusEnum.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum BillSubmitStatusEnum {
+ NOT_SUBMITTED(0, "未提交"),
+ SUBMITTED(1, "已提交"),
+ REJECTED(2, "已驳回");
+
+ private final Integer status;
+ private final String name;
+
+ public static BillSubmitStatusEnum valueOf(Integer status) {
+ return Arrays.stream(values())
+ .filter(item -> item.getStatus().equals(status))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BizTypeEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BizTypeEnum.java
new file mode 100644
index 0000000..e4c5d6b
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/BizTypeEnum.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum BizTypeEnum {
+ HYDROGEN_DEDUCTION(0, "加氢扣款"),
+ BILL_SETTLEMENT(1, "账单结算"),
+ MANUAL_ADJUST(2, "手动调整"),
+ RECHARGE(3, "充值"),
+ REMIT(4, "汇款");
+
+ private final Integer type;
+ private final String name;
+
+ public static BizTypeEnum valueOf(Integer type) {
+ return Arrays.stream(values())
+ .filter(item -> item.getType().equals(type))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/CooperationTypeEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/CooperationTypeEnum.java
new file mode 100644
index 0000000..d1b035f
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/CooperationTypeEnum.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum CooperationTypeEnum {
+ COOPERATED(0, "合作"),
+ NON_COOPERATED(1, "非合作");
+
+ private final Integer type;
+ private final String name;
+
+ public static CooperationTypeEnum valueOf(Integer type) {
+ return Arrays.stream(values())
+ .filter(item -> item.getType().equals(type))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/CostBearerEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/CostBearerEnum.java
new file mode 100644
index 0000000..a5ef08e
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/CostBearerEnum.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum CostBearerEnum {
+ CUSTOMER(0, "客户承担"),
+ COMPANY(1, "羚牛承担"),
+ SELF_SETTLE(2, "自行结算");
+
+ private final Integer type;
+ private final String name;
+
+ public static CostBearerEnum valueOf(Integer type) {
+ return Arrays.stream(values())
+ .filter(item -> item.getType().equals(type))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/DeductionStatusEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/DeductionStatusEnum.java
new file mode 100644
index 0000000..c000404
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/DeductionStatusEnum.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum DeductionStatusEnum {
+ NOT_DEDUCTED(0, "未扣款"),
+ DEDUCTED(1, "已扣款");
+
+ private final Integer status;
+ private final String name;
+
+ public static DeductionStatusEnum valueOf(Integer status) {
+ return Arrays.stream(values())
+ .filter(item -> item.getStatus().equals(status))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/EnergyTypeEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/EnergyTypeEnum.java
new file mode 100644
index 0000000..f51d8d9
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/EnergyTypeEnum.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum EnergyTypeEnum {
+ HYDROGEN(0, "氢费"),
+ ELECTRIC(1, "电费"),
+ ETC(2, "ETC");
+
+ private final Integer type;
+ private final String name;
+
+ public static EnergyTypeEnum valueOf(Integer type) {
+ return Arrays.stream(values())
+ .filter(item -> item.getType().equals(type))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/ErrorCodeConstants.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/ErrorCodeConstants.java
new file mode 100644
index 0000000..cd62d83
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/ErrorCodeConstants.java
@@ -0,0 +1,32 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import cn.iocoder.yudao.framework.common.exception.ErrorCode;
+
+public interface ErrorCodeConstants {
+ // ========== 加氢记录 1-050-000-000 ==========
+ ErrorCode HYDROGEN_RECORD_NOT_EXISTS = new ErrorCode(1_050_000_000, "加氢记录不存在");
+ ErrorCode HYDROGEN_RECORD_IMPORT_EMPTY = new ErrorCode(1_050_000_001, "导入数据为空");
+ ErrorCode HYDROGEN_RECORD_DUPLICATE = new ErrorCode(1_050_000_002, "存在重复导入记录");
+
+ // ========== 加氢明细 1-050-001-000 ==========
+ ErrorCode HYDROGEN_DETAIL_NOT_EXISTS = new ErrorCode(1_050_001_000, "加氢明细不存在");
+ ErrorCode HYDROGEN_DETAIL_ALREADY_AUDITED = new ErrorCode(1_050_001_001, "明细已审核,不可重复审核");
+
+ // ========== 能源账单 1-050-002-000 ==========
+ ErrorCode ENERGY_BILL_NOT_EXISTS = new ErrorCode(1_050_002_000, "能源账单不存在");
+ ErrorCode ENERGY_BILL_NOT_DRAFT = new ErrorCode(1_050_002_001, "账单非草稿状态,不可删除");
+ ErrorCode ENERGY_BILL_ALREADY_AUDITED = new ErrorCode(1_050_002_002, "账单已审核");
+ ErrorCode ENERGY_BILL_NO_DETAILS = new ErrorCode(1_050_002_003, "无可生成账单的明细");
+
+ // ========== 能源账户 1-050-003-000 ==========
+ ErrorCode ENERGY_ACCOUNT_NOT_EXISTS = new ErrorCode(1_050_003_000, "能源账户不存在");
+ ErrorCode ENERGY_ACCOUNT_VERSION_CONFLICT = new ErrorCode(1_050_003_001, "账户余额更新冲突,请重试");
+
+ // ========== 价格管理 1-050-004-000 ==========
+ ErrorCode STATION_PRICE_NOT_EXISTS = new ErrorCode(1_050_004_000, "站点价格不存在");
+ ErrorCode STATION_PRICE_DUPLICATE = new ErrorCode(1_050_004_001, "同一站点同一客户同一生效日期已存在价格");
+
+ // ========== 站点配置 1-050-005-000 ==========
+ ErrorCode STATION_CONFIG_NOT_EXISTS = new ErrorCode(1_050_005_000, "站点配置不存在");
+ ErrorCode STATION_CONFIG_DUPLICATE = new ErrorCode(1_050_005_001, "该站点配置已存在");
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/FlowTypeEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/FlowTypeEnum.java
new file mode 100644
index 0000000..f0195ac
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/FlowTypeEnum.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum FlowTypeEnum {
+ RECHARGE(0, "充值"),
+ DEDUCTION(1, "扣款"),
+ REVERSAL(2, "冲正"),
+ REMIT(3, "汇款"),
+ REFUND(4, "退款");
+
+ private final Integer type;
+ private final String name;
+
+ public static FlowTypeEnum valueOf(Integer type) {
+ return Arrays.stream(values())
+ .filter(item -> item.getType().equals(type))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/MatchStatusEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/MatchStatusEnum.java
new file mode 100644
index 0000000..1e8e3ea
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/MatchStatusEnum.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum MatchStatusEnum {
+ UNMATCHED(0, "未匹配"),
+ MATCHED(1, "已匹配"),
+ UNMATCHABLE(2, "无法匹配");
+
+ private final Integer status;
+ private final String name;
+
+ public static MatchStatusEnum valueOf(Integer status) {
+ return Arrays.stream(values())
+ .filter(item -> item.getStatus().equals(status))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/PayMethodEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/PayMethodEnum.java
new file mode 100644
index 0000000..186ff3f
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/PayMethodEnum.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum PayMethodEnum {
+ PREPAID(0, "预充值"),
+ MONTHLY(1, "月结算");
+
+ private final Integer type;
+ private final String name;
+
+ public static PayMethodEnum valueOf(Integer type) {
+ return Arrays.stream(values())
+ .filter(item -> item.getType().equals(type))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/PaymentStatusEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/PaymentStatusEnum.java
new file mode 100644
index 0000000..0ad3436
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/PaymentStatusEnum.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum PaymentStatusEnum {
+ UNPAID(0, "未支付"),
+ PARTIAL(1, "部分支付"),
+ PAID(2, "已支付");
+
+ private final Integer status;
+ private final String name;
+
+ public static PaymentStatusEnum valueOf(Integer status) {
+ return Arrays.stream(values())
+ .filter(item -> item.getStatus().equals(status))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/SettlementStatusEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/SettlementStatusEnum.java
new file mode 100644
index 0000000..c630e50
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/SettlementStatusEnum.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum SettlementStatusEnum {
+ NOT_SETTLED(0, "未结算"),
+ SETTLED(1, "已结算");
+
+ private final Integer status;
+ private final String name;
+
+ public static SettlementStatusEnum valueOf(Integer status) {
+ return Arrays.stream(values())
+ .filter(item -> item.getStatus().equals(status))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/SourceTypeEnum.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/SourceTypeEnum.java
new file mode 100644
index 0000000..bef2dba
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/enums/SourceTypeEnum.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.energy.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import java.util.Arrays;
+
+@Getter
+@AllArgsConstructor
+public enum SourceTypeEnum {
+ EXCEL(0, "Excel导入"),
+ WEB(1, "Web录入"),
+ API(2, "API对接"),
+ OCR(3, "OCR识别");
+
+ private final Integer type;
+ private final String name;
+
+ public static SourceTypeEnum valueOf(Integer type) {
+ return Arrays.stream(values())
+ .filter(item -> item.getType().equals(type))
+ .findFirst().orElse(null);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/package-info.java b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/package-info.java
new file mode 100644
index 0000000..bdae697
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-api/src/main/java/cn/iocoder/yudao/module/energy/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 能源账单 API 模块,定义枚举、错误码等
+ */
+package cn.iocoder.yudao.module.energy;
diff --git a/yudao-module-energy/yudao-module-energy-server/pom.xml b/yudao-module-energy/yudao-module-energy-server/pom.xml
new file mode 100644
index 0000000..45ba784
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/pom.xml
@@ -0,0 +1,132 @@
+
+
+
+ yudao-module-energy
+ cn.iocoder.cloud
+ ${revision}
+
+ 4.0.0
+ yudao-module-energy-server
+ jar
+
+ ${project.artifactId}
+ 能源账单业务实现
+ https://github.com/YunaiV/yudao-cloud
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-env
+
+
+
+
+ cn.iocoder.cloud
+ yudao-module-energy-api
+ ${revision}
+
+
+
+
+ cn.iocoder.cloud
+ yudao-module-system-api
+ ${revision}
+
+
+
+
+ cn.iocoder.cloud
+ yudao-module-infra-api
+ ${revision}
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-biz-tenant
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-security
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-mybatis
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-rpc
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-job
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-mq
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-test
+ test
+
+
+
+
+ cn.iocoder.cloud
+ yudao-spring-boot-starter-excel
+
+
+
+
+
+ ${project.artifactId}
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring.boot.version}
+
+
+
+ repackage
+
+
+
+
+
+
+
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/EnergyAccountController.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/EnergyAccountController.java
new file mode 100644
index 0000000..313ec20
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/EnergyAccountController.java
@@ -0,0 +1,89 @@
+package cn.iocoder.yudao.module.energy.controller.admin.account;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.energy.controller.admin.account.vo.*;
+import cn.iocoder.yudao.module.energy.convert.account.EnergyAccountConvert;
+import cn.iocoder.yudao.module.energy.dal.dataobject.account.EnergyAccountDO;
+import cn.iocoder.yudao.module.energy.dal.dataobject.account.EnergyAccountFlowDO;
+import cn.iocoder.yudao.module.energy.dal.dataobject.account.EnergyProjectAccountDO;
+import cn.iocoder.yudao.module.energy.service.account.EnergyAccountService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 能源账户管理")
+@RestController
+@RequestMapping("/energy/account")
+@Validated
+public class EnergyAccountController {
+
+ @Resource
+ private EnergyAccountService accountService;
+
+ @GetMapping("/page")
+ @Operation(summary = "获得账户分页")
+ @PreAuthorize("@ss.hasPermission('energy:account:query')")
+ public CommonResult> getAccountPage(@Valid EnergyAccountPageReqVO pageReqVO) {
+ PageResult pageResult = accountService.getAccountPage(pageReqVO);
+ return success(EnergyAccountConvert.INSTANCE.convertPage(pageResult));
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得账户详情")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('energy:account:query')")
+ public CommonResult getAccount(@RequestParam("id") Long id) {
+ EnergyAccountDO account = accountService.getAccount(id);
+ return success(EnergyAccountConvert.INSTANCE.convert(account));
+ }
+
+ @PostMapping("/recharge")
+ @Operation(summary = "账户充值")
+ @PreAuthorize("@ss.hasPermission('energy:account:recharge')")
+ public CommonResult recharge(@RequestParam("customerId") Long customerId,
+ @RequestParam("amount") BigDecimal amount,
+ @RequestParam(value = "remark", required = false) String remark) {
+ accountService.recharge(customerId, amount, null, null, remark);
+ return success(true);
+ }
+
+ @PutMapping("/update-threshold")
+ @Operation(summary = "更新预警阈值")
+ @PreAuthorize("@ss.hasPermission('energy:account:update')")
+ public CommonResult updateThreshold(@RequestParam("id") Long id,
+ @RequestParam("threshold") BigDecimal threshold) {
+ accountService.updateThreshold(id, threshold);
+ return success(true);
+ }
+
+ // ===== 项目账户 =====
+
+ @GetMapping("/project/list")
+ @Operation(summary = "获得项目账户列表")
+ @Parameter(name = "accountId", description = "总账户ID", required = true)
+ @PreAuthorize("@ss.hasPermission('energy:account:query')")
+ public CommonResult> getProjectAccountList(@RequestParam("accountId") Long accountId) {
+ List list = accountService.getProjectAccountsByAccountId(accountId);
+ return success(cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList(list, EnergyAccountConvert.INSTANCE::convert));
+ }
+
+ // ===== 流水查询 =====
+
+ @GetMapping("/flow/page")
+ @Operation(summary = "获得流水分页")
+ @PreAuthorize("@ss.hasPermission('energy:account:query')")
+ public CommonResult> getFlowPage(@Valid EnergyAccountFlowPageReqVO pageReqVO) {
+ return success(accountService.getFlowPage(pageReqVO));
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountFlowPageReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountFlowPageReqVO.java
new file mode 100644
index 0000000..62fdee5
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountFlowPageReqVO.java
@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.energy.controller.admin.account.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 账户流水分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class EnergyAccountFlowPageReqVO extends PageParam {
+ @Schema(description = "总账户ID")
+ private Long accountId;
+ @Schema(description = "项目账户ID")
+ private Long projectAccountId;
+ @Schema(description = "流水类型")
+ private Integer flowType;
+ @Schema(description = "业务类型")
+ private Integer bizType;
+ @Schema(description = "开始时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountPageReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountPageReqVO.java
new file mode 100644
index 0000000..8cca160
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountPageReqVO.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.energy.controller.admin.account.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - 能源账户分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class EnergyAccountPageReqVO extends PageParam {
+ @Schema(description = "客户ID")
+ private Long customerId;
+ @Schema(description = "账户状态")
+ private Integer accountStatus;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountRespVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountRespVO.java
new file mode 100644
index 0000000..485285f
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountRespVO.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.energy.controller.admin.account.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 能源账户 Response VO")
+@Data
+public class EnergyAccountRespVO {
+ @Schema(description = "主键ID")
+ private Long id;
+ @Schema(description = "客户ID")
+ private Long customerId;
+ @Schema(description = "当前余额")
+ private BigDecimal balance;
+ @Schema(description = "初始余额")
+ private BigDecimal initBalance;
+ @Schema(description = "累计充值")
+ private BigDecimal accumulatedRecharge;
+ @Schema(description = "累计氢费")
+ private BigDecimal accumulatedHydrogen;
+ @Schema(description = "累计电费")
+ private BigDecimal accumulatedElectric;
+ @Schema(description = "累计消费")
+ private BigDecimal accumulatedConsume;
+ @Schema(description = "提醒阈值")
+ private BigDecimal reminderThreshold;
+ @Schema(description = "账户状态")
+ private Integer accountStatus;
+ @Schema(description = "最后充值日期")
+ private LocalDate lastRechargeDate;
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountSaveReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountSaveReqVO.java
new file mode 100644
index 0000000..1dc93b2
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyAccountSaveReqVO.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.energy.controller.admin.account.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 能源账户创建 Request VO")
+@Data
+public class EnergyAccountSaveReqVO {
+ @Schema(description = "客户ID", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "客户不能为空")
+ private Long customerId;
+ @Schema(description = "初始余额")
+ private BigDecimal initBalance;
+ @Schema(description = "提醒阈值")
+ private BigDecimal reminderThreshold;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyProjectAccountRespVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyProjectAccountRespVO.java
new file mode 100644
index 0000000..7a6b994
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/account/vo/EnergyProjectAccountRespVO.java
@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.module.energy.controller.admin.account.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 项目账户 Response VO")
+@Data
+public class EnergyProjectAccountRespVO {
+ @Schema(description = "主键ID")
+ private Long id;
+ @Schema(description = "关联总账户ID")
+ private Long accountId;
+ @Schema(description = "合同ID")
+ private Long contractId;
+ @Schema(description = "项目名称")
+ private String projectName;
+ @Schema(description = "项目余额")
+ private BigDecimal projectBalance;
+ @Schema(description = "累计划账金额")
+ private BigDecimal projectRemitAmount;
+ @Schema(description = "累计氢费")
+ private BigDecimal projectHydrogenAmount;
+ @Schema(description = "累计电费")
+ private BigDecimal projectElectricAmount;
+ @Schema(description = "累计消费")
+ private BigDecimal projectConsumeAmount;
+ @Schema(description = "提醒阈值")
+ private BigDecimal reminderThreshold;
+ @Schema(description = "账户状态")
+ private Integer accountStatus;
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/EnergyBillController.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/EnergyBillController.java
new file mode 100644
index 0000000..279224e
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/EnergyBillController.java
@@ -0,0 +1,104 @@
+package cn.iocoder.yudao.module.energy.controller.admin.bill;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.energy.controller.admin.bill.vo.*;
+import cn.iocoder.yudao.module.energy.convert.bill.EnergyBillConvert;
+import cn.iocoder.yudao.module.energy.dal.dataobject.bill.EnergyBillDO;
+import cn.iocoder.yudao.module.energy.service.bill.EnergyBillService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 能源账单管理")
+@RestController
+@RequestMapping("/energy/bill")
+@Validated
+public class EnergyBillController {
+
+ @Resource
+ private EnergyBillService billService;
+
+ @GetMapping("/page")
+ @Operation(summary = "获得账单分页")
+ @PreAuthorize("@ss.hasPermission('energy:bill:query')")
+ public CommonResult> getBillPage(@Valid EnergyBillPageReqVO pageReqVO) {
+ PageResult pageResult = billService.getBillPage(pageReqVO);
+ return success(EnergyBillConvert.INSTANCE.convertPage(pageResult));
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得账单详情")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('energy:bill:query')")
+ public CommonResult getBill(@RequestParam("id") Long id) {
+ EnergyBillDO bill = billService.getBill(id);
+ return success(EnergyBillConvert.INSTANCE.convert(bill));
+ }
+
+ @PostMapping("/generate")
+ @Operation(summary = "生成账单")
+ @PreAuthorize("@ss.hasPermission('energy:bill:create')")
+ public CommonResult generateBill(@Valid @RequestBody EnergyBillGenerateReqVO reqVO) {
+ return success(billService.generateBill(reqVO));
+ }
+
+ @PostMapping("/batch-generate")
+ @Operation(summary = "批量生成账单")
+ @PreAuthorize("@ss.hasPermission('energy:bill:create')")
+ public CommonResult> batchGenerateBills(@Valid @RequestBody List reqVOs) {
+ return success(billService.batchGenerateBills(reqVOs));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新账单")
+ @PreAuthorize("@ss.hasPermission('energy:bill:update')")
+ public CommonResult updateBill(@Valid @RequestBody EnergyBillSaveReqVO reqVO) {
+ billService.updateBill(reqVO);
+ return success(true);
+ }
+
+ @PostMapping("/audit")
+ @Operation(summary = "审核账单")
+ @PreAuthorize("@ss.hasPermission('energy:bill:audit')")
+ public CommonResult auditBill(@RequestParam("id") Long id,
+ @RequestParam("approved") Boolean approved,
+ @RequestParam(value = "remark", required = false) String remark) {
+ billService.auditBill(id, approved, remark);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除账单")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('energy:bill:delete')")
+ public CommonResult deleteBill(@RequestParam("id") Long id) {
+ billService.deleteBill(id);
+ return success(true);
+ }
+
+ @PostMapping("/adjustment/create")
+ @Operation(summary = "创建调整行")
+ @PreAuthorize("@ss.hasPermission('energy:bill:update')")
+ public CommonResult createAdjustment(@Valid @RequestBody EnergyBillAdjustmentSaveReqVO reqVO) {
+ return success(billService.createAdjustment(reqVO));
+ }
+
+ @DeleteMapping("/adjustment/delete")
+ @Operation(summary = "删除调整行")
+ @Parameter(name = "id", description = "调整行ID", required = true)
+ @PreAuthorize("@ss.hasPermission('energy:bill:update')")
+ public CommonResult deleteAdjustment(@RequestParam("id") Long id) {
+ billService.deleteAdjustment(id);
+ return success(true);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillAdjustmentSaveReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillAdjustmentSaveReqVO.java
new file mode 100644
index 0000000..fbe7e45
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillAdjustmentSaveReqVO.java
@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.energy.controller.admin.bill.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 账单调整行创建 Request VO")
+@Data
+public class EnergyBillAdjustmentSaveReqVO {
+ @Schema(description = "账单ID", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "账单不能为空")
+ private Long billId;
+ @Schema(description = "关联明细ID")
+ private Long detailId;
+ @Schema(description = "调整类型", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "调整类型不能为空")
+ private Integer adjustmentType;
+ @Schema(description = "调整金额", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "调整金额不能为空")
+ private BigDecimal amount;
+ @Schema(description = "调整原因")
+ private String reason;
+ @Schema(description = "附件URL")
+ private String attachmentUrls;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillGenerateReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillGenerateReqVO.java
new file mode 100644
index 0000000..f4d2ec4
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillGenerateReqVO.java
@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.energy.controller.admin.bill.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import java.time.LocalDate;
+
+@Schema(description = "管理后台 - 能源账单生成 Request VO")
+@Data
+public class EnergyBillGenerateReqVO {
+ @Schema(description = "能源类型", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "能源类型不能为空")
+ private Integer energyType;
+ @Schema(description = "客户ID", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "客户不能为空")
+ private Long customerId;
+ @Schema(description = "合同ID", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "合同不能为空")
+ private Long contractId;
+ @Schema(description = "加氢站ID")
+ private Long stationId;
+ @Schema(description = "账单周期开始", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "账单周期开始不能为空")
+ private LocalDate billPeriodStart;
+ @Schema(description = "账单周期结束", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "账单周期结束不能为空")
+ private LocalDate billPeriodEnd;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillPageReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillPageReqVO.java
new file mode 100644
index 0000000..b9581ae
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillPageReqVO.java
@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.energy.controller.admin.bill.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDate;
+
+@Schema(description = "管理后台 - 能源账单分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class EnergyBillPageReqVO extends PageParam {
+ @Schema(description = "能源类型")
+ private Integer energyType;
+ @Schema(description = "客户ID")
+ private Long customerId;
+ @Schema(description = "加氢站ID")
+ private Long stationId;
+ @Schema(description = "账单状态")
+ private Integer status;
+ @Schema(description = "审核状态")
+ private Integer auditStatus;
+ @Schema(description = "账单周期")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate[] billPeriod;
+ @Schema(description = "合作模式")
+ private Integer cooperationType;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillRespVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillRespVO.java
new file mode 100644
index 0000000..733ce77
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillRespVO.java
@@ -0,0 +1,64 @@
+package cn.iocoder.yudao.module.energy.controller.admin.bill.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 能源账单 Response VO")
+@Data
+public class EnergyBillRespVO {
+ @Schema(description = "主键ID")
+ private Long id;
+ @Schema(description = "账单编号")
+ private String billCode;
+ @Schema(description = "能源类型")
+ private Integer energyType;
+ @Schema(description = "客户ID")
+ private Long customerId;
+ @Schema(description = "客户名称")
+ private String customerName;
+ @Schema(description = "合同ID")
+ private Long contractId;
+ @Schema(description = "加氢站ID")
+ private Long stationId;
+ @Schema(description = "站点名称")
+ private String stationName;
+ @Schema(description = "合作模式(1=预充值 2=月结算)")
+ private Integer cooperationType;
+ @Schema(description = "账单周期开始")
+ private LocalDate billPeriodStart;
+ @Schema(description = "账单周期结束")
+ private LocalDate billPeriodEnd;
+ @Schema(description = "应收总额")
+ private BigDecimal receivableAmount;
+ @Schema(description = "实收总额")
+ private BigDecimal actualAmount;
+ @Schema(description = "调整总额")
+ private BigDecimal adjustmentAmount;
+ @Schema(description = "已收金额")
+ private BigDecimal paidAmount;
+ @Schema(description = "总加氢量")
+ private BigDecimal totalQuantity;
+ @Schema(description = "明细条数")
+ private Integer detailCount;
+ @Schema(description = "账单状态")
+ private Integer status;
+ @Schema(description = "审核状态")
+ private Integer auditStatus;
+ @Schema(description = "提交状态")
+ private Integer submitStatus;
+ @Schema(description = "支付状态")
+ private Integer paymentStatus;
+ @Schema(description = "审核人ID")
+ private Long auditorId;
+ @Schema(description = "审核时间")
+ private LocalDateTime auditTime;
+ @Schema(description = "审核备注")
+ private String auditRemark;
+ @Schema(description = "生成时间")
+ private LocalDateTime generateTime;
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillSaveReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillSaveReqVO.java
new file mode 100644
index 0000000..42c3084
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/bill/vo/EnergyBillSaveReqVO.java
@@ -0,0 +1,15 @@
+package cn.iocoder.yudao.module.energy.controller.admin.bill.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 能源账单更新 Request VO")
+@Data
+public class EnergyBillSaveReqVO {
+ @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "账单ID不能为空")
+ private Long id;
+ @Schema(description = "审核备注")
+ private String auditRemark;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/EnergyStationConfigController.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/EnergyStationConfigController.java
new file mode 100644
index 0000000..97ec796
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/EnergyStationConfigController.java
@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.module.energy.controller.admin.config;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigPageReqVO;
+import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigRespVO;
+import cn.iocoder.yudao.module.energy.controller.admin.config.vo.EnergyStationConfigSaveReqVO;
+import cn.iocoder.yudao.module.energy.convert.config.EnergyStationConfigConvert;
+import cn.iocoder.yudao.module.energy.dal.dataobject.config.EnergyStationConfigDO;
+import cn.iocoder.yudao.module.energy.service.config.EnergyStationConfigService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 加氢站配置")
+@RestController
+@RequestMapping("/energy/station-config")
+@Validated
+public class EnergyStationConfigController {
+
+ @Resource
+ private EnergyStationConfigService stationConfigService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建站点配置")
+ @PreAuthorize("@ss.hasPermission('energy:station-config:create')")
+ public CommonResult createConfig(@Valid @RequestBody EnergyStationConfigSaveReqVO createReqVO) {
+ return success(stationConfigService.createConfig(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新站点配置")
+ @PreAuthorize("@ss.hasPermission('energy:station-config:update')")
+ public CommonResult updateConfig(@Valid @RequestBody EnergyStationConfigSaveReqVO updateReqVO) {
+ stationConfigService.updateConfig(updateReqVO);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得站点配置")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('energy:station-config:query')")
+ public CommonResult getConfig(@RequestParam("id") Long id) {
+ EnergyStationConfigDO config = stationConfigService.getConfig(id);
+ return success(EnergyStationConfigConvert.INSTANCE.convert(config));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得站点配置分页")
+ @PreAuthorize("@ss.hasPermission('energy:station-config:query')")
+ public CommonResult> getConfigPage(@Valid EnergyStationConfigPageReqVO pageReqVO) {
+ PageResult pageResult = stationConfigService.getConfigPage(pageReqVO);
+ return success(EnergyStationConfigConvert.INSTANCE.convertPage(pageResult));
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigPageReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigPageReqVO.java
new file mode 100644
index 0000000..faa556c
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigPageReqVO.java
@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.energy.controller.admin.config.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - 加氢站配置分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class EnergyStationConfigPageReqVO extends PageParam {
+ @Schema(description = "加氢站ID")
+ private Long stationId;
+ @Schema(description = "是否自动扣款")
+ private Boolean autoDeduct;
+ @Schema(description = "合作类型")
+ private Integer cooperationType;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigRespVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigRespVO.java
new file mode 100644
index 0000000..51fc640
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigRespVO.java
@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.energy.controller.admin.config.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 加氢站配置 Response VO")
+@Data
+public class EnergyStationConfigRespVO {
+ @Schema(description = "主键ID")
+ private Long id;
+ @Schema(description = "加氢站ID")
+ private Long stationId;
+ @Schema(description = "是否自动扣款")
+ private Boolean autoDeduct;
+ @Schema(description = "合作类型")
+ private Integer cooperationType;
+ @Schema(description = "站点名称")
+ private String stationName;
+ @Schema(description = "自动匹配开关")
+ private Boolean autoMatch;
+ @Schema(description = "备注")
+ private String remark;
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigSaveReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigSaveReqVO.java
new file mode 100644
index 0000000..aaa4d13
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/config/vo/EnergyStationConfigSaveReqVO.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.energy.controller.admin.config.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 加氢站配置创建/更新 Request VO")
+@Data
+public class EnergyStationConfigSaveReqVO {
+ @Schema(description = "主键ID")
+ private Long id;
+ @Schema(description = "加氢站ID", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "加氢站不能为空")
+ private Long stationId;
+ @Schema(description = "是否自动扣款", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "是否自动扣款不能为空")
+ private Boolean autoDeduct;
+ @Schema(description = "合作类型")
+ private Integer cooperationType;
+ @Schema(description = "自动匹配开关")
+ private Boolean autoMatch;
+ @Schema(description = "备注")
+ private String remark;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/HydrogenDetailController.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/HydrogenDetailController.java
new file mode 100644
index 0000000..8d1ef66
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/HydrogenDetailController.java
@@ -0,0 +1,75 @@
+package cn.iocoder.yudao.module.energy.controller.admin.detail;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.energy.controller.admin.detail.vo.*;
+import cn.iocoder.yudao.module.energy.convert.detail.HydrogenDetailConvert;
+import cn.iocoder.yudao.module.energy.dal.dataobject.detail.EnergyHydrogenDetailDO;
+import cn.iocoder.yudao.module.energy.service.detail.HydrogenDetailService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 加氢明细管理")
+@RestController
+@RequestMapping("/energy/hydrogen-detail")
+@Validated
+public class HydrogenDetailController {
+
+ @Resource
+ private HydrogenDetailService hydrogenDetailService;
+
+ @GetMapping("/page")
+ @Operation(summary = "获得明细分页")
+ @PreAuthorize("@ss.hasPermission('energy:hydrogen-detail:query')")
+ public CommonResult> getDetailPage(@Valid HydrogenDetailPageReqVO pageReqVO) {
+ PageResult pageResult = hydrogenDetailService.getDetailPage(pageReqVO);
+ return success(HydrogenDetailConvert.INSTANCE.convertPage(pageResult));
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得明细详情")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('energy:hydrogen-detail:query')")
+ public CommonResult getDetail(@RequestParam("id") Long id) {
+ EnergyHydrogenDetailDO detail = hydrogenDetailService.getDetail(id);
+ return success(HydrogenDetailConvert.INSTANCE.convert(detail));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新明细")
+ @PreAuthorize("@ss.hasPermission('energy:hydrogen-detail:update')")
+ public CommonResult updateDetail(@Valid @RequestBody HydrogenDetailSaveReqVO reqVO) {
+ hydrogenDetailService.updateDetail(reqVO);
+ return success(true);
+ }
+
+ @PostMapping("/audit")
+ @Operation(summary = "审核明细")
+ @PreAuthorize("@ss.hasPermission('energy:hydrogen-detail:audit')")
+ public CommonResult auditDetail(@RequestParam("id") Long id,
+ @RequestParam("approved") Boolean approved,
+ @RequestParam(value = "remark", required = false) String remark) {
+ hydrogenDetailService.audit(id, approved, remark);
+ return success(true);
+ }
+
+ @PostMapping("/batch-audit")
+ @Operation(summary = "批量审核明细")
+ @PreAuthorize("@ss.hasPermission('energy:hydrogen-detail:audit')")
+ public CommonResult batchAuditDetail(@RequestParam("ids") List ids,
+ @RequestParam("approved") Boolean approved,
+ @RequestParam(value = "remark", required = false) String remark) {
+ hydrogenDetailService.batchAudit(ids, approved, remark);
+ return success(true);
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/vo/HydrogenDetailPageReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/vo/HydrogenDetailPageReqVO.java
new file mode 100644
index 0000000..5278d30
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/vo/HydrogenDetailPageReqVO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.energy.controller.admin.detail.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDate;
+
+@Schema(description = "管理后台 - 加氢明细分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class HydrogenDetailPageReqVO extends PageParam {
+ @Schema(description = "加氢站ID")
+ private Long stationId;
+ @Schema(description = "客户ID")
+ private Long customerId;
+ @Schema(description = "车牌号")
+ private String plateNumber;
+ @Schema(description = "审核状态")
+ private Integer auditStatus;
+ @Schema(description = "扣款状态")
+ private Integer deductionStatus;
+ @Schema(description = "结算状态")
+ private Integer settlementStatus;
+ @Schema(description = "账单ID")
+ private Long billId;
+ @Schema(description = "加氢日期范围")
+ @DateTimeFormat(pattern = "yyyy-MM-dd")
+ private LocalDate[] hydrogenDate;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/vo/HydrogenDetailRespVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/vo/HydrogenDetailRespVO.java
new file mode 100644
index 0000000..6bdd321
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/vo/HydrogenDetailRespVO.java
@@ -0,0 +1,58 @@
+package cn.iocoder.yudao.module.energy.controller.admin.detail.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 加氢明细 Response VO")
+@Data
+public class HydrogenDetailRespVO {
+ @Schema(description = "主键ID")
+ private Long id;
+ @Schema(description = "关联原始记录ID")
+ private Long recordId;
+ @Schema(description = "加氢站ID")
+ private Long stationId;
+ @Schema(description = "车辆ID")
+ private Long vehicleId;
+ @Schema(description = "车牌号")
+ private String plateNumber;
+ @Schema(description = "加氢日期")
+ private LocalDate hydrogenDate;
+ @Schema(description = "加氢量(KG)")
+ private BigDecimal hydrogenQuantity;
+ @Schema(description = "成本单价")
+ private BigDecimal costPrice;
+ @Schema(description = "成本金额")
+ private BigDecimal costAmount;
+ @Schema(description = "对客单价")
+ private BigDecimal customerPrice;
+ @Schema(description = "对客金额")
+ private BigDecimal customerAmount;
+ @Schema(description = "合同ID")
+ private Long contractId;
+ @Schema(description = "客户ID")
+ private Long customerId;
+ @Schema(description = "项目名称")
+ private String projectName;
+ @Schema(description = "费用承担方")
+ private Integer costBearer;
+ @Schema(description = "支付方式")
+ private Integer payMethod;
+ @Schema(description = "审核状态")
+ private Integer auditStatus;
+ @Schema(description = "审核备注")
+ private String auditRemark;
+ @Schema(description = "扣款状态")
+ private Integer deductionStatus;
+ @Schema(description = "结算状态")
+ private Integer settlementStatus;
+ @Schema(description = "账单ID")
+ private Long billId;
+ @Schema(description = "备注")
+ private String remark;
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/vo/HydrogenDetailSaveReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/vo/HydrogenDetailSaveReqVO.java
new file mode 100644
index 0000000..0e47c44
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/detail/vo/HydrogenDetailSaveReqVO.java
@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.energy.controller.admin.detail.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 加氢明细编辑 Request VO")
+@Data
+public class HydrogenDetailSaveReqVO {
+ @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "明细ID不能为空")
+ private Long id;
+ @Schema(description = "成本单价")
+ private BigDecimal costPrice;
+ @Schema(description = "对客单价")
+ private BigDecimal customerPrice;
+ @Schema(description = "备注")
+ private String remark;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/EnergyStationPriceController.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/EnergyStationPriceController.java
new file mode 100644
index 0000000..fe0ce60
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/EnergyStationPriceController.java
@@ -0,0 +1,82 @@
+package cn.iocoder.yudao.module.energy.controller.admin.price;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.energy.controller.admin.price.vo.*;
+import cn.iocoder.yudao.module.energy.convert.price.EnergyStationPriceConvert;
+import cn.iocoder.yudao.module.energy.dal.dataobject.price.EnergyStationPriceDO;
+import cn.iocoder.yudao.module.energy.service.price.EnergyStationPriceService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDate;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 加氢站价格管理")
+@RestController
+@RequestMapping("/energy/station-price")
+@Validated
+public class EnergyStationPriceController {
+
+ @Resource
+ private EnergyStationPriceService stationPriceService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建价格")
+ @PreAuthorize("@ss.hasPermission('energy:station-price:create')")
+ public CommonResult createPrice(@Valid @RequestBody EnergyStationPriceSaveReqVO createReqVO) {
+ return success(stationPriceService.createPrice(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新价格")
+ @PreAuthorize("@ss.hasPermission('energy:station-price:update')")
+ public CommonResult updatePrice(@Valid @RequestBody EnergyStationPriceSaveReqVO updateReqVO) {
+ stationPriceService.updatePrice(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除价格")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('energy:station-price:delete')")
+ public CommonResult deletePrice(@RequestParam("id") Long id) {
+ stationPriceService.deletePrice(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得价格")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('energy:station-price:query')")
+ public CommonResult getPrice(@RequestParam("id") Long id) {
+ EnergyStationPriceDO price = stationPriceService.getPrice(id);
+ return success(EnergyStationPriceConvert.INSTANCE.convert(price));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得价格分页")
+ @PreAuthorize("@ss.hasPermission('energy:station-price:query')")
+ public CommonResult> getPricePage(@Valid EnergyStationPricePageReqVO pageReqVO) {
+ PageResult pageResult = stationPriceService.getPricePage(pageReqVO);
+ return success(EnergyStationPriceConvert.INSTANCE.convertPage(pageResult));
+ }
+
+ @GetMapping("/get-effective")
+ @Operation(summary = "获取生效价格")
+ @PreAuthorize("@ss.hasPermission('energy:station-price:query')")
+ public CommonResult getEffectivePrice(
+ @RequestParam("stationId") Long stationId,
+ @RequestParam("customerId") Long customerId,
+ @RequestParam("date") LocalDate date) {
+ EnergyStationPriceDO price = stationPriceService.getEffectivePrice(stationId, customerId, date);
+ return success(EnergyStationPriceConvert.INSTANCE.convert(price));
+ }
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/vo/EnergyStationPricePageReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/vo/EnergyStationPricePageReqVO.java
new file mode 100644
index 0000000..37fda96
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/vo/EnergyStationPricePageReqVO.java
@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.energy.controller.admin.price.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "管理后台 - 加氢站价格分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class EnergyStationPricePageReqVO extends PageParam {
+ @Schema(description = "加氢站ID")
+ private Long stationId;
+ @Schema(description = "客户ID")
+ private Long customerId;
+ @Schema(description = "状态")
+ private Integer status;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/vo/EnergyStationPriceRespVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/vo/EnergyStationPriceRespVO.java
new file mode 100644
index 0000000..3d18070
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/vo/EnergyStationPriceRespVO.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.energy.controller.admin.price.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 加氢站价格 Response VO")
+@Data
+public class EnergyStationPriceRespVO {
+ @Schema(description = "主键ID")
+ private Long id;
+ @Schema(description = "加氢站ID")
+ private Long stationId;
+ @Schema(description = "客户ID")
+ private Long customerId;
+ @Schema(description = "成本价")
+ private BigDecimal costPrice;
+ @Schema(description = "对客价")
+ private BigDecimal customerPrice;
+ @Schema(description = "生效日期")
+ private LocalDate effectiveDate;
+ @Schema(description = "失效日期")
+ private LocalDate expiryDate;
+ @Schema(description = "状态")
+ private Integer status;
+ @Schema(description = "创建时间")
+ private LocalDateTime createTime;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/vo/EnergyStationPriceSaveReqVO.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/vo/EnergyStationPriceSaveReqVO.java
new file mode 100644
index 0000000..e782f1a
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/price/vo/EnergyStationPriceSaveReqVO.java
@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.energy.controller.admin.price.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Schema(description = "管理后台 - 加氢站价格创建/更新 Request VO")
+@Data
+public class EnergyStationPriceSaveReqVO {
+ @Schema(description = "主键ID")
+ private Long id;
+ @Schema(description = "加氢站ID", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "加氢站不能为空")
+ private Long stationId;
+ @Schema(description = "客户ID", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "客户不能为空")
+ private Long customerId;
+ @Schema(description = "成本价", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "成本价不能为空")
+ private BigDecimal costPrice;
+ @Schema(description = "对客价", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "对客价不能为空")
+ private BigDecimal customerPrice;
+ @Schema(description = "生效日期", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "生效日期不能为空")
+ private LocalDate effectiveDate;
+ @Schema(description = "失效日期")
+ private LocalDate expiryDate;
+}
diff --git a/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/record/HydrogenRecordController.java b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/record/HydrogenRecordController.java
new file mode 100644
index 0000000..821b870
--- /dev/null
+++ b/yudao-module-energy/yudao-module-energy-server/src/main/java/cn/iocoder/yudao/module/energy/controller/admin/record/HydrogenRecordController.java
@@ -0,0 +1,105 @@
+package cn.iocoder.yudao.module.energy.controller.admin.record;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.module.energy.controller.admin.record.vo.*;
+import cn.iocoder.yudao.module.energy.convert.record.HydrogenRecordConvert;
+import cn.iocoder.yudao.module.energy.dal.dataobject.record.EnergyHydrogenRecordDO;
+import cn.iocoder.yudao.module.energy.service.record.HydrogenRecordService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 加氢记录管理")
+@RestController
+@RequestMapping("/energy/hydrogen-record")
+@Validated
+public class HydrogenRecordController {
+
+ @Resource
+ private HydrogenRecordService hydrogenRecordService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建加氢记录")
+ @PreAuthorize("@ss.hasPermission('energy:hydrogen-record:create')")
+ public CommonResult createRecord(@Valid @RequestBody HydrogenRecordSaveReqVO createReqVO) {
+ return success(hydrogenRecordService.createRecord(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新加氢记录")
+ @PreAuthorize("@ss.hasPermission('energy:hydrogen-record:update')")
+ public CommonResult updateRecord(@Valid @RequestBody HydrogenRecordSaveReqVO updateReqVO) {
+ hydrogenRecordService.updateRecord(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除加氢记录")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('energy:hydrogen-record:delete')")
+ public CommonResult deleteRecord(@RequestParam("id") Long id) {
+ hydrogenRecordService.deleteRecord(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得加氢记录")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('energy:hydrogen-record:query')")
+ public CommonResult getRecord(@RequestParam("id") Long id) {
+ EnergyHydrogenRecordDO record = hydrogenRecordService.getRecord(id);
+ return success(HydrogenRecordConvert.INSTANCE.convert(record));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得加氢记录分页")
+ @PreAuthorize("@ss.hasPermission('energy:hydrogen-record:query')")
+ public CommonResult> getRecordPage(@Valid HydrogenRecordPageReqVO pageReqVO) {
+ PageResult pageResult = hydrogenRecordService.getRecordPage(pageReqVO);
+ return success(HydrogenRecordConvert.INSTANCE.convertPage(pageResult));
+ }
+
+ @Deprecated // 被 import-preview + import-confirm + import-progress 三步流程替代
+ @PostMapping("/import")
+ @Operation(summary = "Excel 批量导入")
+ @PreAuthorize("@ss.hasPermission('energy:hydrogen-record:import')")
+ public CommonResult