# AutoRpa 洁达 RPA。当前主线是**订单中心入站**(`rpa_oms`)和**选品班次**(`选品流程/`):收件落 Oracle,请求里不跑选品;选品作业另起进程捞 `deal_flag=0`。采购主链(状态中心编排、艺赛旗/Selenium 点合同系统)仍在仓库里,按问题打开对应行。 智力用在**定落点、想清楚对错**;速度和 token 靠下面这张地图定点打开,禁止用扫仓代替思考。改对应了,反工和消耗都会少。 ## 怎么干活 1. **先定落点**(不开文件):哪个函数、成功长什么样(哪条 ACCEPT / 哪个点名用例)、这次不碰什么。方向说不清就先问,不要靠翻目录找感觉。 2. **只在落点上想透**:规则、边界、会不会拿错号/写错状态。打开文件是为了验证落点,不是再想要不要改别处。 3. **薄验收就停**:控制台 `ACCEPT SUMMARY` 或一条点名用例。过了收工。 问「法子 / 怎么优化」先答方案;用户说「改 / 重构 / 收口」再动代码。一件事一个会话,换任务 `/new`。 ## 项目地图 按问题打开一行,不要 `list_dir` 根目录。 | 问题 | 打开 | 验收 | | --- | --- | --- | | 接口1 收件契约 | `rpa_oms/app/inbound/sales_goods.py`、`envelope.py` | `rpa_oms/tests/test_sales_goods_receive.py::点名` | | 接口1 Oracle 落表 | `rpa_oms/app/inbound/oracle_repo.py` | `rpa_oms/tests/test_oracle_repo.py::点名` | | 接口1 入口 / 鉴权 | `rpa_oms/app/main.py`、`auth.py` | 同上;真库见 `rpa_oms/README.md` Windows 段 | | 选品规则 / 拆量 | `选品流程/rules.py`、`pipeline.py` | `选品流程/tests/test_pipeline.py::test_split_across_malls_is_success` | | 选品班次落表 | `选品流程/job.py`、`persist.py`、`repo.py` | `选品流程/tests/test_job.py::test_job_searches_barcode_not_approval_no` | | 合同页面步骤 S02–S13 | `rpa_yisaiqi/contract_flow_steps.py` 里对应函数 | `ACCEPT SUMMARY` 或 `rpa_yisaiqi/screenshots/CONTRACT_CREATE/ACCEPT.txt` | | 合同入参 / 客商草稿 | `rpa_yisaiqi/contract_draft.py` | `state_center/tests/test_yisaiqi_contract_draft.py::点名` | | 节点入口、回调 complete | `rpa_yisaiqi/contract_create_node.py`、`callback_client.py` | 回调 JSON 含 `contractSystemNo` | | 浏览器适配 | `rpa_yisaiqi/apa_browser_adapter.py` | `rpa_yisaiqi/tests/test_apa_browser_adapter.py::点名` | | 文字验收 / 截图策略 | `rpa_yisaiqi/runtime/accept.py` | 只读 `ACCEPT.txt`,禁止读 png | | 艺赛旗画布代码块 | `rpa_yisaiqi/build_multinode_seq.py`(源)→ `studio/`(编译产物) | 未说画布不要改这两处 | | 跨节点共享状态 | `rpa_yisaiqi/_flow_state.py` | — | | 状态机 / API | `state_center/app/main.py`、`web_state_machine.py`、`match_engine.py` | `state_center/tests/test_web_state_machine.py::点名` 等 | | 前端看板 | `state_center_web/src/stateMachine.ts`、`App.tsx` | 浏览器点一遍相关页 | | 一键启动(状态中心) | `scripts/dev.py start` | 状态中心 :8000,前端 :5173 | | 节点业务规则(点名一节) | `资料/采购主链RPA一期实施与验收规范.md` | 禁止通读 `资料/`、`docs/` | 禁止打开:`node_modules/`、`chrome-profile/`、任何 png。Chrome 用户目录只在仓库外 `D:\work\rpa-chrome-profile`。Oracle 密码放本机 `rpa_oms/.env`(选品空缺时复用);商城账号放 `选品流程/.env`。都已 gitignore,不要写进仓库、README、示例 JSON,不要 `git add` / commit / push。 ## 接口1 落点(订单中心) 订单中心四接口,本期只开放接口 1:销售商品对码数据接收。`POST /api/oms/v1/sales-goods`,鉴权 header `X-Oms-Token`(`OMS_INBOUND_TOKEN`)。落表 `rpa_sales_goods_mapping_data`,`deal_flag=0`,等选品作业捞;**请求里不跑选品**。 默认 `OMS_REPO=oracle`,本机连不上库用 `OMS_REPO=memory`。服务端口 **8001**,不走 `scripts/dev.py`。 | 步 | 函数 | 要点 | | --- | --- | --- | | 信封 | `parse_envelope` | 缺 `data` / 空数组 / 超过 100 条:整包 422,一条都不落 | | 逐条校验 | `receive_sales_goods` | 入参 camelCase,落表 snake_case;长度跟 VARCHAR2 | | 鉴权 | `token_ok` | 未配 token 一律失败 | | 落表 | `OracleSalesGoodsRepo.insert` | `fid` 由序列触发器生成,INSERT 不绑这一列 | | 幂等 | 同 `omsId` | 已存在 → `DUPLICATE`,不更新、不重跑 | | 同批冲突 | 同一 POST 里 `omsId` 再现 | 后一条 `CONFLICT`,只落第一条 | | 字段不过 | `_parse_row` | `REJECTED`,不入库 | | 混批 | `post_sales_goods` | 逐条有成功/重复/拒绝时 HTTP 仍 200,看 `results[].resultCode` | `omsId` / `saleQty` / `planPurchaseQty` 必须是 JSON 整数,不把 `"10"` 当 10。Windows 连真库测;Instant Client 位数与 Python 一致。 验收(内存、不连库):`cd rpa_oms` → `uv run pytest tests/test_sales_goods_receive.py::点名 -q`。真库:`GET /health` 后把 `examples/sales_goods_batch.json` POST 两次(第一次两条 `ACCEPTED`,第二次两条 `DUPLICATE`)。 修接口1不要顺手改 `state_center/`、`rpa_yisaiqi/`、`选品流程/`。接口 2–4 未开放,不要先写。 ## 选品落点 班次作业在 `选品流程/`,不在接口 1 请求里跑。从表 1 领 `deal_flag=0`,按**条形码**搜 1 号药城 / 药帮忙,两平台合并后按四级仓序贪心拆量,写入表 2。凑齐才落成功行;凑不齐不落部分成功。 口径:`docs/superpowers/specs/2026-10-02-selection-split-allocation-design.md`。 | 步 | 函数 | 要点 | | --- | --- | --- | | 领取 | `claim_pending` | `deal_flag` 0→3;中途崩溃停在 3,改回 0 再跑 | | 规则 | `allocate` / `run_selection` | 自营仓全称匹配、毛利 ≥ 4%、效期 ≥ 12 月;同仓只留低价;按仓序拆量 | | 落表 | `build_result` + `save_result` | 成功每仓一行 `status=1`,合计=计划量;`push_status=0` | | 库存不足 | `KIND_BUSINESS_FAIL` | 两边都搜到但合计不够:`deal_flag=2`,该 `omsId` 不重跑 | | 对端故障 | `KIND_SYSTEM_FAIL` | 一边故障且剩下的凑不齐:可把 `deal_flag` 改回 0;禁止写成库存不足 | 湖南壹号、甘肃壹号云不在自营集合。不加购,不推接口 2。 验收:`cd 选品流程` → `uv run pytest tests/test_pipeline.py::test_split_across_malls_is_success -q`(杭州 3 + 广东 7 = 计划 10)。 ## CONTRACT_CREATE 落点 `run_contract_create_flow` 串起来;修一步只打开对应函数。 | 步 | 函数 | 要点 | | --- | --- | --- | | S02 打开 | `open_contract_system` | `http://contract-test.gzmpc.com:8080/` | | S03 登录 | `login_contract_system` | `test002` / `1` | | S04–S05 起草 | `enter_contract_create`、`select_contract_template` | 直达 `FORM_PAGE_URL`,不要点 SPA 菜单 | | S06 签约方 | `fill_contract_signatory_info` | 客商 `DW0100046361` / `重庆亿昊药业有限公司` | | S07 基础 | `fill_contract_basic_info` | 标题 `_expected_title` | | S08 金额日期 | `fill_contract_amount_and_dates` | 签约日=订单日 | | S09 货品 | `fill_contract_goods_lines` | 弹窗按操作码搜 | | S10 付款 | `fill_contract_payment_info` | | | S11 PDF | `upload_contract_document_if_needed` | 仅 YYC 传合并 PDF | | S12 提交 | `submit_contract_for_approval` | 成功后**不要等详情页** | | S13 合同号 | `read_contract_number` | 回「我的合同」,`fdId` > 标题+客户编码;禁止盲取最新一条 | 成功路径默认不截图(`RPA_SCREENSHOT=always` 才全截)。页面等待用 `wait_for_text` / `wait_for_element`,不要固定长睡。 ## 返利中心及之后 合同审批通过后才进这一段。三把钥匙:`contractSystemNo` → `rebateOrderNo` → `receiptNoticeNo`。页面步骤未建,联调 `rpa_yisaiqi/runners/mock.py`。开做时按合同同款:一个节点一份 `*_flow_steps.py`,验收只看 ACCEPT / 点名用例。 | 节点 | 谁做 | 要回传 | 页面要做什么(尚未拆函数) | | --- | --- | --- | --- | | `REBATE_HEADER` | RPA | `rebateOrderNo` | 登录返利中心 → 按合同编号查总单 → 填必填 → 保存拿总单号 | | `REBATE_IMPORT` | RPA | 成功/失败行 | 下模板 → 按字段填 Excel → 上传 → 读导入结果 | | `REBATE_SUBMIT` | RPA | `submitted` | 点提交送审 | | `M5_CREATE_ORDER` | RPA 桌面端 | `m5OrderNo` | 录单后**停、不保存**。`M5_QC_MISSING` 必须识别准(直接转人工、不重试) | | `M5_MANUAL_CONFIRM` | 采购 | — | 人在 M5 里保存签订;前端任务推进 | | `M5_RECEIPT_NOTICE` | 采购 | `receiptNoticeNo` | 人填收货通知单号,全链终点钥匙 | | `ARCHIVE_JOB` | 状态中心 | — | 无页面 | 调度:`rpa_yisaiqi/agent.py`。人节点在 `HUMAN_NODES`。不要连续轮询审批;返利段开始前的 `CONTRACT_APPROVE_WAIT` 约 30 分钟查一次。 ## 验收 - 接口1:点名 `rpa_oms/tests/test_sales_goods_receive.py` 或 `test_oracle_repo.py`;禁止为「显得全面」跑整包再去连真库。 - 选品:点名 `选品流程/tests/test_pipeline.py::test_split_across_malls_is_success` 或 `test_rules.py::test_margin_exactly_4_percent_passes`。 - 合同页:只读控制台 `ACCEPT` 或 `screenshots/<节点>/ACCEPT.txt`。 - 单测只跑点名用例,例如 `state_center/tests/test_yisaiqi_contract_flow_steps.py::test_read_contract_number_falls_back_to_my_contracts_list`。禁止跑整份该文件。 - 该文件已打掉 `time.sleep`;不要再拿全量带睡的套件当回归。 ## 不要 - 不要扫根目录,不要通读 `资料/`、`docs/`。需要背景就点名打开一节。 - 不要顺手改 `studio/`、`build_multinode_seq.py`(画布任务除外)。 - 不要把 Oracle 密码写进仓库、README、示例 JSON。 - 不要在接口1 请求路径里跑选品。 - 不要为「显得全面」多开文件、重跑、看图。落点外的改动会制造反工。