Files
ctms/docs/setup-config-api.md
T

5.7 KiB
Raw Blame History

立项配置接口说明(Excel 导入导出版)

1. 概览

  • 基础路径: /api/v1/studies/{study_id}/setup-config
  • 数据作用域: 单项目唯一配置(study_setup_configs.study_id 唯一约束)
  • 存储格式: JSONB(字段结构与前端 SetupConfigDraft 对齐)
  • 并发控制: 乐观锁(expected_version
  • 发布机制: 草稿/已发布(publish_status
  • 前端视图语义:
    • 草稿视图: 当前草稿可编辑
    • 发布预览: 当前草稿只读预览(不直接读取 published_data
    • published_data: 用于发布快照、差异比较与版本能力
    • published_project_snapshot: 发布时的项目基础信息快照(用于“项目信息差异”判定)

2. 权限矩阵

  • GET /setup-config
    • 允许: 项目成员、管理员
  • PUT /setup-config
    • 允许: PM、ADMIN
    • 限制: 项目锁定时返回 403
  • POST /setup-config/publish
    • 允许: PM、ADMIN
    • 限制: 项目锁定时返回 403
  • GET /setup-config/export-excel
    • 允许: 项目成员、管理员
  • POST /setup-config/import-excel
    • 允许: PM、ADMIN
    • 限制: 项目锁定时返回 403

3. 数据结构

3.1 请求体(保存)

{
  "expected_version": 3,
  "data": {
    "projectMilestones": [
      {
        "id": "m1",
        "name": "首例入组",
        "planDate": "2026-03-01",
        "owner": "项目经理",
        "remark": "",
        "status": "未开始"
      }
    ],
    "enrollmentPlan": {
      "totalTarget": 100,
      "startDate": "2026-02-01",
      "endDate": "2026-12-31",
      "monthlyGoalNote": "按月拆解",
      "stageBreakdown": "阶段1/2/3"
    },
    "siteMilestones": [],
    "siteEnrollmentPlans": [],
    "monitoringStrategies": [],
    "centerConfirm": []
  }
}

3.2 响应体(GET/PUT/PUBLISH/IMPORT-EXCEL

{
  "id": "f0ac2fca-5fd3-470e-8e7e-2ded2b8f0f77",
  "study_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
  "version": 6,
  "publish_status": "PUBLISHED",
  "data": {
    "projectMilestones": [],
    "enrollmentPlan": {
      "totalTarget": 120,
      "startDate": "2026-02-01",
      "endDate": "2026-12-31",
      "monthlyGoalNote": "",
      "stageBreakdown": ""
    },
    "siteMilestones": [],
    "siteEnrollmentPlans": [],
    "monitoringStrategies": [],
    "centerConfirm": []
  },
  "published_data": null,
  "published_project_snapshot": {
    "code": "DEMO-CTMS",
    "name": "演示项目",
    "project_full_name": "演示项目全称",
    "sponsor": "",
    "protocol_no": "",
    "lead_unit": "",
    "principal_investigator": "",
    "main_pm": "",
    "research_analysis": "",
    "research_product": "",
    "control_product": "",
    "indication": "",
    "research_population": "",
    "research_design": "",
    "plan_start_date": "2026-02-01",
    "plan_end_date": "2026-12-31",
    "planned_site_count": 12,
    "planned_enrollment_count": 120,
    "summary_note": "",
    "objective_note": "",
    "status": "DRAFT",
    "visit_interval_days": null,
    "visit_total": null,
    "visit_window_start_offset": null,
    "visit_window_end_offset": null
  },
  "saved_by": "11111111-1111-1111-1111-111111111111",
  "saved_by_name": "System Admin",
  "published_by": null,
  "published_by_name": null,
  "published_at": null,
  "created_at": "2026-02-09T01:30:00.000000Z",
  "updated_at": "2026-02-09T02:11:13.000000Z"
}

4. 接口定义

4.1 GET 获取配置

GET /api/v1/studies/{study_id}/setup-config
Authorization: Bearer <token>

4.2 PUT 保存配置(草稿)

PUT /api/v1/studies/{study_id}/setup-config
Authorization: Bearer <token>
Content-Type: application/json

4.3 POST 发布配置

POST /api/v1/studies/{study_id}/setup-config/publish
Authorization: Bearer <token>
Content-Type: application/json

4.4 GET 导出 Excel

GET /api/v1/studies/{study_id}/setup-config/export-excel
Authorization: Bearer <token>

说明:

  • 返回 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  • 文件可直接作为导入模板继续回灌

4.5 POST 导入 Excel

POST /api/v1/studies/{study_id}/setup-config/import-excel
Authorization: Bearer <token>
Content-Type: multipart/form-data

表单字段:

  • file: .xlsx 文件(必填)
  • expected_version: 当前配置版本(可选,建议携带)

说明:

  • 导入会覆盖当前草稿并自增版本。
  • 写入审计事件: IMPORT_SETUP_CONFIG_EXCEL

5. 错误码与典型场景

  • 400 BAD REQUEST
    • 上传文件非 .xlsx
    • Excel 解析失败
  • 403 FORBIDDEN
    • 非 PM/ADMIN 导入/保存/发布
    • 项目已锁定
  • 404 NOT FOUND
    • study 不存在
  • 409 CONFLICT
    • expected_version 与服务端不一致
  • 422 UNPROCESSABLE ENTITY
    • Excel 数据通过解析后,业务字段校验失败

6. 联调脚本(curl

  • 脚本路径: docs/setup-config-curl-smoke.sh
  • 使用方式:
chmod +x docs/setup-config-curl-smoke.sh
BASE_URL=http://localhost \
EMAIL=admin@example.com \
PASSWORD=admin123 \
STUDY_ID=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa \
bash docs/setup-config-curl-smoke.sh

7. Postman 联调集合

  • Collection: docs/postman/setup-config.postman_collection.json
  • Environment: docs/postman/local.postman_environment.json

8. 后端烟雾测试(非 pytest

docker compose up -d db backend
docker compose exec -T backend python scripts/smoke_setup_config.py

9. 监控埋点(4xx/5xx

  • 中间件统计以下接口:
    • GET /api/v1/studies/{study_id}/setup-config
    • PUT /api/v1/studies/{study_id}/setup-config
    • POST /api/v1/studies/{study_id}/setup-config/publish
    • GET /api/v1/studies/{study_id}/setup-config/export-excel
    • POST /api/v1/studies/{study_id}/setup-config/import-excel