Skip to content

合同管理模块业务流程测试用例

生成日期:2026-03-26 模块名称:yudao-module-contract 文档用途:以完整业务场景串联各子功能的集成测试用例


一、测试环境说明

说明
后端地址http://localhost:48080/admin-api
前端地址http://localhost:5800
测试账号admin / admin123
租户ID1
前置条件数据库已初始化字典(contract_type/contract_nature/contract_status 等)、菜单数据

二、测试场景概览

本测试用例设计 3 个完整业务场景,每个场景贯穿合同全生命周期的不同路径:

场景合同类型覆盖流程
场景 A销售合同(ERP 系统)配置 → 分类 → 模板 → 创建 → 明细行 → 收款计划 → 提交审批 → 审批通过 → 履约 → 统计验证
场景 B采购合同(设备采购)创建 → 提交审批 → 审批通过 → 合同变更 → 变更提交 → 履约(交付+付款) → 统计验证
场景 C服务合同(咨询服务)创建草稿 → 修改 → 删除 → 重新创建 → 搜索 → 导出 → 关闭

三、场景 A:销售合同全生命周期

业务故事:宇擎科技向客户"深圳创新科技"销售 ERP 系统,签订 58 万销售合同。合同经审批生效后,按 3 期收款,客户分阶段付款。全程跟踪履约进度。

A-01 合同配置

内容
前置条件系统已部署启动
操作入口合同管理 → 合同配置

测试步骤

#操作请求预期结果
1获取当前配置GET /contract/config/get返回默认配置或已有配置
2保存配置:编号前缀=HT、日期格式=yyyyMMdd、流水号位数=3、到期提醒=开启、提醒天数=30PUT /contract/config/save Body: {"codePrefix":"HT","codeDateFormat":"yyyyMMdd","codeSeqLength":3,"notifyEnabled":true,"notifyDays":30}code=0,保存成功
3再次获取配置验证GET /contract/config/get返回的字段值与步骤 2 一致

前端验证

#操作预期结果
4浏览器打开合同配置页 /contract/contract-config表单回显:编号前缀=HT、日期格式=yyyyMMdd、流水号位数=3、到期提醒开关=开启、天数=30
5修改提醒天数为 15,点击"保存配置"提示保存成功,刷新后回显 15

A-02 合同分类管理

内容
前置条件A-01 完成
操作入口合同管理 → 合同分类

测试步骤

