4、分摊引擎架构:分摊计算引擎的模块划分、输入输出接口、调度流程
分摊计算引擎是成本台账系统的核心计算单元,负责将公共成本(如水电费、折旧、管理费)按照预定义的分摊规则精确分配到多个成本对象(项目、部门、产品)。本章从架构视角拆解引擎的模块边界、接口契约与调度机制,为后续接口测试提供结构化的分析基础。
4.1 模块划分与职责
分摊引擎采用分层+微内核设计,核心模块包括以下五个部分:
| 模块名称 | 职责描述 | 关键输出 |
|---|---|---|
| 规则解析器 | 读取分摊规则配置(固定比例、按工时、按面积、按产量等),校验规则合法性,生成可执行的分摊策略树。 | 策略树对象、规则校验报告 |
| 数据加载器 | 从成本台账数据库或上游接口拉取待分摊的成本原始数据(成本中心、金额、期间、币种),完成数据清洗与格式转换。 | 标准化的成本数据集 |
| 分摊计算器 | 执行核心分摊算法:按策略树遍历,逐层计算各成本对象应承担金额,支持多维度(部门+项目+产品)交叉分摊。 | 分摊明细表、分摊汇总表 |
| 结果持久化器 | 将分摊结果写入目标表(分摊明细表、项目成本台账、财务报表接口表),处理并发写入与事务一致性。 | 写入确认记录、错误日志 |
| 调度控制器 | 管理分摊任务的触发、排队、重试、超时与监控,对外暴露统一的REST/SOAP接口。 | 任务状态、执行日志 |
测试关注点: 规则解析器是错误高发区,尤其当规则配置为“按工时分摊”但工时数据缺失时,引擎应触发降级策略(如均摊)而非直接报错。测试用例需覆盖规则缺失、规则冲突、规则循环引用等异常场景。
4.2 输入输出接口定义
分摊引擎对外暴露三个核心接口,接口契约采用JSON Schema定义,确保上下游系统解耦。
4.2.1 分摊任务提交接口(输入)
POST /api/v1/allocation/task
Content-Type: application/json
{
"taskId": "ALLOC_20250321_001",
"period": "2025-03",
"costCenterIds": ["CC001", "CC002"],
"ruleGroupId": "RG_DEFAULT",
"targetObjects": [
{"type": "project", "ids": ["PJ-A", "PJ-B", "PJ-C"]},
{"type": "department", "ids": ["DEPT-SALES", "DEPT-RD"]}
],
"options": {
"dryRun": false,
"rollbackOnError": true,
"timeoutSeconds": 300
}
}
4.2.2 分摊结果查询接口(输出)
GET /api/v1/allocation/result/{taskId}
Response:
{
"taskId": "ALLOC_20250321_001",
"status": "COMPLETED",
"totalCost": 1250000.00,
"allocatedCost": 1250000.00,
"details": [
{
"sourceCostCenter": "CC001",
"targetObject": {"type": "project", "id": "PJ-A"},
"amount": 350000.00,
"ruleApplied": "按面积分摊",
"baseValue": 3500.0,
"unit": "平方米"
}
],
"errors": []
}
4.2.3 接口对比表
| 接口 | 方向 | 协议 | 数据格式 | 幂等性 |
|---|---|---|---|---|
| 提交分摊任务 | 输入 | REST POST | JSON | 是(基于taskId去重) |
| 查询分摊结果 | 输出 | REST GET | JSON | 是(只读) |
| 回调通知 | 输出 | Webhook POST | JSON | 是(支持重试) |
4.3 调度流程与状态机
分摊引擎的调度流程采用有限状态机模型,确保每个任务的生命周期可追踪、可恢复。下图展示了从任务提交到结果回写的完整调度路径:
4.4 调度时序与重试机制
引擎调度控制器按以下时序执行任务,并内置三级重试策略:
- 任务接收: 控制器校验taskId唯一性,若重复则直接返回已有结果(幂等)。
- 数据加载: 调用数据加载器,若加载超时(默认30秒)或数据不完整,触发一级重试(最多3次,间隔5秒)。
- 分摊计算: 计算器执行策略树,若计算过程中出现除零、空指针等异常,触发二级重试(最多2次,间隔10秒)。
- 结果持久化: 写入数据库时若发生死锁或唯一键冲突,触发三级重试(最多5次,间隔1秒,使用指数退避)。
- 回调通知: 任务最终状态(COMPLETED/FAILED)通过Webhook通知调用方,通知失败则进入死信队列人工处理。
测试陷阱: 在接口测试中,需验证重试机制的幂等性。例如:同一taskId重复提交时,引擎不应重复计算,而应直接返回第一次的计算结果。若引擎错误地执行了两次分摊,将导致项目成本台账金额翻倍,财务报表合并时出现重大差异。
4.5 架构图:模块间依赖与数据流
下图展示了分摊引擎各模块之间的依赖关系与数据流向,帮助测试人员理解接口调用的上下游依赖:
架构测试策略: 针对上述模块依赖,接口测试应覆盖以下场景:
• 调度控制器在规则解析器超时(模拟响应延迟 > 5秒)时,是否正确触发重试并最终返回超时错误。
• 数据加载器返回空数据集时,分摊计算器是否直接输出零金额明细,还是抛出异常导致任务失败。
• 结果持久化器在数据库连接断开时,是否触发ROLLBACK状态并回滚已写入的中间数据,避免脏数据残留。
• 调度控制器在规则解析器超时(模拟响应延迟 > 5秒)时,是否正确触发重试并最终返回超时错误。
• 数据加载器返回空数据集时,分摊计算器是否直接输出零金额明细,还是抛出异常导致任务失败。
• 结果持久化器在数据库连接断开时,是否触发ROLLBACK状态并回滚已写入的中间数据,避免脏数据残留。