34 KiB
财务与收费域 - 详细设计
文档类型: 详细设计文档 生成日期: 2026-05-18 数据来源: REVERSE-FINANCE.md(反推文档)+ 04-FINANCE.md(原设计文档)+ 实际代码分析
一、功能点清单
| 编号 | 功能模块 | 功能点 | 实现状态 | 说明 |
|---|---|---|---|---|
| FIN-001 | 能耗计量管理 | 计量点CRUD | 已实现 | module-mdm 中 EnergyMeter |
| FIN-002 | 能耗计量管理 | 计量点编码自动生成 | 已实现 | EM + yyyyMMddHHmmss |
| FIN-003 | 能耗计量管理 | 计量点软删除 | 已实现 | 状态设为 INACTIVE |
| FIN-004 | 能耗录入 | 能耗数据录入 | 已实现 | 手动录入 + IoT预留 |
| FIN-005 | 能耗录入 | 读数递增校验 | 已实现 | 当前读数 >= 上次读数 |
| FIN-006 | 能耗录入 | 自动计算消耗量与费用 | 已实现 | consumption = current - previous; amount = consumption * unitPrice |
| FIN-007 | 能耗统计 | 按类型统计消耗 | 已实现(有缺陷) | 当前全部归入LIGHTING,需修复 |
| FIN-008 | 能耗统计 | 单方能耗 | 已实现 | 遍历项目ACTIVE计量点累加 |
| FIN-009 | 收费项目管理 | 收费项目CRUD | 未实现 | FeeItem 实体不存在 |
| FIN-010 | 收费项目管理 | 周期性收费配置 | 未实现 | 按月/季/年收费 |
| FIN-011 | 收费项目管理 | 一次性收费配置 | 未实现 | 临时收费项目 |
| FIN-012 | 收费项目管理 | 按面积计费配置 | 未实现 | 面积 * 单价 |
| FIN-013 | 收费项目管理 | 按用量计费配置 | 未实现 | 用量 * 单价(对接能耗) |
| FIN-014 | 收费项目管理 | 固定金额计费配置 | 未实现 | 每月固定金额 |
| FIN-015 | 账单管理 | 账单自动生成 | 未实现 | 根据收费项目规则按账期生成 |
| FIN-016 | 账单管理 | 账单手动生成 | 未实现 | 人工创建单笔账单 |
| FIN-017 | 账单管理 | 批量账单生成 | 未实现 | 一次性为项目所有业主生成 |
| FIN-018 | 账单管理 | 账单状态流转 | 未实现 | UNPAID/PARTIAL_PAID/PAID/OVERDUE/CANCELLED |
| FIN-019 | 账单管理 | 催缴提醒 | 未实现 | 到期前3天提醒 + 逾期催缴 |
| FIN-020 | 账单管理 | 账单导出 | 未实现 | Excel/PDF 格式 |
| FIN-021 | 支付管理 | 线下收款登记 | 未实现 | 现金/银行转账/刷卡 |
| FIN-022 | 支付管理 | 线上支付对接 | 未实现 | 微信/支付宝 |
| FIN-023 | 支付管理 | 支付确认 | 未实现 | 支付状态确认 |
| FIN-024 | 支付管理 | 支付记录查询 | 未实现 | 按账单/业主/时间查询 |
| FIN-025 | 退款管理 | 退款申请 | 未实现 | 业主发起退款 |
| FIN-026 | 退款管理 | 退款审核 | 未实现 | 审批流程 |
| FIN-027 | 退款管理 | 退款执行 | 未实现 | 原路退回/线下退款 |
| FIN-028 | 滞纳金 | 滞纳金自动计算 | 未实现 | 逾期天数 * 日利率 |
| FIN-029 | 滞纳金 | 滞纳金上限控制 | 未实现 | 不超过 maxLateFee |
| FIN-030 | 能耗对接 | 能耗数据与账单对接 | 未实现 | EnergyConsumption -> FeeBill |
| FIN-031 | 能耗修复 | 修复按类型统计 | 未实现 | 按 meter.energyType 真正分项汇总 |
| FIN-032 | 能耗修复 | 统一前后端能源类型枚举 | 未实现 | 后端6种 vs 前端5种 |
| FIN-033 | 财务报表 | 收费统计 | 未实现 | 按项目/类型/时间维度 |
| FIN-034 | 财务报表 | 欠费分析 | 未实现 | 逾期/欠费金额统计 |
| FIN-035 | 财务报表 | 收入趋势 | 未实现 | 月度/季度趋势图 |
二、数据结构设计
2.1 已实现实体
2.1.1 EnergyMeter(能源计量点)
所在模块: module-mdm
数据库表: ops_energy_meter
源码: ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/EnergyMeter.java
| 字段名 | 类型 | 数据库列名 | 约束 | 说明 |
|---|---|---|---|---|
| id | UUID | id | PK | 主键 |
| projectId | UUID | project_id | NOT NULL | 所属项目 |
| meterCode | String | meter_code | NOT NULL, UNIQUE | 计量点编码(EM + yyyyMMddHHmmss) |
| meterName | String | meter_name | NOT NULL | 计量点名称 |
| energyType | EnergyType | energy_type | NOT NULL | 能源类型枚举 |
| spaceNodeId | UUID | space_node_id | -- | 关联空间节点 |
| installationLocation | String | installation_location | -- | 安装位置 |
| ratedCapacity | BigDecimal(10,2) | rated_capacity | -- | 额定容量 |
| unitPrice | BigDecimal(10,4) | unit_price | -- | 单价(4位小数精度) |
| status | Status | status | NOT NULL, 默认ACTIVE | 状态枚举 |
| createdAt | LocalDateTime | created_at | -- | 创建时间 |
| updatedAt | LocalDateTime | updated_at | -- | 更新时间 |
枚举定义:
public enum EnergyType {
LIGHTING("照明插座用电"),
HVAC("空调用电"),
POWER("动力用电"),
SPECIAL("特殊用电"),
WATER("给排水"),
GAS("燃气");
}
public enum Status {
ACTIVE, INACTIVE
}
2.1.2 EnergyConsumption(能耗记录)
所在模块: module-mdm
数据库表: ops_energy_consumption
源码: ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/EnergyConsumption.java
| 字段名 | 类型 | 数据库列名 | 约束 | 说明 |
|---|---|---|---|---|
| id | UUID | id | PK | 主键 |
| projectId | UUID | project_id | NOT NULL | 所属项目 |
| meterId | UUID | meter_id | NOT NULL | 关联计量点 |
| consumptionDate | LocalDate | consumption_date | NOT NULL | 记录日期 |
| previousReading | BigDecimal(12,2) | previous_reading | -- | 上次读数 |
| currentReading | BigDecimal(12,2) | current_reading | -- | 当前读数 |
| consumption | BigDecimal(12,2) | consumption | NOT NULL | 消耗量 = current - previous |
| amount | BigDecimal(10,2) | amount | -- | 费用 = consumption * unitPrice |
| recordedBy | UUID | recorded_by | -- | 记录人 |
| recordMethod | RecordMethod | record_method | -- | 记录方式,默认MANUAL |
| remarks | String(1000) | remarks | -- | 备注 |
| createdAt | LocalDateTime | created_at | -- | 创建时间 |
数据库索引:
idx_ec_meter_date -- (meter_id, consumption_date)
idx_ec_project_date -- (project_id, consumption_date)
枚举定义:
public enum RecordMethod {
MANUAL, // 手动录入
IOT // IoT自动采集
}
2.2 待实现实体
2.2.1 FeeItem(收费项目)
目标模块: module-finance(待创建)
目标表: fin_fee_item
| 字段名 | 类型 | 数据库列名 | 约束 | 说明 |
|---|---|---|---|---|
| id | UUID | id | PK | 主键 |
| projectId | UUID | project_id | NOT NULL | 所属项目 |
| code | VARCHAR(50) | code | NOT NULL, UNIQUE | 收费项目编码(FI + yyyyMMddHHmmss) |
| name | VARCHAR(100) | name | NOT NULL | 收费项目名称 |
| type | VARCHAR(20) | type | NOT NULL | 收费类型枚举 |
| billingMethod | VARCHAR(20) | billing_method | NOT NULL | 计费方式枚举 |
| unitPrice | DECIMAL(12,4) | unit_price | -- | 单价(按用量/面积计费时使用) |
| unit | VARCHAR(20) | unit | -- | 计量单位(kWh/吨/平方米/月/次) |
| fixedAmount | DECIMAL(12,2) | fixed_amount | -- | 固定金额(FIXED计费方式) |
| billDay | INT | bill_day | -- | 出账日(每月几号出账,1-28) |
| dueDay | INT | due_day | -- | 到期日(出账后第N天到期) |
| overdueDay | INT | overdue_day | -- | 逾期日(到期后第N天开始计滞纳金) |
| enableLateFee | BOOLEAN | enable_late_fee | NOT NULL, 默认false | 是否启用滞纳金 |
| lateFeeRate | DECIMAL(8,6) | late_fee_rate | -- | 日滞纳金利率(如0.0005 = 万分之五/天) |
| maxLateFee | DECIMAL(12,2) | max_late_fee | -- | 滞纳金上限金额 |
| description | VARCHAR(500) | description | -- | 收费项目说明 |
| status | VARCHAR(20) | status | NOT NULL, 默认ENABLED | 状态:ENABLED/DISABLED |
| createdAt | TIMESTAMP | created_at | NOT NULL | 创建时间 |
| updatedAt | TIMESTAMP | updated_at | NOT NULL | 更新时间 |
| createdBy | UUID | created_by | -- | 创建人 |
枚举定义:
public enum FeeType {
PROPERTY("物业费"),
PARKING("停车费"),
WATER("水费"),
ELECTRICITY("电费"),
GAS("燃气费"),
HEATING("供暖费"),
REPAIR_FUND("维修基金"),
OTHER("其他");
}
public enum BillingMethod {
FIXED("固定金额"), // 每月固定金额
AREA("按面积计费"), // 面积 * 单价
USAGE("按用量计费"), // 用量 * 单价(对接能耗)
CUSTOM("自定义"); // 自定义计费规则
}
数据库索引:
idx_fi_project_status -- (project_id, status)
idx_fi_code -- (code) -- UNIQUE约束自带索引
idx_fi_type -- (type, status)
外键关系:
fk_fi_project -- project_id REFERENCES mdm_project(id)
2.2.2 FeeBill(收费账单)
目标模块: module-finance(待创建)
目标表: fin_fee_bill
| 字段名 | 类型 | 数据库列名 | 约束 | 说明 |
|---|---|---|---|---|
| id | UUID | id | PK | 主键 |
| billNo | VARCHAR(30) | bill_no | NOT NULL, UNIQUE | 账单编号(BL + yyyyMMdd + 4位序号) |
| feeItemId | UUID | fee_item_id | NOT NULL | 关联收费项目 |
| projectId | UUID | project_id | NOT NULL | 所属项目 |
| spaceNodeId | UUID | space_node_id | -- | 关联空间节点(房产) |
| ownerId | UUID | owner_id | -- | 关联业主ID |
| billPeriod | VARCHAR(20) | bill_period | NOT NULL | 账期(如2026-05) |
| billDate | DATE | bill_date | NOT NULL | 出账日期 |
| dueDate | DATE | due_date | NOT NULL | 到期日期 |
| overdueDate | DATE | overdue_date | -- | 逾期日期 |
| usageAmount | DECIMAL(12,2) | usage_amount | -- | 用量(按用量计费时) |
| usageUnit | VARCHAR(20) | usage_unit | -- | 用量单位 |
| area | DECIMAL(12,2) | area | -- | 面积(按面积计费时) |
| amount | DECIMAL(12,2) | amount | NOT NULL | 应收金额 |
| lateFee | DECIMAL(12,2) | late_fee | 默认0 | 滞纳金 |
| discount | DECIMAL(12,2) | discount | 默认0 | 优惠金额 |
| payableAmount | DECIMAL(12,2) | payable_amount | NOT NULL | 应付金额 = amount + lateFee - discount |
| paidAmount | DECIMAL(12,2) | paid_amount | 默认0 | 已付金额 |
| status | VARCHAR(20) | status | NOT NULL, 默认UNPAID | 账单状态枚举 |
| sourceType | VARCHAR(20) | source_type | -- | 来源类型:AUTO/MANUAL/IMPORT |
| sourceId | UUID | source_id | -- | 来源ID(如能耗记录ID) |
| remark | VARCHAR(500) | remark | -- | 备注 |
| createdAt | TIMESTAMP | created_at | NOT NULL | 创建时间 |
| updatedAt | TIMESTAMP | updated_at | NOT NULL | 更新时间 |
| createdBy | UUID | created_by | -- | 创建人 |
枚举定义:
public enum BillStatus {
UNPAID("未支付"),
PARTIAL_PAID("部分支付"),
PAID("已支付"),
OVERDUE("已逾期"),
CANCELLED("已取消");
}
public enum BillSourceType {
AUTO("自动生成"),
MANUAL("手动创建"),
IMPORT("导入");
}
数据库索引:
idx_fb_bill_no -- (bill_no) -- UNIQUE约束自带索引
idx_fb_project_period -- (project_id, bill_period)
idx_fb_owner_status -- (owner_id, status)
idx_fb_fee_item -- (fee_item_id, bill_period)
idx_fb_space_node -- (space_node_id, bill_period)
idx_fb_due_date -- (due_date, status) -- 用于催缴查询
idx_fb_overdue -- (status, overdue_date) -- 用于滞纳金计算
外键关系:
fk_fb_fee_item -- fee_item_id REFERENCES fin_fee_item(id)
fk_fb_project -- project_id REFERENCES mdm_project(id)
fk_fb_space_node -- space_node_id REFERENCES mdm_space_node(id)
2.2.3 FeePayment(支付记录)
目标模块: module-finance(待创建)
目标表: fin_fee_payment
| 字段名 | 类型 | 数据库列名 | 约束 | 说明 |
|---|---|---|---|---|
| id | UUID | id | PK | 主键 |
| paymentNo | VARCHAR(30) | payment_no | NOT NULL, UNIQUE | 支付编号(PY + yyyyMMddHHmmss) |
| billId | UUID | bill_id | NOT NULL | 关联账单 |
| amount | DECIMAL(12,2) | amount | NOT NULL | 支付金额 |
| method | VARCHAR(20) | method | NOT NULL | 支付方式枚举 |
| thirdPartyNo | VARCHAR(100) | third_party_no | -- | 第三方交易号(微信/支付宝) |
| status | VARCHAR(20) | status | NOT NULL, 默认PENDING | 支付状态枚举 |
| failReason | VARCHAR(500) | fail_reason | -- | 失败原因 |
| paymentTime | TIMESTAMP | payment_time | -- | 实际支付时间 |
| operatorId | UUID | operator_id | -- | 操作人(线下收款时为收费员) |
| receiptNo | VARCHAR(30) | receipt_no | -- | 收据编号 |
| remark | VARCHAR(500) | remark | -- | 备注 |
| createdAt | TIMESTAMP | created_at | NOT NULL | 创建时间 |
| updatedAt | TIMESTAMP | updated_at | NOT NULL | 更新时间 |
枚举定义:
public enum PaymentMethod {
WECHAT("微信支付"),
ALIPAY("支付宝"),
CASH("现金"),
BANK_TRANSFER("银行转账"),
CARD("刷卡");
}
public enum PaymentStatus {
PENDING("待支付"),
SUCCESS("支付成功"),
FAILED("支付失败"),
REFUNDED("已退款");
}
数据库索引:
idx_fp_payment_no -- (payment_no) -- UNIQUE约束自带索引
idx_fp_bill_id -- (bill_id)
idx_fp_status -- (status, payment_time)
idx_fp_method -- (method, payment_time)
idx_fp_operator -- (operator_id, payment_time)
外键关系:
fk_fp_bill -- bill_id REFERENCES fin_fee_bill(id)
2.2.4 FeeRefund(退款记录)
目标模块: module-finance(待创建)
目标表: fin_fee_refund
| 字段名 | 类型 | 数据库列名 | 约束 | 说明 |
|---|---|---|---|---|
| id | UUID | id | PK | 主键 |
| refundNo | VARCHAR(30) | refund_no | NOT NULL, UNIQUE | 退款编号(RF + yyyyMMddHHmmss) |
| paymentId | UUID | payment_id | NOT NULL | 关联支付记录 |
| billId | UUID | bill_id | NOT NULL | 关联账单 |
| amount | DECIMAL(12,2) | amount | NOT NULL | 退款金额 |
| reason | VARCHAR(500) | reason | NOT NULL | 退款原因 |
| status | VARCHAR(20) | status | NOT NULL, 默认PENDING | 退款状态枚举 |
| applicantId | UUID | applicant_id | NOT NULL | 申请人ID |
| approverId | UUID | approver_id | -- | 审批人ID |
| approveTime | TIMESTAMP | approve_time | -- | 审批时间 |
| approveRemark | VARCHAR(500) | approve_remark | -- | 审批备注 |
| thirdPartyRefundNo | VARCHAR(100) | third_party_refund_no | -- | 第三方退款单号 |
| refundTime | TIMESTAMP | refund_time | -- | 实际退款时间 |
| refundMethod | VARCHAR(20) | refund_method | -- | 退款方式:ORIGINAL/OFFLINE |
| remark | VARCHAR(500) | remark | -- | 备注 |
| createdAt | TIMESTAMP | created_at | NOT NULL | 创建时间 |
| updatedAt | TIMESTAMP | updated_at | NOT NULL | 更新时间 |
枚举定义:
public enum RefundStatus {
PENDING("待审批"),
APPROVED("已审批"),
REJECTED("已拒绝"),
REFUNDED("已退款"),
FAILED("退款失败");
}
public enum RefundMethod {
ORIGINAL("原路退回"),
OFFLINE("线下退款");
}
数据库索引:
idx_fr_refund_no -- (refund_no) -- UNIQUE约束自带索引
idx_fr_payment -- (payment_id)
idx_fr_bill -- (bill_id)
idx_fr_status -- (status)
idx_fr_applicant -- (applicant_id, status)
外键关系:
fk_fr_payment -- payment_id REFERENCES fin_fee_payment(id)
fk_fr_bill -- bill_id REFERENCES fin_fee_bill(id)
2.3 实体关系图
EnergyMeter (module-mdm) FeeItem (module-finance)
| |
v v
EnergyConsumption ---费用计算---> FeeBill (自动/手动生成)
(抄表数据) | |
| +---> FeePayment (支付记录)
| |
| v
| FeeRefund (退款记录)
|
+-- sourceType=AUTO, sourceId=EnergyConsumption.id
跨模块引用关系:
- FeeBill.sourceId 可指向 EnergyConsumption.id(按用量计费时)
- FeeBill.spaceNodeId 引用 mdm_space_node.id
- FeeBill.ownerId 引用 auth_user.id(业主)
- FeePayment.operatorId 引用 auth_user.id(收费员)
- FeeRefund.applicantId / approverId 引用 auth_user.id
三、API设计
3.1 已实现API:能耗管理相关端点
基础路径: /api/ops/energy
控制器: EnergyController
3.1.1 计量点管理
| 方法 | 路径 | 说明 | 请求参数 | 响应类型 |
|---|---|---|---|---|
| POST | /meters |
创建计量点 | EnergyMeter JSON | ApiResponse<EnergyMeter> |
| GET | /meters |
查询计量点列表 | projectId(必填), energyType(可选) | ApiResponse<List<EnergyMeter>> |
| GET | /meters/{id} |
获取计量点详情 | path: id | ApiResponse<EnergyMeter> |
| PUT | /meters/{id} |
更新计量点 | path: id, EnergyMeter JSON | ApiResponse<EnergyMeter> |
| DELETE | /meters/{id} |
删除计量点(软删除) | path: id | ApiResponse<Void> |
3.1.2 能耗记录
| 方法 | 路径 | 说明 | 请求参数 | 响应类型 |
|---|---|---|---|---|
| POST | /consumption |
录入能耗数据 | {meterId, currentReading, recordedBy} |
ApiResponse<EnergyConsumption> |
| GET | /consumption/{meterId} |
查询能耗记录 | path: meterId, startDate(可选), endDate(可选) | ApiResponse<List<EnergyConsumption>> |
3.1.3 能耗统计
| 方法 | 路径 | 说明 | 请求参数 | 响应类型 |
|---|---|---|---|---|
| GET | /statistics/by-type |
按类型统计消耗 | projectId, month(yyyy-MM-dd) | ApiResponse<Map<EnergyType, BigDecimal>> |
| GET | /statistics/unit-consumption |
单方能耗 | projectId, month(yyyy-MM-dd) | ApiResponse<BigDecimal> |
3.2 待实现API:收费项目/账单/支付/退款相关端点
3.2.1 FeeItemController -- 收费项目管理
基础路径: /api/finance/fee-items
| 方法 | 路径 | 说明 | 请求体/参数 | 响应类型 |
|---|---|---|---|---|
| POST | / |
创建收费项目 | FeeItemForm JSON | ApiResponse<FeeItem> |
| GET | / |
查询收费项目列表 | projectId(必填), type(可选), status(可选), page, size | ApiResponse<PageResponse<FeeItem>> |
| GET | /{id} |
获取收费项目详情 | path: id | ApiResponse<FeeItem> |
| PUT | /{id} |
更新收费项目 | path: id, FeeItemForm JSON | ApiResponse<FeeItem> |
| PUT | /{id}/status |
启用/禁用收费项目 | {status: "ENABLED"/"DISABLED"} |
ApiResponse<Void> |
| DELETE | /{id} |
删除收费项目 | path: id | ApiResponse<Void> |
FeeItemForm:
{
"projectId": "UUID",
"name": "物业费",
"type": "PROPERTY",
"billingMethod": "AREA",
"unitPrice": 3.50,
"unit": "平方米/月",
"fixedAmount": null,
"billDay": 1,
"dueDay": 15,
"overdueDay": 5,
"enableLateFee": true,
"lateFeeRate": 0.0005,
"maxLateFee": 500.00,
"description": "住宅物业费"
}
3.2.2 FeeBillController -- 账单管理
基础路径: /api/finance/bills
| 方法 | 路径 | 说明 | 请求体/参数 | 响应类型 |
|---|---|---|---|---|
| POST | / |
手动创建账单 | FeeBillForm JSON | ApiResponse<FeeBill> |
| POST | /generate |
按收费项目自动生成账单 | {projectId, feeItemId, billPeriod} |
ApiResponse<List<FeeBill>> |
| POST | /generate-batch |
批量生成账单 | {projectId, billPeriod, feeItemIds[]} |
ApiResponse<BatchResult> |
| GET | / |
查询账单列表 | projectId, ownerId, status, billPeriod, page, size | ApiResponse<PageResponse<FeeBill>> |
| GET | /{id} |
获取账单详情 | path: id | ApiResponse<FeeBill> |
| PUT | /{id} |
更新账单 | path: id, FeeBillForm JSON | ApiResponse<FeeBill> |
| POST | /{id}/cancel |
取消账单 | {reason} |
ApiResponse<Void> |
| GET | /overdue |
查询逾期账单 | projectId, page, size | ApiResponse<PageResponse<FeeBill>> |
| GET | /statistics |
账单统计 | projectId, billPeriod | ApiResponse<BillStatistics> |
| GET | /export |
导出账单 | projectId, billPeriod, format | Blob |
FeeBillForm:
{
"feeItemId": "UUID",
"projectId": "UUID",
"spaceNodeId": "UUID",
"ownerId": "UUID",
"billPeriod": "2026-05",
"usageAmount": 150.50,
"usageUnit": "kWh",
"area": 120.00,
"amount": 525.00,
"remark": ""
}
BillStatistics:
{
"totalAmount": 150000.00,
"paidAmount": 120000.00,
"unpaidAmount": 30000.00,
"overdueAmount": 15000.00,
"lateFeeAmount": 500.00,
"totalCount": 200,
"paidCount": 160,
"unpaidCount": 30,
"overdueCount": 10
}
3.2.3 FeePaymentController -- 支付管理
基础路径: /api/finance/payments
| 方法 | 路径 | 说明 | 请求体/参数 | 响应类型 |
|---|---|---|---|---|
| POST | / |
创建支付记录(线下收款) | PaymentForm JSON | ApiResponse<FeePayment> |
| GET | / |
查询支付记录 | billId, ownerId, method, status, startDate, endDate, page, size | ApiResponse<PageResponse<FeePayment>> |
| GET | /{id} |
获取支付详情 | path: id | ApiResponse<FeePayment> |
| POST | /{id}/confirm |
确认支付 | {status: "SUCCESS"/"FAILED", failReason} |
ApiResponse<FeePayment> |
| POST | /online/prepare |
发起线上支付 | {billId, method} |
ApiResponse<PaymentPrepareResult> |
| POST | /online/callback |
支付回调 | 第三方回调数据 | ApiResponse<Void> |
PaymentForm:
{
"billId": "UUID",
"amount": 525.00,
"method": "CASH",
"receiptNo": "RCP20260518001",
"remark": ""
}
3.2.4 FeeRefundController -- 退款管理
基础路径: /api/finance/refunds
| 方法 | 路径 | 说明 | 请求体/参数 | 响应类型 |
|---|---|---|---|---|
| POST | / |
申请退款 | RefundForm JSON | ApiResponse<FeeRefund> |
| GET | / |
查询退款记录 | billId, status, startDate, endDate, page, size | ApiResponse<PageResponse<FeeRefund>> |
| GET | /{id} |
获取退款详情 | path: id | ApiResponse<FeeRefund> |
| POST | /{id}/approve |
审批通过 | {approveRemark} |
ApiResponse<FeeRefund> |
| POST | /{id}/reject |
审批拒绝 | {approveRemark} |
ApiResponse<FeeRefund> |
| POST | /{id}/execute |
执行退款 | {thirdPartyRefundNo, refundMethod} |
ApiResponse<FeeRefund> |
RefundForm:
{
"paymentId": "UUID",
"billId": "UUID",
"amount": 525.00,
"reason": "重复缴费",
"refundMethod": "ORIGINAL"
}
3.2.5 FeeReminderJob -- 催缴定时任务
| 任务 | Cron表达式 | 说明 |
|---|---|---|
| 到期提醒 | 0 0 9 * * ? |
每天上午9点检查3天内到期账单,发送提醒 |
| 逾期催缴 | 0 0 10 * * ? |
每天上午10点检查逾期账单,发送催缴通知 |
| 滞纳金计算 | 0 0 2 * * ? |
每天凌晨2点计算逾期账单滞纳金 |
| 周汇总 | 0 0 18 ? * MON |
每周一18点汇总逾期账单,通知项目经理 |
四、业务规则
4.1 能耗计费规则(已实现 + 待完善)
4.1.1 已实现规则
| 规则编号 | 规则名称 | 规则描述 | 实现位置 |
|---|---|---|---|
| E-001 | 仪表状态校验 | 只能对ACTIVE状态的仪表进行抄表 | EnergyConsumptionServiceImpl |
| E-002 | 读数递增校验 | 当前读数不能小于上次读数 | EnergyConsumptionServiceImpl |
| E-003 | 自动获取上次读数 | 从最近一条记录获取previousReading,首次为0 | EnergyConsumptionServiceImpl |
| E-004 | 自动计算消耗量 | consumption = currentReading - previousReading | EnergyConsumptionServiceImpl |
| E-005 | 自动计算费用 | amount = consumption * meter.unitPrice(单价为空时为0) | EnergyConsumptionServiceImpl |
| E-006 | 按月统计 | 根据month参数计算月份起止日期 | EnergyConsumptionServiceImpl |
| E-007 | 单方能耗 | 遍历项目所有ACTIVE计量点,累加月度消耗量 | EnergyConsumptionServiceImpl |
4.1.2 待修复缺陷
| 缺陷编号 | 描述 | 严重度 | 修复方案 |
|---|---|---|---|
| E-BUG-001 | getConsumptionByType()将总消耗全部归入LIGHTING | 高 | 按 meter.energyType 真正分项汇总 |
| E-BUG-002 | 前后端能源类型枚举不一致 | 中 | 统一为后端6种枚举,前端对齐 |
4.2 收费项目规则(待设计)
| 规则编号 | 规则名称 | 规则描述 | 适用计费方式 |
|---|---|---|---|
| FI-001 | 周期性收费 | 按月/季/年定期出账,billDay指定出账日 | FIXED / AREA / USAGE |
| FI-002 | 一次性收费 | 临时创建,不参与自动出账 | CUSTOM |
| FI-003 | 临时收费 | 针对特定业主的临时性收费 | CUSTOM |
| FI-004 | 固定金额计费 | 每期收取固定金额(如停车费300元/月) | FIXED |
| FI-005 | 按面积计费 | 面积 * 单价(如物业费3.5元/平方米/月) | AREA |
| FI-006 | 按用量计费 | 用量 * 单价(如电费0.85元/kWh),对接能耗数据 | USAGE |
| FI-007 | 编码自动生成 | 格式:FI + yyyyMMddHHmmss,冲突时追加后缀 | 全部 |
| FI-008 | 禁用不删除 | 收费项目禁用后不再参与自动出账,已有账单不受影响 | 全部 |
| FI-009 | 项目隔离 | 收费项目属于特定项目,跨项目不可见 | 全部 |
4.3 账单生成规则(待设计)
| 规则编号 | 规则名称 | 规则描述 |
|---|---|---|
| BL-001 | 自动生成 | 根据收费项目的billDay,定时任务自动为项目下所有业主生成账单 |
| BL-002 | 手动生成 | 管理员手动为指定业主创建账单 |
| BL-003 | 批量生成 | 一次性为项目所有业主生成某类收费项目的账单 |
| BL-004 | 账单编号生成 | 格式:BL + yyyyMMdd + 4位序号,序号按天递增 |
| BL-005 | 到期日计算 | dueDate = billDate + feeItem.dueDay天 |
| BL-006 | 逾期日计算 | overdueDate = dueDate + feeItem.overdueDay天 |
| BL-007 | 按用量计费账单 | 从EnergyConsumption获取当期用量,计算金额 |
| BL-008 | 按面积计费账单 | 从SpaceNode获取面积,计算金额 = 面积 * 单价 |
| BL-009 | 固定金额账单 | 金额 = feeItem.fixedAmount |
| BL-010 | 防重复生成 | 同一收费项目 + 同一业主 + 同一账期不可重复生成 |
| BL-011 | 催缴提醒 | 到期前3天发送提醒,逾期后发送催缴通知 |
| BL-012 | 账单取消 | 已支付/部分支付的账单不可取消,需先退款 |
4.4 支付流程(待设计)
| 规则编号 | 规则名称 | 规则描述 |
|---|---|---|
| PY-001 | 线下收款 | 管理员登记现金/转账/刷卡收款,直接确认成功 |
| PY-002 | 线上支付 | 调用微信/支付宝SDK生成预支付单,等待回调确认 |
| PY-003 | 支付确认 | 线上支付由回调确认,线下支付由操作员确认 |
| PY-004 | 部分支付 | 支持部分支付,账单状态变为PARTIAL_PAID |
| PY-005 | 超额支付 | 支付金额不可超过应付金额(payableAmount - paidAmount) |
| PY-006 | 支付编号生成 | 格式:PY + yyyyMMddHHmmss |
| PY-007 | 账单状态联动 | 支付成功后更新账单paidAmount和status |
| PY-008 | 收据编号 | 线下收款时生成收据编号 |
支付状态流转:
PENDING --(支付成功)--> SUCCESS
PENDING --(支付失败)--> FAILED
SUCCESS --(发起退款)--> REFUNDED
账单状态联动:
UNPAID --(部分支付)--> PARTIAL_PAID
UNPAID/PARTIAL_PAID --(全额支付)--> PAID
UNPAID --(超过逾期日)--> OVERDUE
任意状态 --(取消)--> CANCELLED(需先退款)
4.5 退款流程(待设计)
| 规则编号 | 规则名称 | 规则描述 |
|---|---|---|
| RF-001 | 退款申请 | 业主或管理员发起退款申请,需指定退款原因 |
| RF-002 | 退款金额限制 | 退款金额不可超过原支付金额 |
| RF-003 | 退款审批 | 退款金额 > 1000元需审批,否则自动通过 |
| RF-004 | 审批通过 | 审批人确认后,退款状态变为APPROVED |
| RF-005 | 审批拒绝 | 审批人可拒绝退款,需填写拒绝原因 |
| RF-006 | 原路退回 | 线上支付的退款原路退回至支付账户 |
| RF-007 | 线下退款 | 现金/转账支付的退款通过线下处理 |
| RF-008 | 退款执行 | 记录第三方退款单号和实际退款时间 |
| RF-009 | 账单金额回退 | 退款成功后,账单paidAmount减少,状态可能回退 |
| RF-010 | 退款编号生成 | 格式:RF + yyyyMMddHHmmss |
退款状态流转:
PENDING --(审批通过)--> APPROVED
PENDING --(审批拒绝)--> REJECTED
APPROVED --(退款成功)--> REFUNDED
APPROVED --(退款失败)--> FAILED
4.6 滞纳金计算(待设计)
| 规则编号 | 规则名称 | 规则描述 |
|---|---|---|
| LF-001 | 计算触发 | 每天凌晨2点定时任务检查逾期账单 |
| LF-002 | 计算公式 | lateFee = 逾期天数 * payableAmount * lateFeeRate |
| LF-003 | 逾期天数 | 从overdueDate开始计算,到当前日期 |
| LF-004 | 上限控制 | lateFee不超过feeItem.maxLateFee |
| LF-005 | 累加计算 | 每天累加,不覆盖之前的滞纳金 |
| LF-006 | 前提条件 | 仅当feeItem.enableLateFee = true时计算 |
| LF-007 | 已支付账单 | 已全额支付的账单不再计算滞纳金 |
| LF-008 | 已取消账单 | 已取消的账单不再计算滞纳金 |
| LF-009 | 部分支付 | 滞纳金基于剩余应付金额计算 |
滞纳金计算示例:
假设:
payableAmount = 1000元
lateFeeRate = 0.0005(万分之五/天)
maxLateFee = 500元
overdueDate = 2026-05-10
当前日期 = 2026-05-18
计算:
逾期天数 = 8天
每日滞纳金 = 1000 * 0.0005 = 0.5元
累计滞纳金 = 8 * 0.5 = 4元(未超过上限500元)
五、执行约束
| 约束编号 | 约束名称 | 约束描述 |
|---|---|---|
| CON-001 | 金额精度 | 所有金额字段使用DECIMAL(12,2),单价使用DECIMAL(12,4),利率使用DECIMAL(8,6) |
| CON-002 | 事务一致性 | 账单生成、支付确认、退款执行必须在同一事务中完成账单状态更新 |
| CON-003 | 并发控制 | 支付操作使用乐观锁(version字段或状态校验),防止重复支付 |
| CON-004 | 审计日志 | 所有收费/支付/退款操作必须记录审计日志 |
| CON-005 | 项目隔离 | 所有查询必须按projectId过滤,确保项目间数据隔离 |
| CON-006 | 软删除 | 收费项目使用启用/禁用替代物理删除,账单/支付/退款不允许删除 |
| CON-007 | 编码唯一性 | billNo/paymentNo/refundNo全局唯一,生成时需处理冲突 |
| CON-008 | 定时任务幂等 | 催缴/滞纳金计算任务必须幂等,重复执行不产生副作用 |
六、权限控制
| 权限编码 | 权限名称 | 适用角色 | 说明 |
|---|---|---|---|
| finance:fee-item:list | 查看收费项目 | 项目管理员/财务人员 | 查看项目下收费项目列表 |
| finance:fee-item:create | 创建收费项目 | 系统管理员 | 创建新的收费项目 |
| finance:fee-item:update | 修改收费项目 | 系统管理员 | 修改收费项目配置 |
| finance:fee-item:delete | 删除收费项目 | 系统管理员 | 删除/禁用收费项目 |
| finance:bill:list | 查看账单 | 项目管理员/财务人员 | 查看项目下账单列表 |
| finance:bill:create | 创建账单 | 财务人员 | 手动创建账单 |
| finance:bill:generate | 生成账单 | 财务人员 | 自动/批量生成账单 |
| finance:bill:cancel | 取消账单 | 财务主管 | 取消账单(需审批) |
| finance:bill:export | 导出账单 | 财务人员 | 导出账单Excel/PDF |
| finance:payment:create | 登记收款 | 财务人员 | 线下收款登记 |
| finance:payment:confirm | 确认支付 | 财务人员 | 确认支付状态 |
| finance:payment:list | 查看支付记录 | 财务人员 | 查看支付记录列表 |
| finance:refund:apply | 申请退款 | 财务人员/业主 | 发起退款申请 |
| finance:refund:approve | 审批退款 | 财务主管 | 审批退款申请 |
| finance:refund:execute | 执行退款 | 财务人员 | 执行退款操作 |
| finance:refund:list | 查看退款记录 | 财务人员 | 查看退款记录列表 |
| finance:statistics:view | 查看财务统计 | 项目管理员/财务主管 | 查看财务报表 |
| finance:late-fee:config | 配置滞纳金 | 系统管理员 | 配置滞纳金规则 |
数据级权限:
- 财务人员(PROJECT数据范围):只能查看/操作所属项目的财务数据
- 财务主管(ALL数据范围):可查看所有项目的财务数据
- 业主(SELF数据范围):只能查看自己的账单和支付记录
七、例外情况处理
| 例外编号 | 例外场景 | 处理策略 | 错误码 |
|---|---|---|---|
| EX-001 | 重复生成账单 | 检查feeItemId + ownerId + billPeriod唯一性,已存在则跳过 | 7001 |
| EX-002 | 支付金额超过应付金额 | 校验支付金额 <= payableAmount - paidAmount | 7002 |
| EX-003 | 已支付账单取消 | 拒绝取消,提示需先退款 | 7003 |
| EX-004 | 退款金额超过支付金额 | 校验退款金额 <= 原支付金额 | 7004 |
| EX-005 | 重复支付 | 状态校验,已支付/已退款的支付记录不可再次确认 | 7005 |
| EX-006 | 能耗数据缺失 | 按用量计费时无对应能耗记录,生成0元账单并标记异常 | 7006 |
| EX-007 | 业主无关联房产 | 生成账单时业主无房产关联,跳过并记录日志 | 7007 |
| EX-008 | 线上支付超时 | 支付状态保持PENDING,由对账任务处理 | 7008 |
| EX-009 | 线上支付回调异常 | 记录原始回调数据,人工介入处理 | 7009 |
| EX-010 | 滞纳金计算溢出 | lateFee不超过maxLateFee上限 | 7010 |
| EX-011 | 收费项目被禁用后自动出账 | 跳过已禁用的收费项目 | 7011 |
| EX-012 | 批量生成部分失败 | 记录成功/失败数量和失败原因,返回BatchResult | 7012 |