AutoRpa/PARALLEL_DEV_PLAN.md

14 KiB

状态中心 ↔ 艺赛旗并行开发方案

核心原则:契约驱动,各自独立,最后对接

双方只通过 HTTP 回调契约 交互,这个契约在交接文档里已经明确定义。在对接前,双方各自用假数据/假回调验证自己的逻辑,互不阻塞。


对接契约(双方共同遵守)

基础信息

  • 状态中心地址:联调时给艺赛旗实际 IP,如 http://192.168.x.x:8000
  • 鉴权:所有回调必须带 header X-Agent-Token: <token>(默认 dev-agent-token,上线换正式值)
  • 幂等键:complete 回调可带 idempotencyKey,重发同键不会二次推进

三个回调接口(艺赛旗调状态中心)

1. 节点开始

POST /api/jobs/{jobId}/nodes/{nodeCode}/start
Content-Type: application/json
X-Agent-Token: dev-agent-token

{
  "attemptNo": 1,
  "executorPlatform": "iS-RPA",
  "operator": "agent"
}

2. 节点成功

POST /api/jobs/{jobId}/nodes/{nodeCode}/complete
Content-Type: application/json
X-Agent-Token: dev-agent-token

{
  "attemptNo": 1,
  "executorRunId": "YD-RUN-001",
  "idempotencyKey": "uuid-xxx",
  "businessRefs": {
    "contractSystemNo": "HT2026...",  // 三把钥匙,对应节点必传
    "rebateOrderNo": "FL2026...",
    "m5OrderNo": "M5-xxx",
    "receiptNoticeNo": "SH-xxx"
  },
  "summary": { "orderCount": 12 },
  "artifacts": [
    {
      "artifactType": "SOURCE_EXCEL",
      "storagePath": "/data/jobs/xxx/orders.xlsx",
      "fileHash": "sha256:abc",
      "visibleRoles": ["PURCHASER", "PLANNER"],
      "isMasked": false
    }
  ]
}

返回:{"ok": true, "next_node": "OCR_EXTRACT"} ← 艺赛旗拿到 next_node 继续跑下一节点

3. 节点失败

POST /api/jobs/{jobId}/nodes/{nodeCode}/fail
Content-Type: application/json
X-Agent-Token: dev-agent-token

{
  "attemptNo": 1,
  "errorCode": "SYS_LOGIN_FAIL",  // 见交接文档错误码表
  "errorSummary": "验证码识别失败",
  "retryable": true,              // 系统类填 true,业务类填 false
  "routeRole": "OPS",             // OPS/PLANNER/PURCHASER
  "artifacts": []
}

返回:{"ok": true, "job_status": "FAILED_RETRYABLE"}

必须回传的业务编号(三把钥匙)

节点 必传字段 说明
CONTRACT_CREATE contractSystemNo 合同编号(后续返利、M5靠它串)
REBATE_HEADER rebateOrderNo 返利中心总单号
M5_RECEIPT_NOTICE receiptNoticeNo 收货通知单号(全链终点)

不传或传空,状态中心返回 400 拒绝。

错误码规范(部分,全表见交接文档)

错误码 含义 retryable routeRole
SYS_LOGIN_FAIL 登录失败 true OPS
SYS_PAGE_TIMEOUT 页面超时 true OPS
UI_ELEMENT_NOT_FOUND 页面改版找不到元素 false OPS
BIZ_CONTRACT_DISABLED 供应商合同被禁 false PURCHASER
M5_QC_MISSING M5质管资料缺失 - -
REBATE_DUP_CODE 返利重复编码 false PURCHASER

特殊规则:M5_QC_MISSING 无条件转 FAILED_MANUAL,retryable 填什么都没用。


状态中心这边(你的任务)

阶段1:独立验证(不依赖艺赛旗)

时间:1-2天 目标:后端在真 MySQL 上用假回调跑通全链

