scaffold-finance 财务模块
模块概述
scaffold-finance 是 Scaffold v2 的财务管理模块,提供企业级财务核算能力。涵盖会计科目、会计期间、凭证管理、科目余额、辅助核算、应收/应付、收付款、费用报销、预算管理、固定资产、账龄分析、银行对账、财务报表等 16 个功能子域。采用 SPI 架构(FinanceEvent / FinanceSubjectMapper / FinanceVoucherGenerator)实现业务事件到财务凭证的自动转换,业务模块只需发布事件即可自动生成凭证和更新余额。
功能列表
- 会计科目管理:科目树 CRUD,支持多级科目、启用/禁用
- 会计期间管理:创建期间、开账、结账、反结账、期末结转、反结转
- 凭证管理:手工创建/更新/审核/作废凭证,支持 BPM 审核流程
- 科目余额查询:按期间查询科目余额,试算平衡表
- 结算账户管理:银行/现金账户 CRUD
- 辅助核算维度:自定义核算维度(部门/项目等),辅助余额跟踪
- 应收账款:应收账款 CRUD
- 应付账款:应付账款 CRUD
- 收款管理:收款单创建(含核销应收)
- 付款管理:付款单创建(含核销应付)
- 费用报销:报销单 CRUD,支持 BPM 审批流程
- 预算管理:预算编制、生效、执行跟踪
- 固定资产:资产登记、折旧执行、处置审批
- 账龄分析与核销:应收/应付账龄分析,核销记录查询
- 银行对账:导入银行流水、自动对账、手工匹配
- 财务报表:生成/查询报表快照
状态字段规范:
is_enabled 字段(期间、账户)遵循布尔语义:1 = 启用,0 = 禁用
核心组件
分层架构
| 层 |
类 |
职责 |
| Controller |
16 个 Controller(见下方 API 列表) |
REST 接口 |
| Service |
对应 16 个 Service + FinanceEngine |
业务逻辑 |
| Repository |
对应实体数量的 Repository |
数据访问 |
| Mapper |
对应实体数量的 Mapper |
ORM 映射 |
数据实体(23 个)
| 实体 |
说明 |
| FinanceSubject |
会计科目 |
| FinancePeriod |
会计期间 |
| FinanceVoucher |
凭证 |
| FinanceVoucherEntry |
凭证分录 |
| FinanceSettlement |
结算账户 |
| FinanceBalance |
科目余额 |
| FinanceAuxDimension |
辅助核算维度 |
| FinanceAuxBalance |
辅助余额 |
| FinanceReceivable |
应收账款 |
| FinancePayable |
应付账款 |
| FinanceReceipt |
收款单 |
| FinancePayment |
付款单 |
| FinanceExpenseClaim |
报销单 |
| FinanceExpenseItem |
报销明细 |
| FinanceBudget |
预算 |
| FinanceBudgetItem |
预算明细 |
| FinanceAsset |
固定资产 |
| FinanceAssetDepreciation |
折旧记录 |
| FinanceAssetDisposal |
资产处置 |
| FinanceWriteoff |
核销记录 |
| FinanceBankReconciliation |
银行对账记录 |
| FinanceBankStatement |
银行流水 |
| FinanceReportSnapshot |
报表快照 |
SPI 架构
SPI 接口定义在 scaffold-common 模块,scaffold-finance 提供默认实现。业务模块注入 FinanceEventPublisher 即可与财务模块交互。
FinanceEvent -- 财务事件
public interface FinanceEvent {
String getSourceType(); // 事件来源,如 "pay_order"、"refund"、"asset_depreciation"
Long getSourceId(); // 来源业务 ID
FinanceEventType getEventType(); // 事件类型
Long getAmount(); // 金额(分)
String getCurrency(); // 币种,默认 CNY
String getSummary(); // 业务摘要
LocalDateTime getEventTime(); // 事件时间
Map<String, Long> getAuxAccounting(); // 辅助核算维度
}
FinanceSubjectMapper -- 科目映射
根据事件来源类型映射到借方/贷方科目编码。业务模块实现此接口定义业务到科目的映射规则。
public interface FinanceSubjectMapper {
String supportsSourceType();
Map<String, String> mapSubjects(FinanceEvent event); // "debit" -> 科目编码, "credit" -> 科目编码
}
FinanceVoucherGenerator -- 凭证生成器
根据事件生成凭证分录。业务模块可实现此接口自定义分录生成逻辑。
public interface FinanceVoucherGenerator {
String supportsSourceType();
List<VoucherEntryDTO> generateEntries(FinanceEvent event);
}
FinanceEventPublisher -- 事件发布器
public interface FinanceEventPublisher {
void publish(FinanceEvent event);
void publishBatch(List<FinanceEvent> events);
}
- 默认实现:
DefaultFinanceEventPublisher(委托 FinanceEngine 处理)
- 空实现:
NopFinanceEventPublisher(当 scaffold-finance 未启用时自动配置)
FinanceEngine -- 财务引擎
核心处理流程:接收事件 -> 查找 SPI 映射 -> 校验期间 -> 校验借贷平衡 -> 生成凭证 -> 更新余额 -> 更新辅助余额。
- 根据
sourceType 查找 FinanceSubjectMapper 和 FinanceVoucherGenerator
- 校验当前是否有已开账的会计期间
- 调用
VoucherGenerator.generateEntries() 生成分录
- 校验借贷平衡(借方合计 = 贷方合计)
- 创建凭证和分录记录
- 更新科目余额(期初/本期/期末)
- 更新辅助核算余额
配置参数
配置前缀:scaffold.finance
| 参数 |
类型 |
默认值 |
说明 |
| enabled |
boolean |
true |
模块开关 |
| default-currency |
String |
CNY |
默认币种 |
| voucher-number-pattern |
String |
PZ{year}{month}{seq} |
凭证编号格式,支持 {year}、{month}、{seq} 占位符 |
API 接口列表
FinanceSubjectController -- 会计科目管理 (/v1/finance/subject)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询科目 |
| POST |
/create |
创建科目 |
| POST |
/update |
更新科目 |
| GET |
/detail?id= |
科目详情 |
| POST |
/delete?id= |
删除科目 |
| POST |
/toggle-enabled?id= |
切换启用状态 |
FinancePeriodController -- 会计期间管理 (/v1/finance/period)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询期间 |
| POST |
/create |
创建期间 |
| GET |
/detail?id= |
期间详情 |
| POST |
/open?id= |
开账 |
| POST |
/close?id= |
结账 |
| POST |
/reopen?id= |
反结账 |
| POST |
/settle?id= |
期末结转 |
| POST |
/unsettle?id= |
反结转 |
FinanceVoucherController -- 凭证管理 (/v1/finance/voucher)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询凭证 |
| POST |
/create |
手工创建凭证 |
| POST |
/update |
更新凭证(仅草稿/已驳回) |
| GET |
/detail?id= |
凭证详情(含分录) |
| POST |
/audit |
审核/作废凭证 |
| POST |
/delete?id= |
删除凭证(仅草稿) |
| POST |
/submit-audit?id= |
提交 BPM 审核 |
| POST |
/auditCallback |
BPM 审核回调 |
FinanceSettlementController -- 结算账户管理 (/v1/finance/settlement)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询结算账户 |
| POST |
/create |
创建结算账户 |
| POST |
/update |
更新结算账户 |
| GET |
/detail?id= |
结算账户详情 |
| POST |
/delete?id= |
删除结算账户 |
| POST |
/toggle-enabled?id= |
切换启用状态 |
FinanceBalanceController -- 科目余额查询 (/v1/finance/balance)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询科目余额 |
| POST |
/trial-balance |
试算平衡表 |
FinanceAuxDimensionController -- 辅助核算维度管理 (/v1/finance/aux-dimension)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询维度 |
| POST |
/create |
创建维度 |
| POST |
/update |
更新维度 |
| GET |
/detail?id= |
维度详情 |
| POST |
/delete?id= |
删除维度 |
FinanceReceivableController -- 应收账款管理 (/v1/finance/receivable)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询应收账款 |
| POST |
/create |
创建应收账款 |
| GET |
/detail?id= |
应收账款详情 |
| POST |
/delete?id= |
删除应收账款 |
FinancePayableController -- 应付账款管理 (/v1/finance/payable)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询应付账款 |
| POST |
/create |
创建应付账款 |
| GET |
/detail?id= |
应付账款详情 |
| POST |
/delete?id= |
删除应付账款 |
FinanceReceiptController -- 收款管理 (/v1/finance/receipt)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询收款单 |
| POST |
/create |
创建收款单(含核销) |
| GET |
/detail?id= |
收款单详情 |
| POST |
/delete?id= |
删除收款单 |
FinancePaymentController -- 付款管理 (/v1/finance/payment)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询付款单 |
| POST |
/create |
创建付款单(含核销) |
| GET |
/detail?id= |
付款单详情 |
| POST |
/delete?id= |
删除付款单 |
FinanceExpenseClaimController -- 费用报销管理 (/v1/finance/expense)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询报销单 |
| POST |
/create |
创建报销单 |
| GET |
/detail?id= |
报销单详情 |
| POST |
/delete?id= |
删除报销单 |
| POST |
/submit-audit?id= |
提交审批 |
FinanceBudgetController -- 预算管理 (/v1/finance/budget)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询预算 |
| POST |
/create |
创建预算 |
| GET |
/detail?id= |
预算详情 |
| POST |
/delete?id= |
删除预算 |
| POST |
/activate?id= |
预算生效 |
FinanceReportController -- 财务报表管理 (/v1/finance/report)
| 方法 |
路径 |
说明 |
| POST |
/generate |
生成报表 |
| GET |
/snapshot |
查询报表快照 |
FinanceAssetController -- 固定资产管理 (/v1/finance/asset)
| 方法 |
路径 |
说明 |
| POST |
/page |
分页查询资产 |
| POST |
/create |
新增资产 |
| GET |
/detail?id= |
资产详情 |
| POST |
/depreciation/execute |
执行折旧 |
| GET |
/depreciation/history?assetId= |
折旧历史 |
| POST |
/disposal/create |
提交处置 |
| POST |
/disposal/page |
处置记录分页 |
| POST |
/disposal/auditCallback?disposalId=&approved= |
处置审批回调 |
FinanceAgingController -- 账龄分析与核销查询 (/v1/finance/aging)
| 方法 |
路径 |
说明 |
| POST |
/analyze |
账龄分析 |
| POST |
/writeoff/page |
核销记录分页查询 |
FinanceBankReconciliationController -- 银行对账管理 (/v1/finance/bank)
| 方法 |
路径 |
说明 |
| POST |
/statement/import |
导入银行流水 |
| POST |
/statement/page |
银行流水分页 |
| POST |
/reconciliation/auto?periodId=&settlementId= |
触发自动对账 |
| POST |
/reconciliation/page |
对账结果分页 |
| POST |
/reconciliation/manual |
手工匹配 |
使用示例
1. 通过 SPI 发布财务事件
业务模块(如支付模块)支付成功后自动生成凭证:
@Autowired
private FinanceEventPublisher financeEventPublisher;
public void onPaySuccess(PayOrder order) {
FinanceEvent event = new FinanceEvent() {
public String getSourceType() { return "pay_order"; }
public Long getSourceId() { return order.getId(); }
public FinanceEventType getEventType() { return FinanceEventType.INCOME; }
public Long getAmount() { return order.getAmount(); }
public String getSummary() { return "订单支付入账: " + order.getOrderNo(); }
public LocalDateTime getEventTime() { return LocalDateTime.now(); }
};
financeEventPublisher.publish(event);
}
2. 实现科目映射 SPI
@Component
public class PayOrderSubjectMapper implements FinanceSubjectMapper {
@Override
public String supportsSourceType() { return "pay_order"; }
@Override
public Map<String, String> mapSubjects(FinanceEvent event) {
return Map.of("debit", "1002", "credit", "6001"); // 银行存款 / 主营业务收入
}
}
3. 实现凭证生成器 SPI
@Component
public class PayOrderVoucherGenerator implements FinanceVoucherGenerator {
@Override
public String supportsSourceType() { return "pay_order"; }
@Override
public List<VoucherEntryDTO> generateEntries(FinanceEvent event) {
return List.of(
VoucherEntryDTO.builder().subjectCode("1002").debit(event.getAmount()).summary("收款").build(),
VoucherEntryDTO.builder().subjectCode("6001").credit(event.getAmount()).summary("收入").build()
);
}
}
4. 手工创建凭证
POST /v1/finance/voucher/create
{
"periodId": 100,
"voucherDate": "2026-04-26",
"summary": "手工调整凭证",
"entries": [
{"subjectCode": "1002", "debit": 10000, "credit": 0, "summary": "借记银行存款"},
{"subjectCode": "6001", "debit": 0, "credit": 10000, "summary": "贷记主营业务收入"}
]
}
注意事项
- SPI 自动发现:FinanceSubjectMapper 和 FinanceVoucherGenerator 实现类需标记
@Component,FinanceEngine 通过 Spring 自动注入 List<FinanceSubjectMapper> 和 List<FinanceVoucherGenerator> 进行匹配
- 期间校验:自动生成凭证时,必须存在已开账的会计期间且事件日期在期间范围内
- 借贷平衡:每张凭证的借方合计必须等于贷方合计,否则 FinanceEngine 会抛出 BusinessException
- 凭证编号:按
scaffold.finance.voucher-number-pattern 格式自动生成,默认 PZ{year}{month}{seq}
- 金额单位:所有金额字段统一使用分为单位(Long 类型),与支付模块保持一致
- BPM 集成:凭证审核和费用报销均支持 BPM 审批流程,通过
BpmIntegrationService 可插拔集成
- 模块降级:当 scaffold-finance 未启用时,scaffold-common 自动配置
NopFinanceEventPublisher(空实现),不会影响业务模块编译和运行
- 状态枚举:
is_enabled 字段(期间、账户)遵循布尔语义:1 = 启用,0 = 禁用
VoucherStatus、PeriodStatus、ReceivableStatus、PayableStatus、ExpenseStatus、BudgetStatus、MatchStatus 等为多态状态机,不遵循布尔语义规范
待完善功能
- 费用报销 BPM 审批流程集成(FinanceExpenseClaimServiceImpl 中的 TODO:调用 BPM 发起审批流程)