499 lines
18 KiB
Markdown
499 lines
18 KiB
Markdown
# 洁达选品:改造商城查价工程(详细方案)
|
||
|
||
> Windows 按本文改同事原工程。概要口径见 [2026-09-14-jieda-procure-crawler-overview.md](./2026-09-14-jieda-procure-crawler-overview.md)。
|
||
> 不要改仓库一期状态机,不要把 ±10% 比价逻辑留在主流程里。
|
||
|
||
| 文档属性 | 内容 |
|
||
| --- | --- |
|
||
| 版本 | V1.0 |
|
||
| 日期 | 2026-09-14 |
|
||
| 执行环境 | Windows + 艺赛旗 Python 应用(`isa-rpa` + `uv`) |
|
||
| 基线代码 | 同事工程 `main.py`(约 907 行) |
|
||
| 建议工作副本 | 拷一份到本仓库 `rpa_yisaiqi/procure_mall/`,或 Windows 本地独立目录;不要在原 zip 上直接当唯一真源 |
|
||
|
||
---
|
||
|
||
## 1. 原工程:留什么、删什么、补什么
|
||
|
||
### 1.1 原样保留(不要重写)
|
||
|
||
| 函数 / 能力 | 作用 |
|
||
| --- | --- |
|
||
| `SecretClient` + `YAOEX_SECRET_NAME` / `YBM_SECRET_NAME` | 密码箱登录 |
|
||
| `get_yaoex_auth` / `ensure_yaoex_logged_in` | 1 号药城登录,抽 `token / userId / buyerCode` |
|
||
| `get_ybm_cookies` / `ensure_ybm_logged_in` | 药帮忙登录,抽 cookie |
|
||
| `build_yaoex_search_request` / `query_yaoex_products` | `homeSearchList`,`keyword=批准文号`,`per=20`,`deadLineStart=12` |
|
||
| `decrypt_yaoex_price` / `build_yaoex_price_decrypt_key` | 价格 AES 解密 |
|
||
| `build_ybm_search_payload` / `query_ybm_products` | `list-products`,`queryWord=批准文号`,`isThirdCompany=0`,`isEffectPeriodOverOneYear=1` |
|
||
| `post_json_with_retry` | 3 次重试 |
|
||
| 按批准文号缓存 | 同一文号不打两次 |
|
||
|
||
搜索接口:
|
||
|
||
- 1 号药城:`POST https://gateway-b2b.fangkuaiyi.com/home/search/homeSearchList`
|
||
- 药帮忙:`POST https://www.ybm100.com/new-front/search/list-products`
|
||
|
||
字段映射继续用原代码:
|
||
|
||
| 结果字段 | 1 号药城 | 药帮忙 |
|
||
| --- | --- | --- |
|
||
| 平台索引ID | `spuCode` | `productInfo.skuId` |
|
||
| 平台名称 | `shortName` | `productInfo.showName` |
|
||
| 平台规格 | `spec` | `productInfo.spec` |
|
||
| 平台价格 | `decrypt(price)` | `price`,空则 `fob`;库存 0 时价当 0 |
|
||
| 效期 | `deadLine` | `productInfo.nearEffect` |
|
||
| 商家 | `vendorName` | `productInfo.shopName` |
|
||
| 库存 | `stockCount` | `productInfo.availableQty` |
|
||
|
||
### 1.2 必须删除或停用
|
||
|
||
- `is_in_purchase_price_band`
|
||
- `filter_rows_by_purchase_price_band`
|
||
- `main()` 里「价格区间过滤后总行数」那段
|
||
- 把全部候选行当最终输出
|
||
|
||
### 1.3 必须新增
|
||
|
||
- 选品规则引擎(两平台共用)
|
||
- 按行决策:每行每平台 0 或 1 个仓
|
||
- 加购适配器(接口优先,页面兜底)
|
||
- `--dry-run` / `--limit` / `--platform`
|
||
- 新结果表(结论 + 原因,不再是比价明细大表)
|
||
|
||
---
|
||
|
||
## 2. 建议拆文件
|
||
|
||
原 `main.py` 已 900 行,不要再往里堆加购和规则。Windows 按下列拆;若艺赛旗工程限制只能单文件,也必须把规则和加购写成独立函数,禁止写进 `query_*`。
|
||
|
||
```text
|
||
procure_mall/
|
||
pyproject.toml # 沿用原工程
|
||
main.py # 只编排:读入 → 登录 → 循环行 → 写结果
|
||
search_yaoex.py # 从 main.py 搬登录+查询+解密
|
||
search_ybm.py # 从 main.py 搬登录+查询
|
||
http_util.py # post_json_with_retry 等
|
||
rules.py # 合格判定 + 仓库排序
|
||
cart_yaoex.py # 1 号药城加购
|
||
cart_ybm.py # 药帮忙加购
|
||
io_excel.py # 读输入、写结果
|
||
tests/test_rules.py # 规则单测,不连商城
|
||
```
|
||
|
||
`main.py` 目标骨架:
|
||
|
||
```python
|
||
def main() -> None:
|
||
args = parse_args() # --dry-run 默认 True;--limit N;--platform all|yaoex|ybm
|
||
rows = load_input_rows(args.input_path)
|
||
if args.limit:
|
||
rows = rows[: args.limit]
|
||
|
||
yaoex_auth = asyncio.run(get_yaoex_auth()) if args.platform in ("all", "yaoex") else None
|
||
ybm_cookies = asyncio.run(get_ybm_cookies()) if args.platform in ("all", "ybm") else None
|
||
|
||
decisions = []
|
||
for purchase in rows:
|
||
if yaoex_auth is not None:
|
||
decisions.append(run_one_platform(purchase, "1号药城", yaoex_auth, dry_run=args.dry_run))
|
||
if ybm_cookies is not None:
|
||
decisions.append(run_one_platform(purchase, "药帮忙", ybm_cookies, dry_run=args.dry_run))
|
||
|
||
write_decision_file(decisions)
|
||
```
|
||
|
||
单行单平台:
|
||
|
||
```python
|
||
def run_one_platform(purchase, mall_name, auth, dry_run=True) -> dict:
|
||
try:
|
||
candidates = search_candidates(mall_name, auth, purchase["批准文号"])
|
||
except Exception as exc:
|
||
return decision(purchase, mall_name, status="FAILED", reason=f"QUERY_FAILED:{exc}")
|
||
|
||
picked, rejected = select_warehouse(candidates, purchase)
|
||
if picked is None:
|
||
return decision(purchase, mall_name, status="SKIPPED", reason=rejected_summary(rejected), raw=candidates)
|
||
|
||
if dry_run:
|
||
return decision(purchase, mall_name, status="ADDED", reason="DRY_RUN", picked=picked)
|
||
|
||
try:
|
||
cart_ref = add_to_cart(mall_name, auth, picked, qty=purchase["采购数量"])
|
||
except Exception as exc:
|
||
return decision(purchase, mall_name, status="FAILED", reason=f"CART_FAILED:{exc}", picked=picked)
|
||
|
||
return decision(purchase, mall_name, status="ADDED", reason="CART_OK", picked=picked, cart_ref=cart_ref)
|
||
```
|
||
|
||
查询失败不得改成 SKIPPED。
|
||
|
||
---
|
||
|
||
## 3. 输入 / 输出
|
||
|
||
### 3.1 输入 Excel(改模板,不要沿用只有采购价格的比价模板)
|
||
|
||
路径建议:`桌面/福建商城选品测试/选品输入.xlsx`
|
||
第一行表头,从第 2 行起数据。
|
||
|
||
| 列名 | 必填 | 说明 |
|
||
| --- | --- | --- |
|
||
| 行号 | 否 | 没有则按 Excel 行号 |
|
||
| 批准文号 | 是 | 查询关键字;空行跳过 |
|
||
| 销售价格 | 是 | 毛利基准。缺或无法转数字 → 该行两平台都 SKIPPED,原因 `NO_SALE_PRICE` |
|
||
| 采购数量 | 是 | 库存门槛和加购数量。缺或 ≤0 → SKIPPED,原因 `NO_QTY` |
|
||
| 通用名 | 否 | 回填 |
|
||
| 规格 | 否 | 回填,不参与匹配 |
|
||
| 生产厂家 | 否 | 回填,不参与匹配 |
|
||
|
||
本期**不要用采购价格做合格判断**。模板里可以留着采购价格列,规则引擎忽略它。
|
||
|
||
`--limit 5` 只跑前 5 条有效行。
|
||
|
||
### 3.2 输出 Excel
|
||
|
||
路径:`桌面/福建商城选品测试/结果/选品结果_YYYYMMDD_HHMMSS.xlsx`
|
||
一行 = 一个输入行 × 一个平台。
|
||
|
||
| 列名 | 说明 |
|
||
| --- | --- |
|
||
| 行号 | 输入行 |
|
||
| 批准文号 | |
|
||
| 通用名 | |
|
||
| 销售价格 | |
|
||
| 采购数量 | |
|
||
| 商城 | `1号药城` / `药帮忙` |
|
||
| 结论 | `ADDED` / `SKIPPED` / `FAILED` |
|
||
| 原因 | 见 3.3 |
|
||
| 选中商家 | ADDED 时必填 |
|
||
| 平台索引ID | sku/spu |
|
||
| 平台名称 | |
|
||
| 平台规格 | |
|
||
| 平台价格 | |
|
||
| 效期原文 | |
|
||
| 库存 | |
|
||
| 毛利率 | `(销售价-平台价)/销售价`,保留 4 位小数 |
|
||
| dry_run | `Y/N` |
|
||
| 加购凭证 | 接口回执或页面摘要;dry-run 为空 |
|
||
| 候选商家清单 | 可选,分号拼接,便于核对为什么没选上 |
|
||
|
||
另写一份 `未匹配商家_时间戳.txt`:所有出现过、但不在 11 家名单里的商家名(去重)。用来决定要不要加别名。
|
||
|
||
### 3.3 原因码
|
||
|
||
| 原因码 | 结论 | 何时 |
|
||
| --- | --- | --- |
|
||
| `NO_SALE_PRICE` | SKIPPED | 销售价缺失 |
|
||
| `NO_QTY` | SKIPPED | 采购数量缺失或 ≤0 |
|
||
| `NO_HIT` | SKIPPED | 接口无货或空列表 |
|
||
| `NO_SELF_WAREHOUSE` | SKIPPED | 有货但不在 11 家 |
|
||
| `MARGIN_LT_5PCT` | SKIPPED | 自营仓有货但毛利不够(可与其它原因并列,取「没有任何候选过齐 1~4」) |
|
||
| `EXPIRY_LT_12M` | SKIPPED | 效期不够 |
|
||
| `STOCK_LT_QTY` | SKIPPED | 库存不够 |
|
||
| `NO_CANDIDATE_AFTER_RULES` | SKIPPED | 1~4 筛完为空(推荐作为总原因,明细放候选清单) |
|
||
| `DRY_RUN` | ADDED | 规则通过,未真正加购 |
|
||
| `CART_OK` | ADDED | 加购成功 |
|
||
| `QUERY_FAILED:...` | FAILED | 搜索接口失败(已重试) |
|
||
| `CART_FAILED:...` | FAILED | 加购失败 |
|
||
| `CART_UNKNOWN:...` | FAILED | 加购后无法确认是否进车 |
|
||
|
||
SKIPPED 的总原因用 `NO_CANDIDATE_AFTER_RULES`,并在「候选商家清单」里带每条被淘汰原因。不要只写一个模糊的「不合格」。
|
||
|
||
---
|
||
|
||
## 4. 规则引擎(`rules.py`)
|
||
|
||
两平台只把候选翻译成同一结构,再进引擎。平台代码禁止自己改优先级。
|
||
|
||
```python
|
||
@dataclass
|
||
class Candidate:
|
||
mall_name: str
|
||
sku_id: str
|
||
name: str
|
||
spec: str
|
||
price: float
|
||
expiry_raw: str
|
||
expiry_months: float | None
|
||
vendor_raw: str
|
||
vendor_norm: str
|
||
stock: float
|
||
extra: dict
|
||
|
||
@dataclass
|
||
class PurchaseLine:
|
||
approval_no: str
|
||
sale_price: float
|
||
qty: float
|
||
```
|
||
|
||
### 4.1 商家规范化
|
||
|
||
```text
|
||
去首尾空格
|
||
去掉前缀 "[自营]"(全角空格也去)
|
||
压缩连续空格为单空格
|
||
```
|
||
|
||
规范化后必须 **等于** 下面 11 个字符串之一,顺序即优先级(下标越小越优先):
|
||
|
||
```python
|
||
WAREHOUSE_ORDER = [
|
||
"广东壹号药业有限公司",
|
||
"昆山亿方药业有限公司",
|
||
"湖北亿昊药业有限公司",
|
||
"天津壹号药业有限公司",
|
||
"重庆亿昊药业有限公司",
|
||
"重庆壹号医药有限公司",
|
||
"湖南壹号药业股份有限公司",
|
||
"辽宁亿昊药业有限公司",
|
||
"河南壹号医药有限公司",
|
||
"甘肃壹号云医药有限责任公司企业店",
|
||
"陕西壹号药业有限公司",
|
||
]
|
||
```
|
||
|
||
本期不做别名、不做包含匹配。对不上的 `vendor_raw` 记入未匹配清单。
|
||
|
||
### 4.2 价格
|
||
|
||
```text
|
||
毛利 = (销售价格 - 平台价) / 销售价格
|
||
合格:毛利 >= 0.05
|
||
即:平台价 <= 销售价格 * 0.95
|
||
```
|
||
|
||
平台价无法转数字 → 该候选淘汰。销售价 ≤ 0 → 整行 SKIPPED。
|
||
**禁止**用采购价、禁止 ±10% 区间。
|
||
|
||
### 4.3 效期
|
||
|
||
目标:剩余 ≥ 12 个月。解析顺序:
|
||
|
||
1. 纯数字(含小数):当作月数。
|
||
2. 含「月」:抽出数字当月数。
|
||
3. 日期(`YYYY-MM-DD` / `YYYY/MM/DD` / `YYYY-MM`):`(到期日 - 今天) / 30.4375`,到期日按该月最后一天。
|
||
4. 都不是:`expiry_months = None`,该候选淘汰(原因 `EXPIRY_UNPARSEABLE`)。
|
||
|
||
接口虽已带 12 个月过滤,仍以本函数为准。
|
||
|
||
### 4.4 库存
|
||
|
||
`stock >= qty`。库存无法转数字或为 0 → 淘汰。药帮忙无货把价格改成 0 的旧逻辑可保留在映射层,引擎侧会因库存/价格再淘汰一次。
|
||
|
||
### 4.5 择仓
|
||
|
||
```text
|
||
passed = [c for c in candidates if 自营仓 and 毛利 and 效期 and 库存]
|
||
if not passed: return None
|
||
return min(passed, key=lambda c: WAREHOUSE_ORDER.index(c.vendor_norm))
|
||
```
|
||
|
||
同一仓库多条 SKU:取平台价更低的;再相同取库存更大的。不要两条都加购。
|
||
|
||
### 4.6 必须先写的单测(不连网)
|
||
|
||
文件:`tests/test_rules.py`。Windows 在改 `main.py` 前先把这些测过。
|
||
|
||
| 用例 | 期望 |
|
||
| --- | --- |
|
||
| 11 家名单内、毛利 6%、效期 13 月、库存够 | 选出该仓 |
|
||
| 毛利刚好 5% | 选出(`>= 0.05`) |
|
||
| 毛利 4.9% | 淘汰 |
|
||
| 商家不在名单 | 淘汰 |
|
||
| 商家带 `[自营] 广东壹号药业有限公司` | 视为广东壹号 |
|
||
| 广东和昆山都合格 | 选广东 |
|
||
| 只有昆山合格 | 选昆山 |
|
||
| 库存 9、采购 10 | 淘汰 |
|
||
| 效期 11 个月 | 淘汰 |
|
||
| 效期 `2027-09-14` 且今天起 ≥12 个月 | 过 |
|
||
| 空候选 | SKIPPED 语义(函数返回 None) |
|
||
| 销售价用 100、平台价 96 | 淘汰(毛利 4%) |
|
||
| 销售价 100、平台价 95 | 过 |
|
||
|
||
用采购价 ±10% 的旧例子(平台价 96、采购价 90)在新规则下若销售价是 100 应淘汰。加一条单测钉死,防止有人把 ±10% 加回来。
|
||
|
||
命令:
|
||
|
||
```bat
|
||
cd /d 工程目录
|
||
uv run pytest tests/test_rules.py -v
|
||
```
|
||
|
||
期望:全绿。未装 pytest 则 `uv add --dev pytest`。
|
||
|
||
---
|
||
|
||
## 5. 加购(原工程没有,这是新工作)
|
||
|
||
### 5.1 抓接口(每个平台做一次,记录进 `docs/cart-api.md` 或工程内 `CART_API.md`)
|
||
|
||
在 Windows 上用已经登录的账号:
|
||
|
||
1. 打开对应商城,F12 → Network,过滤 XHR/Fetch。
|
||
2. 搜索一个确定能加的自营仓商品。
|
||
3. 点「加入购物车」,看新出现的请求。
|
||
4. 记录:URL、方法、请求头(cookie / token 哪些必要)、body、成功响应长什么样。
|
||
5. 把 body 里的 sku/spu、数量、商家 ID 标出来。
|
||
|
||
1 号药城登录态用 `ycgltoken` 等;药帮忙用整份 cookie。加购请求必须带上搜品时同一套认证,不要重新登录。
|
||
|
||
若加购接口有 CSRF / 签名 / 人机验证:不要硬解,改页面点击(5.3)。
|
||
|
||
### 5.2 接口加购(优先)
|
||
|
||
`cart_yaoex.add(auth, candidate, qty) -> cart_ref`
|
||
`cart_ybm.add(cookies, candidate, qty) -> cart_ref`
|
||
|
||
- 数量 = 采购数量。
|
||
- 成功:响应明确成功,或随后查购物车能看到该 sku + 数量。
|
||
- 响应含糊:结论 `FAILED`,原因 `CART_UNKNOWN`,不要报 ADDED。
|
||
- 已在车里:视为成功(幂等),不要再加一次导致数量翻倍。先查车再加。
|
||
|
||
### 5.3 页面加购(接口抓不到才用)
|
||
|
||
只对规则已经选出的那 **1 条** 操作:
|
||
|
||
1. 打开商品页或搜索结果中该 sku。
|
||
2. 填数量。
|
||
3. 点加入购物车。
|
||
4. 等成功提示或打开购物车核对。
|
||
|
||
禁止:重新用页面搜索批准文号再人工挑仓。仓已经由规则选定。
|
||
|
||
页面选择器用艺赛旗 `BrowserSession`,登录态复用。不要为加购再登一次(除非会话丢了)。
|
||
|
||
### 5.4 dry-run
|
||
|
||
默认 `--dry-run`。`ADDED + DRY_RUN` 表示规则通过。关 dry-run 必须显式 `--execute-cart`。
|
||
|
||
第一次真正加购只用 `--limit 1 --platform yaoex --execute-cart`,人工打开购物车核对后再加量。
|
||
|
||
---
|
||
|
||
## 6. Windows 环境与运行
|
||
|
||
### 6.1 环境
|
||
|
||
- 艺赛旗 Python 应用,能 `uv run main.py`
|
||
- 密码箱已有:
|
||
- `yaoex_GYJDLHT_login`
|
||
- `yaobangmang_18146141930_login`
|
||
- 账号必须是业务允许加购的测试/正式采购账号。真正加购前跟业务确认,避免测出一车真货。
|
||
- 桌面目录:`福建商城选品测试\`
|
||
|
||
### 6.2 命令
|
||
|
||
```bat
|
||
:: 只判定,不加购(默认)
|
||
uv run main.py --dry-run --limit 5
|
||
|
||
:: 只跑一个平台
|
||
uv run main.py --dry-run --limit 5 --platform yaoex
|
||
|
||
:: 确认规则后,真加购 1 条
|
||
uv run main.py --execute-cart --limit 1 --platform yaoex
|
||
```
|
||
|
||
把命令写进 `README.md`,替换原「查价结果」说明。
|
||
|
||
### 6.3 验收顺序(必须按这次序,不要一上来一千条真加购)
|
||
|
||
1. `pytest tests/test_rules.py` 全绿。
|
||
2. `--dry-run --limit 5 --platform yaoex`:结果表 5 行,结论只有 ADDED/SKIPPED/FAILED,没有 ±10% 残留。
|
||
3. 同样 5 条跑药帮忙。
|
||
4. 人工抽 2 条 ADDED:对照网页,商家是否 11 家之一、毛利是否 ≥5%、效期、库存。
|
||
5. `--execute-cart --limit 1` 一个平台,打开购物车看 sku 和数量。
|
||
6. 再跑同一条,确认不会把数量翻倍(幂等)。
|
||
7. 再 `--limit 20` dry-run,看耗时。预估一千条:约 `20 条耗时 × 50`,写入结果 README。登录应只发生两次(每平台一次)。
|
||
|
||
失败则停在当前步,不要跳到一千条。
|
||
|
||
---
|
||
|
||
## 7. 异常
|
||
|
||
| 情况 | 处理 |
|
||
| --- | --- |
|
||
| 密码箱空 | 立即失败退出,不写半份结果 |
|
||
| 登录失败 | 该平台本批中止;另一平台仍可跑(已登录的话) |
|
||
| 单文号查询 3 次仍失败 | 该行该平台 FAILED,继续下一行 |
|
||
| 加购超时 | FAILED `CART_UNKNOWN`,不要当 SKIPPED |
|
||
| 极验登录点一次不够 | 沿用原等待逻辑;仍失败则整平台中止,记登录错误 |
|
||
| 关闭 dry-run 但加购模块未实现 | 启动时报错退出,禁止假装 ADDED |
|
||
|
||
脚本不点支付、不打开结算页。
|
||
|
||
---
|
||
|
||
## 8. Windows 任务清单
|
||
|
||
按序做。每步可单独验证。
|
||
|
||
### 任务 1:工作副本和输入模板
|
||
|
||
- [ ] 拷贝同事工程到工作目录(仓库 `rpa_yisaiqi/procure_mall/` 或 Windows 本地)
|
||
- [ ] 桌面建 `福建商城选品测试\选品输入.xlsx`,表头按 3.1
|
||
- [ ] 放 5 条真实批准文号、销售价格、采购数量(问业务要,不要用假文号)
|
||
- [ ] `uv run python -c "import isa_rpa, requests, openpyxl; print('ok')"` 能过
|
||
|
||
### 任务 2:规则引擎 + 单测
|
||
|
||
- [ ] 新建 `rules.py`、`tests/test_rules.py`
|
||
- [ ] 实现规范化、毛利、效期、库存、择仓
|
||
- [ ] `uv run pytest tests/test_rules.py -v` 全绿
|
||
- [ ] 确认没有 import 原 ±10% 函数
|
||
|
||
### 任务 3:搜品接到按行决策(仍不加购)
|
||
|
||
- [ ] 拆出或保留 `query_yaoex_products` / `query_ybm_products`
|
||
- [ ] 候选映射成 `Candidate`
|
||
- [ ] `main.py` 改为按行循环,默认 dry-run
|
||
- [ ] 删除 `filter_rows_by_purchase_price_band` 调用
|
||
- [ ] 写新结果表(3.2)
|
||
- [ ] 跑 `uv run main.py --dry-run --limit 5`
|
||
- [ ] 人工核对 2 条 ADDED、2 条 SKIPPED
|
||
|
||
### 任务 4:抓加购接口
|
||
|
||
- [ ] 1 号药城 F12 抓「加入购物车」,写入 `CART_API.md`
|
||
- [ ] 药帮忙同样写一份
|
||
- [ ] 判定:接口可用 / 必须页面点击
|
||
|
||
### 任务 5:实现加购(默认仍 dry-run)
|
||
|
||
- [ ] `cart_yaoex.py` / `cart_ybm.py`
|
||
- [ ] 先查车再加,避免数量翻倍
|
||
- [ ] `--execute-cart --limit 1` 单平台
|
||
- [ ] 人工打开购物车核对
|
||
- [ ] 再跑同一条,数量不翻倍
|
||
|
||
### 任务 6:收尾
|
||
|
||
- [ ] README:命令、dry-run 默认、输入输出路径、密码箱名称
|
||
- [ ] `--limit 20` dry-run 耗时写进 README
|
||
- [ ] 把 `未匹配商家` 列表交给业务看要不要补别名(本期不改代码硬匹配)
|
||
- [ ] 交付:工程、5 条结果 xlsx、加购成功截图、CART_API.md
|
||
|
||
---
|
||
|
||
## 9. 与后续 Oracle / 状态中心的边界
|
||
|
||
本期 `decision` 字典就是以后 `PROCURE_ITEM_RUN` 的 `output_json`。字段先对齐:`result=ADDED|SKIPPED|FAILED`、原因、商家、sku、价格、数量。
|
||
|
||
不要在本期接 FastAPI、不要写 MySQL、不要为选品新建 Oracle 表。下一期只换输入输出通道,不换规则和搜品。
|
||
|
||
---
|
||
|
||
## 10. 未决(不影响 Windows 开工)
|
||
|
||
| 项 | 本期默认 | 谁拍板 |
|
||
| --- | --- | --- |
|
||
| 两平台都合格是否都加购 | 都加 | 业务;要互斥再改 `main` 循环 |
|
||
| 毛利 刚好 5% | 算合格 `>=` | 已按设计说明「不低于 5%」 |
|
||
| 商家名不完全等于 11 家 | 淘汰并记未匹配清单 | 业务补别名后再改 `WAREHOUSE_ORDER` 映射 |
|
||
| 真正加购用测试账号还是正式采购账号 | 必须业务书面确认后再 `--execute-cart` | 业务 / 运维 |
|
||
|
||
加购接口在改代码前未知,这是正常的。任务 4 的产出就是答案,不是阻塞任务 1~3 的理由。
|