#操作请求预期结果
1创建顶级分类"销售合同"POST /contract/category/create Body: {"name":"销售合同","code":"SALE","parentId":0,"sort":1,"status":0,"remark":"面向客户的销售类合同"}code=0,返回分类 ID(记为 catSaleId
2创建子分类"软件销售"挂在"销售合同"下POST /contract/category/create Body: {"name":"软件销售","code":"SALE_SW","parentId":${catSaleId},"sort":1,"status":0}code=0,返回 catSaleSwId
3查询分类列表GET /contract/category/list返回列表含"销售合同"和"软件销售",parentId 关系正确
4重复创建"销售合同"POST /contract/category/create Body: {"name":"销售合同","code":"SALE2","parentId":0,"sort":2,"status":0}code != 0,提示"合同分类名称已存在"
5获取精简列表GET /contract/category/simple-list返回 id/name/parentId 结构,可构建树

前端验证

#操作预期结果
6打开合同分类页面 /contract/contract-category树形表格正确展示,"销售合同"展开后显示"软件销售"
7点击"销售合同"行的"新增下级"按钮弹出表单,父分类自动回填为"销售合同"
8输入名称"实施服务"、编码"SALE_IMPL",点保存新增成功,表格刷新后"销售合同"下多出"实施服务"
9编辑"软件销售",修改排序为 2保存成功,排序变更
10尝试删除"销售合同"(有子分类)提示"存在子分类,无法删除"

A-03 合同模板管理

内容
前置条件A-02 完成,已有分类"软件销售"
操作入口合同管理 → 合同模板

测试步骤

#操作请求预期结果
1创建模板"标准销售合同模板"POST /contract/template/create Body: {"name":"标准销售合同模板","categoryId":${catSaleSwId},"description":"适用于一般商品和软件销售场景","status":0,"sort":1}code=0,返回模板 ID
2查询模板分页GET /contract/template/page?pageNo=1&pageSize=10列表含"标准销售合同模板",分类显示正确
3更新模板状态为停用PUT /contract/template/update Body: {"id":${templateId},"status":1}code=0
4再次查询,按 status=0 过滤GET /contract/template/page?pageNo=1&pageSize=10&status=0不含被停用的模板

前端验证

#操作预期结果
5打开合同模板页面 /contract/contract-template列表正确展示模板名称、合同分类、排序、状态、说明
6使用搜索条件"模板名称=标准"进行搜索列表过滤只显示含"标准"的模板
7点击"新增模板",填写名称、选择分类、输入说明保存成功,列表刷新

A-04 创建销售合同(含明细行)

内容
前置条件A-02、A-03 完成
操作入口合同管理 → 合同台账 → 新增合同

测试步骤

#操作请求预期结果
1生成合同编号GET /contract/info/generate-code返回格式为 HT + 日期 + 随机数,如 HT202603261234
2创建合同(含明细行)POST /contract/info/create Body 如下code=0,返回合同 ID(记为 contractAId

步骤 2 请求体

json
{
  "contractCode": "HT20260326A001",
  "contractName": "宇擎ERP系统销售合同",
  "categoryId": "${catSaleSwId}",
  "contractType": 1,
  "contractNature": 1,
  "partyACompanyName": "宇擎科技有限公司",
  "partyBName": "深圳创新科技有限公司",
  "partyBContact": "张三",
  "partyBPhone": "13800138001",
  "partyBAddress": "深圳市南山区科技园",
  "totalAmount": 580000,
  "currency": "CNY",
  "signDate": "2026-03-26",
  "startDate": "2026-04-01",
  "endDate": "2027-03-31",
  "ownerUserId": 1,
  "ownerUserName": "宇擎源码",
  "deptId": 103,
  "deptName": "研发部门",
  "remark": "含软件许可+首年维保",
  "items": [
    {"itemName": "ERP标准版软件许可", "spec": "V5.0", "unit": "套", "quantity": 1, "unitPrice": 400000, "amount": 400000, "remark": "含50用户授权"},
    {"itemName": "首年维保服务", "spec": "12个月", "unit": "年", "quantity": 1, "unitPrice": 80000, "amount": 80000},
    {"itemName": "数据迁移服务", "spec": "一次性", "unit": "项", "quantity": 1, "unitPrice": 100000, "amount": 100000}
  ]
}
#操作请求预期结果
3查询合同详情GET /contract/info/get?id=${contractAId}基本信息完整,items 列表含 3 条明细行,金额合计 580000
4验证合同状态status=0(草稿)、processStatus=-1(未发起)
5重复编号创建POST /contract/info/create 相同编号code != 0,提示"合同编号已存在"

前端验证

#操作预期结果
6打开合同台账列表 /contract/contract-info-list新合同显示在列表中,状态为"草稿"
7点击合同编号链接跳转到合同详情页 /contract/contract-info-detail?id=xxx
8详情页检查基本信息表单回显正确(合同名称、类型、性质、甲乙方、金额、日期等);合同明细表格显示 3 行

A-05 合同收款计划

内容
前置条件A-04 完成,合同 ID = contractAId
操作入口API 调用 / 合同详情页

测试步骤

#操作请求预期结果
1创建第 1 期收款计划POST /contract/payment-plan/create Body: {"contractId":${contractAId},"period":1,"planAmount":174000,"planDate":"2026-04-20","status":0,"remark":"首付款30%"}code=0,返回计划 ID
2创建第 2 期POST /contract/payment-plan/create Body: {"contractId":${contractAId},"period":2,"planAmount":232000,"planDate":"2026-07-31","status":0,"remark":"中期款40%"}code=0
3创建第 3 期POST /contract/payment-plan/create Body: {"contractId":${contractAId},"period":3,"planAmount":174000,"planDate":"2026-10-31","status":0,"remark":"尾款30%"}code=0
4查询该合同收款计划列表GET /contract/payment-plan/list?contractId=${contractAId}返回 3 条记录,期次 1/2/3,合计金额 = 580000
5更新第 1 期为已收款PUT /contract/payment-plan/update Body: {"id":${plan1Id},"actualAmount":174000,"actualDate":"2026-04-18","status":2}code=0
6再次查询,验证状态GET /contract/payment-plan/list?contractId=${contractAId}第 1 期 status=2(已收付),actualAmount=174000
7删除第 3 期计划DELETE /contract/payment-plan/delete?id=${plan3Id}code=0
8查询验证删除GET /contract/payment-plan/list?contractId=${contractAId}仅剩 2 条

A-06 提交合同审批

内容
前置条件A-04 完成,合同处于草稿状态
操作入口合同详情页 → 提交按钮

测试步骤

#操作请求预期结果
1提交合同POST /contract/info/submit Body: 同 A-04 步骤 2code=0,返回合同 ID
2查询合同状态GET /contract/info/get?id=${contractAId}status 变为审批中(1)或已生效(4,视流程配置),processInstanceId 不为空
3再次提交同一合同POST /contract/info/submit 相同 body应被拒绝或幂等处理

前端验证

#操作预期结果
4合同列表中查看该合同状态标签变为"审批中"或"已生效"(取决于是否配置了审批流程)
5合同详情页表单变为只读模式(已提交后不可编辑),显示审批状态

A-07 合同履约记录

内容
前置条件A-06 完成,合同已生效
操作入口合同管理 → 合同履约

测试步骤

#操作请求预期结果
1添加收款履约记录POST /contract/performance/create Body: {"contractId":${contractAId},"performanceType":4,"performanceAmount":174000,"performanceDate":"2026-04-18 10:00:00","performanceContent":"客户支付首付款","remark":"银行转账到账"}code=0,返回履约 ID
2添加交付履约记录POST /contract/performance/create Body: {"contractId":${contractAId},"performanceType":1,"performanceAmount":400000,"performanceDate":"2026-05-15 14:00:00","performanceContent":"ERP系统交付部署完成"}code=0
3查询合同履约列表GET /contract/performance/list-by-contract?contractId=${contractAId}返回 2 条记录
4查询履约汇总GET /contract/performance/summary?contractId=${contractAId}返回汇总数据,已履约金额 = 574000
5查询全局履约分页GET /contract/performance/page?pageNo=1&pageSize=10列表含上述 2 条,显示合同编号和名称
6更新一条履约记录PUT /contract/performance/update Body: {"id":${perfId},"remark":"更新备注"}code=0
7删除一条履约记录DELETE /contract/performance/delete?id=${perfId}code=0

前端验证

#操作预期结果
8打开合同履约页面 /contract/contract-performance列表正确展示,履约类型字典渲染(收款/交付/付款等)
9点击"新增履约记录"按钮弹出表单,合同选择下拉可搜索、履约类型下拉、金额输入、日期选择

A-08 统计分析验证

内容
前置条件A-01 ~ A-07 完成
操作入口合同管理 → 统计分析

测试步骤

#操作请求预期结果
1获取统计概览GET /contract/stats/overviewtotalCount >= 1,totalAmount 含 A 合同的 580000,各状态计数正确
2获取月度统计GET /contract/stats/monthly?year=20262026-03 月份有签约数据
3获取分类统计GET /contract/stats/category"销售合同"/"软件销售"分类有数据

前端验证

#操作预期结果
4打开统计分析页面 /contract/contract-stats概览卡片显示合同总数、各状态数量、合同总金额、已履约金额、待收付金额
5月度签约统计表格2026 年各月份的合同数量和金额正确

四、场景 B:采购合同 + 合同变更

业务故事:宇擎科技向联想采购服务器设备,签订 32 万采购合同。合同生效后,因业务扩展需求追加采购交换机,发起合同金额变更。变更审批通过后继续履约。

B-01 创建采购合同

#操作请求预期结果
1创建采购分类(如已有则跳过)POST /contract/category/create Body: {"name":"采购合同","code":"PURCHASE","parentId":0,"sort":2,"status":0}返回 catPurchaseId,或提示已存在
2创建采购合同POST /contract/info/create Body: {"contractCode":"HT20260326B001","contractName":"服务器设备采购合同","categoryId":${catPurchaseId},"contractType":2,"contractNature":2,"partyACompanyName":"宇擎科技有限公司","partyBName":"联想集团","partyBContact":"王五","partyBPhone":"13700137003","totalAmount":320000,"currency":"CNY","signDate":"2026-03-20","startDate":"2026-03-25","endDate":"2026-06-25","ownerUserId":1,"ownerUserName":"宇擎源码","deptId":103,"deptName":"研发部门","remark":"采购8台服务器","items":[{"itemName":"机架式服务器","spec":"Dell R750","unit":"台","quantity":8,"unitPrice":35000,"amount":280000},{"itemName":"企业级交换机","spec":"H3C S6520","unit":"台","quantity":2,"unitPrice":20000,"amount":40000}]}code=0,返回 contractBId
3查验合同详情GET /contract/info/get?id=${contractBId}合同类型=2(采购),性质=2(支出),明细 2 行,合计 320000
4提交审批POST /contract/info/submit 同上 bodycode=0

B-02 创建合同变更

内容
前置条件B-01 完成,合同已审批通过
操作入口合同管理 → 合同变更 → 新增变更

测试步骤

#操作请求预期结果
1创建变更申请POST /contract/change/create Body: {"contractId":${contractBId},"changeType":1,"changeReason":"业务扩展需要追加采购交换机","changeContent":"增加4台交换机,合同金额增加8万元","originalValue":"合同总额32万","newValue":"合同总额40万","remark":"追加采购需求"}code=0,返回变更 ID(changeId),自动生成 changeCode
2查询变更详情GET /contract/change/get?id=${changeId}changeCode 格式正确(BG+日期+序号),changeType=1(金额变更),关联 contractId 正确
3按合同查变更列表GET /contract/change/list-by-contract?contractId=${contractBId}返回 1 条变更记录
4查询变更分页GET /contract/change/page?pageNo=1&pageSize=10列表含该变更,显示合同编号和名称
5提交变更审批POST /contract/change/submit?id=${changeId}code=0
6查询变更状态GET /contract/change/get?id=${changeId}processStatus 不再是 -1(已发起流程)

前端验证

#操作预期结果
7打开合同变更页面 /contract/contract-change列表显示变更单号、合同编号、合同名称、变更类型(金额变更)、审批状态
8点击"新增变更"弹出表单,合同选择下拉可搜索,变更类型下拉,变更原因/内容/原值/新值可输入
9未提交的变更行操作列显示"提交"和"删除"按钮已提交的不显示删除

B-03 采购合同履约

#操作请求预期结果
1交付履约:服务器到货POST /contract/performance/create Body: {"contractId":${contractBId},"performanceType":1,"performanceAmount":280000,"performanceDate":"2026-04-10 14:00:00","performanceContent":"8台服务器到货验收,全部通过"}code=0
2交付履约:交换机到货POST /contract/performance/create Body: {"contractId":${contractBId},"performanceType":1,"performanceAmount":40000,"performanceDate":"2026-04-12 09:30:00","performanceContent":"2台交换机到货验收"}code=0
3付款履约POST /contract/performance/create Body: {"contractId":${contractBId},"performanceType":5,"performanceAmount":320000,"performanceDate":"2026-04-15 16:00:00","performanceContent":"全款支付"}code=0
4查询合同履约汇总GET /contract/performance/summary?contractId=${contractBId}已履约金额合计正确(含交付 + 付款)

五、场景 C:服务合同 + 边界测试

业务故事:创建一份咨询服务合同草稿,测试修改、删除、重建、搜索、导出等操作。

C-01 草稿生命周期

#操作请求预期结果
1保存草稿POST /contract/info/save Body: {"contractName":"年度技术咨询服务","contractType":3,"contractNature":2,"partyBName":"麦肯锡咨询","totalAmount":90000,"currency":"CNY"}code=0,返回合同 ID,自动生成编号
2查看草稿状态GET /contract/info/get?id=${contractCId}status=0(草稿),编号已自动生成
3修改草稿PUT /contract/info/update Body: {"id":${contractCId},"contractName":"2026年度技术咨询服务合同","totalAmount":120000,"startDate":"2026-04-01","endDate":"2026-12-31"}code=0
4查验修改结果GET /contract/info/get?id=${contractCId}名称、金额、日期均已更新
5删除草稿DELETE /contract/info/delete?id=${contractCId}code=0
6查验删除GET /contract/info/get?id=${contractCId}code != 0,提示合同不存在

C-02 列表搜索与导出

#操作请求预期结果
1无条件分页查询GET /contract/info/page?pageNo=1&pageSize=20返回合同列表,total > 0
2按合同编号搜索GET /contract/info/page?pageNo=1&pageSize=20&contractCode=HT20260326A仅返回编号匹配的合同
3按合同名称搜索GET /contract/info/page?pageNo=1&pageSize=20&contractName=ERP返回含"ERP"的合同
4按合同类型搜索GET /contract/info/page?pageNo=1&pageSize=20&contractType=1仅返回销售合同
5按合同状态搜索GET /contract/info/page?pageNo=1&pageSize=20&status=0仅返回草稿状态合同
6按乙方名称搜索GET /contract/info/page?pageNo=1&pageSize=20&partyBName=联想返回乙方含"联想"的合同
7组合条件搜索GET /contract/info/page?pageNo=1&pageSize=20&contractType=2&partyBName=联想返回采购合同且乙方含"联想"的数据
8导出 ExcelGET /contract/info/export-excel?contractType=1返回 Excel 文件流(Content-Type 含 spreadsheet),文件可正常打开
9获取精简列表GET /contract/info/simple-list返回 id/contractCode/contractName 列表,用于下拉选择

前端验证

#操作预期结果
10合同台账页面,输入"合同编号"搜索条件,点击搜索列表按编号过滤
11选择"合同类型=采购合同",点击搜索列表仅显示采购合同
12点击"重置"按钮搜索条件清空,列表恢复全部
13点击"导出"按钮浏览器下载 Excel 文件

六、场景 D:前端页面完整性检查

此场景不涉及具体业务数据,侧重于前端各页面的 UI 渲染、交互、路由跳转是否正常。

D-01 菜单与路由

#检查项路由预期结果
1合同管理一级菜单侧边栏左侧菜单出现"合同管理",点击展开子菜单
2合同台账/contract/contract-info-list页面正常加载,显示搜索栏+表格+分页
3合同分类/contract/contract-category页面正常加载,树形表格
4合同模板/contract/contract-template页面正常加载,列表+搜索+分页
5合同变更/contract/contract-change页面正常加载,列表+搜索+分页
6合同履约/contract/contract-performance页面正常加载,列表+搜索+分页
7合同配置/contract/contract-config页面正常加载,表单+保存按钮
8统计分析/contract/contract-stats页面正常加载,概览卡片+月度统计表格
9合同详情/contract/contract-info-detail?id=1页面正常加载,显示表单+明细表格

D-02 字典渲染

#页面字段预期渲染
1合同台账列表合同类型彩色标签:销售合同/采购合同/服务合同/...
2合同台账列表合同性质彩色标签:收入类/支出类/无金额
3合同台账列表合同状态彩色标签:草稿/审批中/已审批/已生效/...
4合同变更列表变更类型彩色标签:金额变更/期限变更/条款变更/...
5合同履约列表履约类型彩色标签:交付/验收/收款/付款/...
6合同详情表单合同类型下拉字典选项完整,与后端一致
7合同详情表单合同性质下拉字典选项完整

D-03 表单校验

#页面操作预期结果
1合同分类新增不填名称直接保存提示"请输入分类名称"
2合同台账新增不填合同名称直接保存提示必填校验
3合同台账新增不选合同类型直接保存提示"请选择合同类型"
4合同变更新增不选关联合同直接保存提示必填校验
5合同配置保存流水号位数输入 0 或负数校验不通过

七、场景 E:跨功能关联验证

验证各子功能之间的数据关联和一致性。

E-01 合同与收付款计划关联

#检查项预期结果
1创建收付款计划时,contractId 不存在返回错误,提示合同不存在
2查询计划传 contractId,验证只返回该合同的计划不会返回其他合同的计划
3计划金额合计 vs 合同总金额无强制一致性约束,但数据应合理

E-02 合同与履约关联

#检查项预期结果
1创建履约记录时,contractId 不存在返回错误
2履约汇总 summary 的已履约金额 = 该合同所有履约记录金额之和数据一致
3合同主表 performanceAmount 与履约汇总一致创建履约记录后自动更新主表

E-03 合同与变更关联

#检查项预期结果
1变更记录的 contractId 指向正确合同GET 变更详情后 contractId 与原合同匹配
2按合同查变更列表只返回该合同的变更,不混入其他合同
3删除合同后查其变更列表变更记录仍存在(软删除不影响变更数据)

E-04 统计数据一致性

#检查项预期结果
1overview.totalCount = 合同台账 page 的 total数量一致
2overview.totalAmount = 所有非草稿合同金额之和金额一致(±精度)
3月度统计各月合计 = overview 总量数量和金额月度累加等于总计
4分类统计各分类合计 = overview 总量数量和金额分类累加等于总计

八、异常与边界测试

F-01 权限控制

#操作预期结果
1不带 Authorization header 调用任意接口返回 401 未授权
2使用无 contract:info:create 权限的用户创建合同返回 403 无权限
3使用无 contract:info:delete 权限的用户删除合同返回 403 无权限

F-02 数据完整性

#操作预期结果
1创建合同时 contractType 传非法值(如 99999)创建成功但字典无法渲染,或后端校验拒绝
2创建合同总金额传负数合理的校验拒绝或允许(视业务设计)
3日期字段传空字符串不报错,日期存为 null
4合同明细行 items 传空数组创建成功,明细行为空
5contractCode 传超长字符串(>64字符)数据库层面截断或报错

F-03 并发与幂等

#操作预期结果
1同时两个请求创建相同 contractCode仅一个成功,另一个返回编号已存在
2同时两个请求更新同一合同最后一次更新生效(乐观锁或覆盖写)

九、测试数据清理

测试完成后,按以下顺序清理测试数据(或使用专用测试租户隔离):

  1. 删除履约记录:DELETE /contract/performance/delete?id=xxx
  2. 删除收付款计划:DELETE /contract/payment-plan/delete?id=xxx
  3. 删除合同变更:DELETE /contract/change/delete?id=xxx
  4. 删除合同(仅草稿状态可删):DELETE /contract/info/delete?id=xxx
  5. 删除合同模板:DELETE /contract/template/delete?id=xxx
  6. 删除合同分类(先删子分类再删父分类):DELETE /contract/category/delete?id=xxx

注意:已提交/已生效的合同不可直接删除,需先终止或通过数据库操作清理。


十、测试检查清单(Checklist)

#检查项场景状态
1合同配置 CRUDA-01
2合同分类树形 CRUDA-02
3合同模板 CRUD + 搜索A-03
4合同创建(含明细行)A-04
5合同编号唯一性A-04.5
6收付款计划 CRUDA-05
7合同提交审批A-06
8合同履约 CRUD + 汇总A-07
9统计分析概览/月度/分类A-08
10采购合同创建 + 提交B-01
11合同变更创建 + 提交B-02
12变更列表按合同过滤B-02.3
13采购合同履约(交付+付款)B-03
14草稿保存 / 修改 / 删除C-01
15列表搜索(编号/名称/类型/状态/乙方/组合)C-02
16Excel 导出C-02.8
17精简列表(下拉选择)C-02.9
18前端各页面路由正常D-01
19字典标签渲染D-02
20表单必填校验D-03
21跨功能数据关联E-01~04
22权限控制F-01
23数据边界F-02
联系我们

获取报价、演示和二开方案

微信咨询二维码

微信咨询

17156169080

添加时备注「RuoYi Office」

在线体验商业版