feat(edit): 定价试算开发、SKU 样式功能修改

This commit is contained in:
R524809
2026-09-29 17:50:19 +08:00
parent 84b230e69a
commit 0a303414d8
52 changed files with 4278 additions and 1393 deletions
+24
View File
@@ -0,0 +1,24 @@
# 类目佣金导入 API
> 2026-09-29。产品方案见 `docs/product/category-commission-import-plan.md`。所有金额与费率为十进制字符串;导入仅支持 Ozon / RU / rFBS / RUB。
## 管理端
全部 `/system/pricing/commissions` 接口要求实时有效的系统管理员授权,普通用户返回 403 `SYSTEM_ADMIN_REQUIRED`。
- `GET /system/pricing/commissions?platform_id={uuid}`:返回导入版本列表(不含原始文件),最近版本在前。
- `GET /system/pricing/commissions/:id`:版本详情,含解析后的类目、档位、异常、变更状态。
- `POST /system/pricing/commissions/preview`:只读预览。请求 `{platform_id,version,source_reference,captured_on,document}`,`document` 为来源 JSON 对象。返回 `{preview_hash,categories,summary,previous_import_id}`。分类结果为 eligible/excluded,差异为 added/changed/unchanged;summary 包含总类目、规则数、可用/排除类目、映射商品类型、移除类目数。格式不正确返回 422 `COMMISSION_IMPORT_INVALID`;允许预览全部无法映射的结果;没有可映射类目时禁止启用空版本。
- `POST /system/pricing/commissions/imports`:201,要求 UUID `Idempotency-Key`。请求在预览输入基础上增加 `{preview_hash,confirm_scope:true}`。确认适用范围表示管理员确认数据适用于 Ozon RU/rFBS 的 RUB 售价;目录异常和移除数量只在预览中提示,不要求额外勾选确认。只支持立即启用,完整替换本入口的前一版本,不修改非本入口规则;发生其他来源有效映射冲突时拒绝启用。
预览指纹覆盖完整输入、解析结果、可映射的商品类型及当前版本。启用时锁平台并重新核对,变化返回 409 `COMMISSION_PREVIEW_STALE`。同一来源内容不重复导入,同平台版本名称唯一,冲突返回 409 `COMMISSION_IMPORT_EXISTS`。旧导入的规则/映射结束有效期,新规则使用新行;禁止改写历史费率,历史报价保持不变。
最多 100 个一级类目、2,000 个二级类目,JSON 总大小最多 2 MiB。首版只接收三种固定区间的完整组合,校验叶子序号及 label/value 百分比一致、所有来源 cate_id 唯一;0% 是有效佣金,可正常导入;未匹配、父子关系不符、无有效类型的类目在预览中提示,并因无法建立商品类型映射而暂不参与算价。缺少或重叠档位不能发布。
## 卖家查询
`GET /pricing/commission-rules?store_id={uuid}&platform_product_category_id={uuid}`,也可用 `description_category_id={外部类目ID}` 替代内部类目 ID,两者必须且只能指定一个。当前固定 RU/rFBS,无需前端重复传入履约枚举。
需要门店属于当前工作空间。返回 `{data:{category_name,currency_code,bands,version,source,effective_from}}`;每档含 `{id,min_price,max_price,min_inclusive,max_inclusive,commission_rate}`。内部类目必须属于门店平台且有效;外部 ID 必须能唯一解析到同平台已核对佣金类目。没有可用规则返回 422 `PRICING_COMMISSION_UNAVAILABLE`,不能将缺失规则推定为 0% 佣金。
报价与此查询共用正式佣金解析器。现有 `PricingOption` 增加可选 `commission_details`(类目、区间、来源版本),以兼容已持久化的历史报价。规则换版会使待确认预览失效,已确认报价不重新计算。
+7 -7
View File
@@ -10,8 +10,8 @@
需要已认证工作空间。返回 `{data: PricingCatalog}`:
- `store`:门店 ID、名称及报价币种(CNY / RUB)。
- `rate_cards[]`:该门店平台、RU / rFBS 的有效费率卡及运输方式。正式环境必须 active、在有效期内、有审核时间及审核人。`development_only=true` 表示本地开发模式临时可选的 draft 卡。
- `pending_rate_cards[]`:该平台 RU / rFBS 待审核草稿的名称、版本和状态,仅用于说明阻断原因,不作为方案或报价可选项。
- `rate_cards[]`:该门店平台、RU / rFBS 的可用费率卡及运输方式,包含已审核且在有效期内的 active 卡,以及配置允许时的 draft 卡。`development_only=true` 为兼容现有 DTO 保留,表示所选卡尚未审核,并不代表禁止首次上架。
- `pending_rate_cards[]`:该平台 RU / rFBS 待审核草稿的名称、版本和状态;在允许草稿报价时也可能同时出现在 `rate_cards[]`,用于展示审核状态。
- `policies[]`:该门店活动方案,默认方案优先,包含完整参数和 revision。
- `exchange_rate`:CBR 最新 CNY→RUB 官方参考汇率,包含 ID、日期和 stale;缺少数据时为 null。超过 72 小时提示过期参考,不自动代填其他来源。
@@ -46,7 +46,7 @@
```
- 独立试算 `binding=null`;SKU 必须提供 profile,已有 variant_id 与新建 client_key 二选一。验证资源归属,已上架 SKU 不接受新报价。
- 包装输入是编辑草稿合并后的有效 g/mm 值,必须已确认;尺寸最多三位小数,重量至少 1 g。保存时从实际持久化草稿重新合并并核对,不能仅信任客户端摘要。
- 包装输入是编辑草稿合并后的有效 g/mm 值,必须已确认;接口为兼容历史值允许最多三位小数,重量至少 1 g,当前编辑页与试算界面只接受正整数。保存时从实际持久化草稿重新合并并核对,不能仅信任客户端摘要。
- `mode=target_markup`:目标利润=采购成本×加价率;求解销售价。`fixed_sale`:selling_price 必填,按该售价核算利润。
- 百分比费用以销售额为基数;除加价率外每项小于 1、最多六位小数。引擎拒绝总扣费率≥1。划线价=销售价÷(1−折扣率)。
- 枚举运输方式×产品类型×佣金档,按最终币种舍入后回验货值、佣金、重量和体积重边界。默认运输不可用时 recommended_option_id=null,不替换为另一方式。
@@ -93,13 +93,13 @@ context 保存规则版本、实际汇率与来源,以及系统汇率记录 ID
| DELETE | `/pricing-policies/{id}` | Idempotency-Key;归档并清除默认标志,返回 `{id,archived:true}` |
写入 `{name,note,parameters,allow_commission_override}`。只保存费用、加价、折扣、固定/系统汇率与运输偏好;采购价、包装、手动售价及临时佣金不属于方案持久字段。
方案的默认和比较运输必须属于同一可用费率卡;正式环境仅允许已审核卡。历史快照不会被方案修改;尚未确认的预览因方案版本改变要求重算。
方案的默认和比较运输必须属于同一可用费率卡;正式环境默认允许有效草稿卡;可通过 `PRICING_ALLOW_DRAFT_RATES=false` 仅使用已审核卡。历史快照不会被方案修改;尚未确认的预览因方案版本改变要求重算。
## 5. 数据启用与错误
迁移中的 CEL 目录为 `draft`,覆盖六种产品类型、三种运输方式,香港空运不纳入。真实账单复核、有效日期/审核人以及平台类目佣金映射仍是正式使用前置条件,接口不会回退到示例费率或固定佣金。
迁移中的 CEL 目录为 `draft`,覆盖六种产品类型、三种运输方式,香港空运不纳入。平台类目佣金映射仍是正式试算所需数据;草稿物流费率可按上述配置参与报价,页面保留费率来源标识,接口不会回退到未选定的固定佣金。物流费率审核用于形成有证据的已审核版本,不再是草稿报价上架预检的前置条件。
商品编辑联调期间,API 在 `NODE_ENV=development` 时默认允许 draft 费率卡参与方案保存、预览与草稿报价确认;可设 `PRICING_ALLOW_DRAFT_RATES=false` 关闭。测试环境只有显式设 `PRICING_ALLOW_DRAFT_RATES=true` 才开启;生产环境始终关闭。该模式不修改费率卡状态、不生成审核记录。目录的 `rate_cards[].development_only` 和预览的 `context.development_only` 标识试算性质;基于此类预览确认的 SKU 报价可在编辑页查看,但首次上架校验必须返回 `PRICING_RATE_REVIEW_REQUIRED`,直至使用已审核费率重新试算确认。佣金和汇率仍按现有输入规则处理。
API 在开发与生产环境默认允许 draft 费率卡参与方案保存、预览和 SKU 报价确认;`PRICING_ALLOW_DRAFT_RATES=false` 可显式关闭。测试环境默认关闭,仅显式设为 `true` 才开启。使用草稿卡不会修改费率卡状态或生成审核记录;目录的 `rate_cards[].development_only` 和预览的 `context.development_only` 保留来源标识,供页面和报价快照展示。已确认的草稿卡报价满足定价确认要求,首次上架预检不再因卡片未审核返回 `PRICING_RATE_REVIEW_REQUIRED`;其他报价输入、利润和发布字段校验照常执行。佣金和汇率仍按现有输入规则处理。此变更由维护者于 2026-09-29 要求,影响 Web、API、现有响应说明和发布预检,不改变审核端点。
### 系统管理员审核 CEL 费率
@@ -121,7 +121,7 @@ context 保存规则版本、实际汇率与来源,以及系统汇率记录 ID
|---|---|
| 422 VALIDATION_ERROR | 修正输入格式或缺项 |
| 422 PRICING_RULES_UNAVAILABLE | 配置并审核物流费率 |
| 422 PRICING_COMMISSION_UNAVAILABLE | 配置正式映射,或使用允许临时佣金的方案 |
| 422 PRICING_COMMISSION_UNAVAILABLE | 配置正式映射;缺少正式规则时,可在允许临时佣金的方案或本次自定义参数中填写已核实的临时佣金率 |
| 422 PRICING_FX_UNAVAILABLE | 等待 CBR 同步,或明确采用临时/方案固定汇率 |
| 409 PRICING_PREVIEW_STALE | 重算、比较并重新应用,或显式仅保存草稿 |
| 409 VERSION_CONFLICT | 重新读取版本后修改 |
+11 -4
View File
@@ -13,6 +13,7 @@
Headers:`Idempotency-Key` 必填,页头平台由 header 指定,body 为空。服务端验证采集记录归属、平台可用,并取得或创建该商品在当前平台的 `product_platform_profile`:
- 首次创建时使用该平台默认店铺作为 `target_store_id`,并为所有未删除 SKU 建立本平台 `product_variant_platform_listing`;
- 首期新建 Ozon profile 的履约方式为 `rfbs`,与当前定价费率卡及报价接口一致;其他平台保持 `unknown`,由后续平台适配确定;
- 当前平台没有默认店铺时返回 `422 DEFAULT_STORE_REQUIRED`,只给出店铺管理引导,不创建缺少目标门店的 profile;
- 已存在 profile 时只读取,绝不因再次进入而覆盖用户已选门店、类目、属性或价格;
- 不创建跨平台 profile,也不改变其他平台的上架状态。
@@ -38,7 +39,8 @@ Headers:`Idempotency-Key` 必填,页头平台由 header 指定,body 为空
"id": "uuid", "revision": 12,
"common": { "source_title": "来源标题", "brand": null, "model": null, "barcode": null, "purchase_url": "https://…", "supply_note": null },
"default_physical_spec": { "length_mm": null, "width_mm": null, "height_mm": null, "net_weight_g": null, "status": "missing" },
"default_package_spec": { "length_mm": null, "width_mm": null, "height_mm": null, "shipping_weight_g": null, "status": "missing" }
"default_package_spec": { "length_mm": null, "width_mm": null, "height_mm": null, "shipping_weight_g": null, "status": "missing" },
"package_weight_mode": "common", "package_dimensions_mode": "common"
},
"profile": {
"id": "uuid", "revision": 8, "platform_id": "uuid", "market_code": "RU", "fulfillment": "rfbs",
@@ -78,6 +80,10 @@ Headers:`Idempotency-Key` 必填,页头平台由 header 指定,body 为空
`default_package_spec` 是 SPU 的存储事实,`variants[].package_spec` 仅保存该 SKU 的覆盖值;`effective_package_spec` 按“SKU 覆盖值优先、SPU 默认值回退”解析。Ozon 发布适配器在创建 job 时才将每个目标 SKU 的有效值物化为独立 `items[]`:`length_mm → depth`、`width_mm → width`、`height_mm → height`、`shipping_weight_g → weight`,并固定带上 `dimension_unit: "mm"` 与 `weight_unit: "g"`。不得为了 payload 预先将 SPU 默认值复制到所有 SKU 草稿。商品净重/尺寸不是这组固定物流字段;它们的 SPU/SKU 展示归属由当前 Ozon schema 的 `is_aspect` 决定。
编辑快照的 `product.package_weight_mode` 和 `product.package_dimensions_mode` 分别保存包装重量、包装尺寸的编辑模式(`common` / `variant`);保存草稿的 `common` 中可传同名字段,旧客户端省略时保留当前模式,新商品默认 `common`。模式独立于数值保存,使逐 SKU 表单尚未填写时重新打开仍保持原模式。切到 `variant` 时客户端清空并禁用对应 SPU 输入;切回 `common` 时经确认清空所有 SKU 对应覆盖值并恢复 SPU 输入。两项切换互不影响,模式不改变有效包装规格的“SKU 覆盖优先、SPU 回退”解析规则。
商品编辑页的包装重量和长宽高仅允许手工输入正整数(g / mm),定价详情弹窗采用相同输入规则。已有小数值保留原样供人工核对,不自动取整;API 暂保留三位小数的历史数据兼容能力。
`source_material` 是供页面展示和 AI 使用的**有效来源素材**,由当前 `collection_items.normalized_payload` 的最新规范化值与用户明确修改过的顶层字段合并而成。未修改字段随重复采集自动更新;已修改字段继续保留用户值。`source_material_state.latest` 保留本次最新规范化来源,`overridden_fields` 表示用户覆盖字段,`changed_fields` 表示复采后与用户稿不同的覆盖字段,页面可据此提示、逐项恢复或全部采用最新采集值。原始 `normalized_payload` 与 `raw_evidence` 始终作为采集证据保留,不因编辑而改变。
`captured_category_match` 仅对 Ozon 来源返回自动类目判定结果。服务端只使用公开详情页的**一级**面包屑和结构化 `Type_0` 商品类型,在当前平台目录的活动可发布叶子中精确匹配;公开页后二、三级导航不参与判定。`matched` 时服务端已自动写入 `source_capture`;`ambiguous` 时前端展示 `candidates` 的完整 Atlas 路径,用户确认后按普通手选类目保存为 `manual`;`unmatched`、`unavailable` 均不得自动选择。
@@ -112,7 +118,8 @@ Headers:`If-Match: "{product_revision}:{profile_revision}"`、`Idempotency-Key
"ai_source_overridden_fields": ["title", "description"],
"common": { "source_title": "商品名称", "brand": "品牌", "model": null, "barcode": null, "purchase_url": "https://…", "supply_note": null,
"default_physical_spec": { "length_mm": "100", "width_mm": "50", "height_mm": "20", "net_weight_g": "300", "status": "confirmed" },
"default_package_spec": { "length_mm": "120", "width_mm": "60", "height_mm": "30", "shipping_weight_g": "400", "status": "confirmed" } },
"default_package_spec": { "length_mm": "120", "width_mm": "60", "height_mm": "30", "shipping_weight_g": "400", "status": "confirmed" },
"package_weight_mode": "common", "package_dimensions_mode": "common" },
"profile": { "target_store_id": "uuid", "fulfillment": "rfbs", "title": "Название", "description": "…", "tags": ["tag"],
"platform_product_category_id": "uuid", "category_source": "manual" },
"variants": [{
@@ -142,7 +149,7 @@ Headers:`If-Match: "{product_revision}:{profile_revision}"`、`Idempotency-Key
- 类目变化后不匹配的旧属性作为未映射草稿返回 warnings,不能自动进入发布 payload。属性由平台 schema 校验 `type`、必填、字典、多值/复杂属性和 `is_aspect`;客户端不能用任意 JSON 绕过。
- `media_asset_ids` 是本 SKU 当前平台的最终选图顺序;最多 30 张。格式只允许 JPG/PNG/WebP,单文件最多 20 MB,边长超过 10,000 px 拒绝,短边小于 700 px 不得作为首图并给出警告。第一张是主图。已完成的 `product_image` 上传素材和网络导入素材可供同工作空间的 SKU 选择;当前商品成功的水印与 3:4 处理结果也可选择。采集图片仍须先转存,且来源变体须匹配。
- `common.model` 是用户手填或主动 AI 填报的商品型号;采集时允许为空,但每次首次上架前必须非空。`offer_id` 是用户手填或主动 AI 填报的目标平台卖家货号;采集入箱时不填值,生成时不直接复用 `source_sku`。草稿可为空,但每个待首次上架 SKU 的 `offer_id` 必须非空且在同一店铺/平台唯一。AI 填报接口和回填规则见[方案](../product/ai-autofill-plan.md)。
- `common.source_title` 在编辑页显示为“中文商品名”;`profile.title` 显示为“俄文发布标题”,页面保存时必填。为允许先保存采集草稿再使用 AI 填报,API 草稿契约仍接受空标题;发布就绪校验在 `profile.title` 为空时返回 `PUBLISH_TITLE_REQUIRED`。SKU 发布标题 `variants[].title` 为 `null` 时继承 `profile.title`,不回退到 `display_name`;现有 SKU `tags=[]`、`description=null` 保持继承语义。标题、标签、描述分别独立覆盖。中俄对照按 SPU/SKU 与字段随 `editor-draft` 原子保存;SKU 继承项直接引用 SPU 对照,手工俄文覆盖但无匹配中文时标为对照待更新。发布适配器使用 SKU 有效文案仍是后续工作。
- `common.source_title` 在编辑页显示为“中文商品名”;`profile.title` 显示为“俄文发布标题”。编辑页保存草稿时允许中文商品名、俄文发布标题、型号、品牌、产品类目及类目必填属性留空,必填标记只提示首次上架所需资料;首次上架预检统一检查缺失项,`profile.title` 为空时返回 `PUBLISH_TITLE_REQUIRED`。草稿仍须携带有效的 `target_store_id` 作为店铺上下文,并遵守已填写字段的格式和长度约束。SKU 发布标题 `variants[].title` 为 `null` 时继承 `profile.title`,不回退到 `display_name`;现有 SKU `tags=[]`、`description=null` 保持继承语义。标题、标签、描述分别独立覆盖。中俄对照按 SPU/SKU 与字段随 `editor-draft` 原子保存;SKU 继承项直接引用 SPU 对照,手工俄文覆盖但无匹配中文时标为对照待更新。发布适配器使用 SKU 有效文案仍是后续工作。
成功返回新 `product.revision`、`profile.revision`、创建的 SKU ID/`client_key` 映射和 warnings。任一字段、属性或媒体无效时返回 `422` 且不部分保存;版本冲突返回 `409 VERSION_CONFLICT`,客户端应重新读取编辑快照。
@@ -254,7 +261,7 @@ Body:`{ "variant_ids": ["uuid", "uuid"] }`,最多 100 个且不能重复。
没有报价时仍可保存商品,但首次发布预检返回 `PRICING_REQUIRED`。已确认报价不会随预览到期而失效;采购、包装、目标门店/类目、履约或门店币种改变后须重新确认。调整默认方案、汇率或费率不会反向改写历史快照。详见[定价 API](./pricing.md)。
开发环境可按定价 API 的草稿费率模式完成商品编辑联调;这种报价即使已保存,也会在首次发布预检返回 `PRICING_RATE_REVIEW_REQUIRED`。费率完成正式审核后,须用已审核卡重新试算并确认 SKU。
经维护者 2026-09-29 确认,使用草稿物流费率卡完成的报价可以保留到首次发布预检;未审核状态只作为来源信息展示,不再生成 `PRICING_RATE_REVIEW_REQUIRED`。当前仍要求 SKU 已确认有效报价、售价、包装和其他发布必填数据。生产环境默认可使用草稿卡,管理员可通过 `PRICING_ALLOW_DRAFT_RATES=false` 限制其进入新试算;审核流程仍可用于核实费率。
## 5. 素材选择与水印派生
@@ -0,0 +1,72 @@
# 类目佣金 JSON 导入与定价接入方案
> 2026-09-29:维护者已批准实施。目标是通过「系统管理 → 类目佣金」导入、核对并启用分档规则,让商品编辑页和即时试算自动读取佣金。
## 1. 范围与责任
本任务由当前会话负责跨领域集成,涉及 `apps/web`、`apps/api`、`packages/contracts`、`packages/database` 和文档。原因是导入页面、管理员鉴权、数据库原子启用和报价规则读取必须形成一个可验收能力。新增接口采用独立契约,不破坏现有报价请求。
本次只支持 Ozon、RU、rFBS、RUB 阶梯佣金。数据是平台共享参考数据,沿用平台目录的系统管理员权限;普通用户仅通过已授权门店查询有效规则。导入来源为 `competitor_capture`,保留来源信息与版本。
## 2. 已核对的数据
用户附件包含 26 个一级类目、542 个二级类目、1,626 条规则。每个二级类目都是三档:`0 < 售价 ≤ 1500₽`、`1500₽ < 售价 ≤ 5000₽`、`售价 > 5000₽`。84 个二级类目的三档费率相同。标签百分比与 `value` 一致。
2026-09-29 只读核对本地 Ozon 平台目录:542 个二级 `cate_id` 全部匹配,一级父类目 ID 全部一致,覆盖 7,365 个有效商品类型。目录最近同步于 2026-09-28。该结果证明本次可建立映射,不代表任意未来附件的 ID 都正确。
来源 `id` 是树节点编号,不能用作平台 ID。`cate_id` 保存为来源键,并与 Ozon `external_category_id` 核对;同名类目不能合并。第三层是价格档,不是商品类型。
`200001728`(管材、桩材、型材)和 `17028768`(Ozon Fresh 新鲜及冷冻肉类、家禽和鱼类)的三档都是 0%。维护者明确指出 0% 可能是平台的真实优惠费率;导入按有效佣金处理并保留原值,不由系统推断为占位值。
## 3. 页面与流程
系统管理增加「类目佣金」列表,展示平台规则版本、来源、启用时间及覆盖数量,选中版本查看各类目的三档费率。
导入弹窗:
1. 上传 JSON(也可粘贴文本),填写来源说明、采集日期、版本名称。
2. 服务端校验格式、ID 唯一性、档位、百分比一致性;与当前平台目录匹配,生成预览。
3. 预览列出新增、变更、未变类目和目录异常(未匹配、父子关系不符、无有效商品类型);显示成功类目及商品类型覆盖数量。异常类目不进入可启用集合。
4. 管理员确认来源适用于 RU/rFBS;预览明确展示无法映射数与上一版本被移除的覆盖数,但不要求额外勾选排除确认。
5. 点击「确认并启用」,后端重算预览指纹,若目录、当前版本或输入变化则返回冲突并要求重新预览。成功后立即生效。
首版只支持立即启用,不做定时发布、逐条在线编辑、后台抓取或自动猜测缺失费率。0% 佣金直接按来源导入。无法映射的类目保留在导入版本及预览中,但无法建立定价映射;只要存在可映射类目,就可启用其余规则。
## 4. 存储与原子启用
复用 `commission_categories`、`commission_category_rules`、`platform_product_category_commission_mappings`;增加导入版本表保存原始 JSON、内容指纹、来源、采集日期、操作者、统计和启用时间。规则及映射关联导入版本。
费率按比例字符串存储,例如 12% 为 `0.120000`,20.50% 为 `0.205000`。金额边界为精确十进制,第三档上界为 null。一级类目仅用于分组,规则挂在二级佣金类目下;商品类型叶子通过显式映射共享规则。
启用在单个数据库事务内完成:检查系统管理员权限、锁定平台、检查预览指纹、保存版本、写入类目与规则、建立有效商品类型映射、结束被替代规则/映射的有效期。失败整体回滚。所有关键写操作要求 Idempotency-Key;重复提交同一批次不产生重复版本。
同平台、市场、履约模式只保留一个当前导入版本。使用新的规则行保留历史引用,禁止修改已启用的费率、区间和来源。报价保存时仍重新读取规则并检查指纹,旧预览在换版后不能确认;已确认报价保留历史快照。
## 5. 规则查询与算价
增加卖家查询接口:按 `store_id` 和 Atlas 商品类目 UUID,或者按已核对的 Ozon `description_category_id` 查询,二者只能指定一个;返回匹配类目、币种、全部价格档、来源、版本、生效日期。门店必须属于当前工作空间。
查询接口与报价共用正式规则解析逻辑;报价仍由后端选择规则,前端不能用传入佣金替换有效正式规则。现有定价引擎已经逐档反算售价、舍入并检查区间,继续复用。规则的区间币种为 RUB,CNY 门店按当前预览锁定的汇率换算判断。
现有试算结果增加佣金类目、档位、百分比、来源版本展示;有正式规则时无需填写临时佣金。未覆盖类目继续给出缺失规则提示。前端展示缺失状态不能把它误写成 0%。
## 6. 验收
- 原始附件可预览 542 类、1,626 档,包括两个全档 0% 类目,均可映射。
- 错误 JSON、重复 ID、缺失档位、标签和值不一致的费率被拒绝。
- 同名不同 ID 保持独立;父类目不符和未匹配项不会自动发布。
- 普通用户不能预览或启用管理员导入;跨租户门店查询失败。
- 启用重放、并发换版、陈旧预览、完整回滚及历史规则保护有数据库/API 测试。
- `1500`、`1500.01`、`5000`、`5000.01` 正确命中档位,CNY/RUB 试算和目标利润反算使用正式规则。
- 新版启用后旧试算预览失效,已有确认报价保持原快照。
- 受影响工作区通过类型检查、构建和相关测试;浏览器验证上传、预览、异常提示与启用条件。
## 7. 实施顺序
先补充 API 契约与共享 DTO,再实现导入解析器、数据库迁移和原子启用,随后实现管理页面与菜单、查询及试算展示,最后完成测试与交接记录。开发验证使用测试数据,不自动把用户附件启用为正式业务费率;正式启用需由管理员在页面确认其来源与适用范围。
## 8. 实施结果(2026-09-29)
已实现以上主流程,迁移为 `052_category_commission_imports.sql`。最初附件预览为 540 类 / 7,358 类型;维护者纠正 0% 处理后,新版浏览器实测 542 类 / 7,365 类型均可映射。修正后 38 项相关测试、API/Web 类型检查与构建、contracts/database 构建通过;浏览器曾核对上传、预览、异常筛选、确认条件和预览失效;0% 处理修改后已重新验证全部 542 类均可用,且不需要额外排除确认。数据库启用/历史查询/失败回滚使用事务测试验证,未启用用户附件,未做多连接并发压力测试。
首版映射为发布时快照,不自动补齐后续同步新增类型;同内容重复导入被拒绝,映射单独刷新能力留待后续。正式使用前需管理员在页面确认数据适用范围。
+18 -1
View File
@@ -1,6 +1,6 @@
# Atlas Seller Kit 交接说明
> 更新:2026-09-28。此文是新 AI 对话、架构讨论与开发工作的首读入口。开始开发前,必须先阅读并遵守 [`development-collaboration-contract.md`](./development-collaboration-contract.md) 和仓库 `AGENTS.md`。下方按日期记录的旧方案仅供追溯;当前状态以本节及最新的 1.47 节为准。
> 更新:2026-09-29。此文是新 AI 对话、架构讨论与开发工作的首读入口。开始开发前,必须先阅读并遵守 [`development-collaboration-contract.md`](./development-collaboration-contract.md) 和仓库 `AGENTS.md`。下方按日期记录的旧方案仅供追溯;当前状态以本节、2026-09-29 类目佣金记录及最新的 1.47 节为准。
## 1. 项目定位
@@ -20,6 +20,23 @@ SKU 定价已打通试算、表单应用与原子保存确认,在线商品同
接手前请先阅读 `git status --short`,确认当前工作区状态;本轮图片选择的 Web、API、contracts、迁移、测试和文档随本报告一起提交。不要用 `git reset --hard` 或批量清理未跟踪文件。共享 contracts 类型需先构建,再执行 Web/API/Worker 检查。开发验证需要时可按 `AGENTS.md` 先确认进程与端口,再启动或重启 API/Worker;下方旧章节中的“不可重启”说法已失效。
### 2026-09-29:类目佣金 JSON 导入与定价接入
- 已先编写[实施方案](../product/category-commission-import-plan.md),并完成[API 契约](../api/category-commissions.md)、迁移 `052`、导入解析器、原子启用、管理页面及试算展示。影响 Web、API、contracts、database;未涉及 Worker 和扩展。
- 入口为「系统管理 → 类目佣金」(`/system/commissions`):上传 JSON/TXT 或粘贴 JSON,填写版本、来源、采集日期,预览差异与异常,确认适用范围后启用。支持搜索、只看异常、查看历史版本;百分比显示两位小数。
- 当前限定 Ozon RU / rFBS / RUB 三档佣金;通过已同步平台目录核对二级 `cate_id` 和父类目,映射到 Atlas 商品类型 UUID。查询接口支持内部 UUID 或外部 `description_category_id`,正式报价按最终售价及汇率命中分档,结果展示佣金类目、档位和版本。
- 原始附件共 542 类 / 1,626 档。最初预览错误地排除了两个全档 0% 类目。维护者确认 0% 可能是有效优惠佣金后,已修正为可导入;新版浏览器实测 542 类全部可用,覆盖 7,365 个商品类型。**仅预览,尚未把用户附件启用为正式费率**;管理员需核对 RU/rFBS 适用范围并在页面确认。
- 迁移 `052` 已在本地数据库应用,再次运行迁移无变化。修正后 38 项相关测试通过:解析、数据库真实角色权限、启用/幂等/旧预览、目录异常提示、授权撤销、跨工作空间、后半程写入失败回滚、历史不可变,以及 1500/1500.01/5000/5000.01 ₽ 边界与 CNY 换算。API/Web 类型检查及构建、contracts/database 构建通过;Web 仍有大 bundle 提示。
- 浏览器验证了实际附件上传、预览、异常筛选、确认项使按钮可用、修改来源后预览失效;未在浏览器提交真实费率。启用及历史查询由事务回滚集成测试验证;未做多连接并发压力测试。没有手动启动/停止维护者的 API/Web/Worker,使用现有 8100/8200 服务;浏览器验证窗口已关闭。
- 首版每次启用完整替换上一导入版本,不支持增量或定时发布;同 JSON 内容和同平台版本名称禁止重复导入。映射是启用时目录的快照,后续新增商品类型的映射刷新仍需完善,不能承诺目录同步自动扩展佣金覆盖。正式使用仍须核对附件适用范围及其他物流/结算费用。
### 2026-09-29:草稿物流费率用于报价与发布预检
- 维护者取消“草稿物流费率报价不能首次上架”的业务限制。开发和生产环境默认允许草稿卡参与方案、试算与 SKU 确认,`PRICING_ALLOW_DRAFT_RATES=false` 可限制新报价;测试环境仍默认关闭。既有 `development_only` 字段继续标记费率尚未审核。
- 首次发布预检不再因草稿卡报价产生 `PRICING_RATE_REVIEW_REQUIRED`;已确认报价、售价、包装、素材与平台属性等校验保持有效。定价工具移除误导性告警,SKU 显示定价自身状态,费率选择仍标明“待审核费率”。
- 系统管理「物流费率审核」仍可用真实账单样本复核 Ozon CEL 费率;草稿卡不会因可试算而自动变为 active。商品编辑页的“选择 SKU 并首次上架”按钮仍为占位,真正 Ozon 首次发布 job 尚未接入。
- 验证:草稿费率配置、定价 HTTP/PostgreSQL 和商品编辑 HTTP/PostgreSQL 共 26 项通过;contracts/API/Web 类型检查和构建通过,`git diff --check` 通过。隔离浏览器打开现有门店的定价方案页,确认旧“当前使用开发草稿费率”提示已消失。未重启维护者服务,未进行真实上架。
### 2026-09-28:SKU 定价试算与确认
- SKU 采购价失焦/回车自动计算、手动算价、批量计算和保留手动售价;明细弹窗比较运输方案、调整参数并应用当前 SKU。