任务

  1. 环境准备

    • Docker 起 MySQL 8,执行 schema.sql 建库。
    • 配 MYSQL_DSN,起后端服务。
    • 前端 npm run dev 起来。
  2. 用假回调跑通一单

    • 方式1:用 curl 按顺序调回调接口。
    • 方式2:用前端"开发:节点回调模拟"区域的按钮。
    • 路径:建单 → ORDER_FETCH start/complete → PRODUCT_MATCH run(有 MULTI) → 人工确认 → SOURCE_ADD 人工提交 → CONTRACT_CREATE complete(带合同编号) → ... → ARCHIVE_JOB。
    • 验证点:
      • job 状态正确推进(PENDING → RUNNING → WAITING_USER → ...)。
      • 业务编号正确落库(合同编号、返利总单号、M5单号、收货通知单号)。
      • job_node 每个节点有历史记录,attempt_no 正确。
      • user_task 在该创建时创建,提交后关闭。
      • job_artifact 证据落库。
      • 条件节点(OCR_EXTRACT/SOURCE_ADD)正确跳过或执行。
  3. 发现并修复真实问题

    • SQL 语法问题(如 MySQL 8 的保留字冲突)。
    • JSON 列序列化问题(Python dict → MySQL JSON → 前端拿到的是对象还是字符串)。
    • 事务回滚是否正确。
    • datetime 字段格式(MySQL 存的 YYYY-MM-DD HH:MM:SS,前端拿到的格式)。
    • 幂等逻辑是否真的防重(重复 complete 同一节点,状态不会乱)。
  4. 记录真实 API 响应

    • 把 GET /api/jobs/{id} 的完整响应存下来,给 UI 优化做参考。

产出

  • ✅ 一个能在真 MySQL 上跑通全链的后端(用假回调验证)。
  • ✅ 一份真实响应示例 + 发现的问题清单。
  • ✅ 前端能正常展示真实数据(不再依赖 demoJobDetailMap)。

阶段2:优化与补全(不依赖艺赛旗)

时间:2-3天 目标:UI 优化 + 补缺失接口 + 加调度重试

任务

  1. UI 优化

    • 按刚才的方案,分区 + 可折叠 + 调试开关。
    • 基于阶段1 的真实响应,确保所有字段正确展示。
  2. 补缺失接口

    • GET /api/jobs/{id}/match/unmatched:返回该 job 未命中的订单行列表。
    • 其他小接口(如果阶段1 发现有遗漏)。
  3. 调度与重试(任务6)

    • 定时建单:每天早上扫前一天订单。
    • 系统类错误自动重试(FAILED_RETRYABLE 状态的 job,重试 1-2 次)。
    • 超时升级:合同审批超时、人工待办超时转 OPS。

产出

  • ✅ 优化后的前端(信息分层清晰,调试模式可开关)。
  • ✅ 完整的接口(验收点名的都实现)。
  • ✅ 调度器能定时触发建单和重试。

阶段3:准备对接(等艺赛旗阶段2 完成)

时间:半天 目标:给艺赛旗提供联调环境

任务

  1. 部署联调环境

    • 把后端部署到艺赛旗能访问的机器(或你本机开端口映射)。
    • 给艺赛旗提供:基础地址(如 http://192.168.x.x:8000) + 正式 X-Agent-Token。
  2. 准备测试数据

    • 在库里建几个不同类型的 job:
      • 医药城线上单(会跳过 OCR_EXTRACT)。
      • 线下单(会走 OCR_EXTRACT)。
      • 有对码 MULTI 的单。
      • 缺货源的单(会走 SOURCE_ADD)。
    • 每个 job 停在 ORDER_FETCH 节点,等艺赛旗来调 start/complete 推进。
  3. 写联调检查表

    • 逐节点列验收点,双方对着检查表勾。

产出

  • ✅ 一个可供艺赛旗调用的联调环境。
  • ✅ 测试数据 + 联调检查表。

艺赛旗那边(你要转述给他们)

阶段1:独立开发(不依赖状态中心)

时间:2-3周(他们的活重) 目标:每个节点的页面自动化都能独立跑通

任务

  1. 理解回调契约

    • 仔细读 给艺赛旗的开发交接.md。
    • 确认三个回调接口的字段、错误码表。
  2. 逐节点开发页面自动化

    • 节点顺序(他们的优先级):

      1. ORDER_FETCH(订单获取):登录医药城/小药药 → 导出 Excel → 存证据。
      2. CONTRACT_CREATE(合同建单):登录合同系统 → 填表 → 上传 PDF(医药城) → 提交送审 → 拿到合同编号。
      3. REBATE_HEADER(返利总单):登录返利中心 → 按合同编号查总单 → 填必填项 → 保存 → 拿到返利总单号。
      4. REBATE_IMPORT(返利细单):下载模板 → 填字段 → 上传 → 读成功/失败行。
      5. REBATE_SUBMIT(返利送审):点"提交送审"按钮。
      6. M5_CREATE_ORDER(M5建单):桌面自动化 → 录单 → 停,不保存。
      7. CONTRACT_APPROVE_WAIT(合同审批):定时查审批状态(到点被状态中心扫到时才查一次)。
    • 每个节点独立验证:

      • 不调状态中心,在自己环境里跑(比如用测试账号登录真实系统,手工给初始数据)。
      • 验证能拿到业务编号(合同编号、返利总单号等)。
      • 验证错误情况能识别出正确的错误码(如登录失败是 SYS_LOGIN_FAIL,合同被禁是 BIZ_CONTRACT_DISABLED)。
  3. 本地模拟回调

    • 自己起个假的状态中心(或者直接用 curl 打印 JSON),验证回调 payload 格式对不对。
    • 示例(他们自己写个小脚本验证):
      # 假的状态中心 mock.py
      from flask import Flask, request, jsonify
      app = Flask(__name__)
      
      @app.route('/api/jobs/<job_id>/nodes/<node_code>/complete', methods=['POST'])
      def complete(job_id, node_code):
          data = request.json
          print(f"收到 {node_code} complete:", data)
          # 检查必传字段
          if node_code == 'CONTRACT_CREATE' and not data.get('businessRefs', {}).get('contractSystemNo'):
              return jsonify({"error": "缺少合同编号"}), 400
          return jsonify({"ok": True, "next_node": "下一节点"})
      
      app.run(port=8000)
      

产出

  • ✅ 每个节点的页面自动化脚本(iS-RPA 流程)。
  • ✅ 能正确识别各种错误并返回对应错误码。
  • ✅ 能拿到三把钥匙(合同编号、返利总单号、收货通知单号)。

阶段2:准备对接(等状态中心阶段3 准备好)

时间:1天 目标:改成调真实状态中心接口

任务

  1. 获取联调环境信息

    • 从状态中心拿到:基础地址 + X-Agent-Token。
  2. 改造回调逻辑

    • 把阶段1 的假回调改成调真实状态中心接口。
    • 关键:拿到 complete 返回的 next_node,继续跑下一节点(不要自己写死顺序)。
  3. 小范围试跑

    • 先跑一个最简单的节点(如 ORDER_FETCH),验证回调能调通、状态中心能正确推进。

产出

  • ✅ 能调通状态中心回调接口的 RPA 脚本。

联调阶段(双方一起)

时间:3-5天 目标:端到端跑通一单真实流程

任务

  1. 按节点逐个验证

    • 顺序:ORDER_FETCH → (OCR_EXTRACT) → PRODUCT_MATCH(状态中心内部) → (SOURCE_ADD 人工) → CONTRACT_CREATE → ...
    • 每个节点验证:
      • RPA 能正确调 start/complete/fail。
      • 状态中心正确推进到下一节点或转人工。
      • 业务编号正确落库。
      • 证据正确存储。
  2. 跑完整链

    • 医药城线上单(跳过 OCR)。
    • 线下单(走 OCR)。
    • 有对码 MULTI 的单(走人工确认)。
    • 缺货源的单(走 SOURCE_ADD 人工)。
    • 合同审批等待(定时查几次,验证不会死等)。
  3. 异常场景

    • 登录失败 → 重试。
    • 页面改版找不到元素 → 转 OPS。
    • M5 质管缺失 → 直接 FAILED_MANUAL,不重试。
    • 返利重复编码 → 该单挂起,整批继续。
  4. 对照验收规范逐条勾

    • 打开 实施与验收规范.md,每个节点的代码验收 + 业务验收两栏逐条过。

产出

  • ✅ 一个能端到端跑通的完整流程(从订单获取到归档)。
  • ✅ 验收报告(哪些通过,哪些有问题)。

时间线(并行开发)

第1周                          第2周                          第3周
状态中心  │────阶段1────│───阶段2───│──阶段3──│────联调────│
         真MySQL跑通    UI优化+补全  准备环境   与艺赛旗对接
           (1-2天)       (2-3天)    (半天)      (3-5天)

艺赛旗    │────────────阶段1────────────│─阶段2─│────联调────│
         独立开发各节点页面自动化         改真回调  与状态中心对接
              (2-3周)                   (1天)     (3-5天)

关键点:

  • 前两周双方完全独立,互不阻塞。
  • 状态中心先做完(1周内),等艺赛旗追上。
  • 艺赛旗开发周期长(页面自动化细节多),但不影响状态中心进度。
  • 第3周开始联调,双方都已在各自环境验证过,对接就是走形式。

给艺赛旗的检查清单(转述)

在开始联调前,艺赛旗必须自证能做到:

功能检查

  • 能登录医药城/小药药/合同系统/返利中心/M5,并正确处理验证码/超时。
  • 能导出订单 Excel 并存到指定路径。
  • 能建合同、上传 PDF(医药城)、拿到合同编号。
  • 能在返利中心按合同编号查总单、填表、拿到返利总单号。
  • 能下载返利细单模板、填字段、上传、读成功/失败行。
  • 能点返利送审按钮。
  • 能用桌面自动化在 M5 录单(但不保存)。
  • 能定时查合同审批状态(不是连续轮询,是到点查一次)。

回调检查

  • 知道何时调 start、何时调 complete、何时调 fail。
  • complete 时能正确带 businessRefs(三把钥匙对应节点必传)。
  • fail 时能正确识别错误码(SYS_* vs BIZ_*,retryable 填对)。
  • 拿到 next_node 后能继续跑下一节点(不写死顺序)。
  • 所有回调都带 X-Agent-Token header。

异常检查

  • 登录失败时返回 SYS_LOGIN_FAIL,retryable=true。
  • 页面改版找不到元素时返回 UI_ELEMENT_NOT_FOUND,retryable=false,routeRole=OPS。
  • M5 质管缺失时返回 M5_QC_MISSING(状态中心会直接转 FAILED_MANUAL,不重试)。
  • 供应商合同被禁时返回 BIZ_CONTRACT_DISABLED,retryable=false,routeRole=PURCHASER。

总结

你现在要做的:

  1. 马上开始阶段1(真 MySQL 跑通),1-2天搞定。
  2. 接着做阶段2(UI 优化 + 补全),2-3天搞定。
  3. 然后做阶段3(准备联调环境),半天搞定。
  4. 这时你这边已经全部做完,等艺赛旗追上(他们要 2-3 周)。

艺赛旗要做的(你转述给他们):

  1. 阶段1:独立开发各节点页面自动化,2-3周。期间不需要状态中心配合,自己用假数据验证。
  2. 阶段2:拿到状态中心联调环境信息后,改成调真实接口,1天。
  3. 联调阶段:双方一起按检查表逐条验收,3-5天。

不会互相阻塞:你 1 周内做完你的,艺赛旗 2-3 周做完他们的,最后 3-5 天一起联调。


要我把这份文档发给艺赛旗吗?或者你先看看有没有要调整的。