Offer 基础信息拉取 PRD

初评 + 系统设计

DDD 框架已就位 | 本期 = 口径修正 + BI 取数出口

2026-06-18 · 联盟 Offer 元属性接入(一期 Awin + Impact)

一句话结论

值得做,且高度可行——本期硬目标的 DDD 框架(独立表 blueaff_offer_declared_metrics + IDeclaredMetricsParser 注册表 + 严格镜像 persistence + 同步链路 + admin 透出)已全部落地

本期实为「口径修正 + BI 取数出口」的小增量,而非从零构建。

置信度
1
头号待核实矛盾
4
阻塞待澄清

⚠️ 这是初评,非最终方案。置信度封顶为「中」:因存在一处头号待核实矛盾 + 多个阻塞性范围澄清,且 BI 落点链路在本仓库未定位。

🚩 头号待核实矛盾(开工前必须拍板)

Impact avg_payment 是否需要 ContractStatus(LOCKED/INVOICED) 分支?

来源结论
专家评估 R9 / scope_do「需改为按 ContractStatus 分支才补 Locking 段」(列为本期范围)
反驳核验 + 代码/spec 复核PRD §2.3 原文是 LOCKED/INVOICED → 折算(Locking)+折算(PayoutScheduling)——两状态共用同一公式,并非两条分支impact_offer.py:240-256 已无条件实现该公式;活跃 spec 亦无分支要求。

R9 所称的「待实现分支」很可能根本不存在。这一条推翻了上一轮"按 PRD 加 ContractStatus 分支"的决策——严禁据此直接动 get_average_payment_time

5 分钟人工复核命令:

sed -n '88,96p' offer-basic-info/raw/prd-original.md          # avg_payment 是否真要求按状态产出不同结果
sed -n '240,266p' commons/entities/offers/affiliates/impact_offer.py   # 现实现是否已是 Locking+PayoutScheduling
sed -n '60,70p' openspec/specs/offer-declared-metrics/spec.md  # 活跃 spec 是否要求分支

若复核确认无分支要求 → Impact avg_payment 本期零改动,口径修正收缩为「仅 Awin 拒单率量纲一处」。

一、PRD 评估 · 需求明确度

明确

  • R1 一期覆盖 Impact + Awin
  • R2 两类来源模型 raw / calc
  • R3 本期只落 network_raw
  • R4 上游 6 字段
  • R5 只调静态属性,不碰流水
  • R14 后续期 6×18 覆盖矩阵
  • R15 拒单率仅 Awin 覆盖全

部分明确

  • R6 Awin 映射(avgPayTime 语义需实测)
  • R7 Impact 折算公式
  • R8 Awin 拒单率量纲(PRD 未回写)
  • R10/R11 中台双栏(Network 就绪/BlueAff 未做)

待澄清

  • R9 Impact avg_payment 分支 (前提存疑)
  • R12 Portal §1.2 自算新取值
  • R13 本期边界(与 callout 张力)

本期做 / 不做

✅ 本期做

  • 按两类来源模型接入,只落 network_raw 原始保真值
  • Awin + Impact 6 字段静态元属性拉取(拿到入库,拿不到 NULL)
  • 沿用已落地的 declared_metrics DDD 范式
  • 口径修正 (范围以头号矛盾复核结果为准)
  • 其余一级联盟逐家迭代接入

❌ 本期不做

  • 不算 blueaff_calc 新规则;calculate_offer_metrics.py 保持原样
  • 不做 §1.2 Portal 字段自算新取值
  • 不实现 TradeDoubler / 不爬 HTML / 不接调研中(0) 联盟
  • 不碰联盟订单 / 流水接口
  • 不触 Portal(apps/、api/ v2)展示与取值

待澄清阻塞项(需 PRD 方书面锁定)

阻塞 开工前必须锁定

  1. 一期范围张力:callout「页面不更新仅 BI 加值」 vs §0.1「portal 数据更新」 vs §3.1/§3.2「中台双栏 + Portal 红框」——验收无基准
  2. §1.2 Portal 自算本期是否实现?(memory 决策为不做,需责任方认可收窄)
  3. 中台 §3.1 BlueAff 栏数据来源:现 metrics 表 Awin EPC 仍混存,直接透出还是剥离?
  4. 本期联盟交付家数:仅 Awin+Impact,还是纳入 §2.3 已给映射的其余一级联盟?

非阻塞 需回写 / 确认

  1. Awin 拒单率最终量纲(PRD 文字 1-x/100 vs 代码现状百分数原值)
  2. Impact INVOICED 地板值是否需打标 / 告警
  3. BI「加联盟原始值」落点形态(admin View 透出 vs 独立 BI 表)

二、可行性方案

A · 改动最小

收敛到 callout 唯一硬目标:口径对齐 + 复用 admin 透出/直读表作 BI 出口 + 确认同步覆盖。

+ 侵入面最小,无 DB 迁移,当天可上线

- 仅覆盖 Awin+Impact;拒单率改归一属破坏式变更

B · 风险优先

四阶段受控,每阶段前置核验闸门:口径基线先冻结再扩面;联盟逐家迭代。

+ 规避数仓量纲不可逆,逐家验证不互污

- 接入速度慢;可能需停下对齐甚至回刷

🎯 推荐 · A范围 + B闸门

用 A 的最小改动范围,给口径修正套上 B 的前置闸门。

闸门:①量纲书面对齐+落注释 ②锁定 callout 范围 ③Impact 分支先复核 ④联盟接入前确认鉴权/限流

框架已落地使「最小改动」真实可行;口径不可逆必须用闸门兜住 —— 两者结合最优。

三、系统调研 · 已就位

本期硬目标的基础设施基本齐全(均带来源,本次已复核)

  • 独立表 blueaff_offer_declared_metrics:5 字段(epc/cvr/rejection decimal、avg_payment/lock int),均 null=True,OneToOne→offer offer.py:342-371
  • cookie_period 归主表 blueaff_offer(BigInteger),不在声明值表 offer.py:33
  • 自算表 blueaff_offer_metrics 与声明值表物理隔离,互不触发清理 offer.py:313-339
  • Parser 注册表 _DECLARED_METRICS_PARSERS 仅 awin/impact,其余走 Default 全 None declared_metrics.py:162-174
  • 同步链路 update_attributes 已纳入 declared_metrics 与 cookie_period network_offer_synchronizer.py:89-124
  • 写入 DeclaredMetricsPersistence.save update_or_create 全字段(None→NULL 严格镜像)declared_metrics_persistence.py:19-127
  • 下游:admin 列表 + 详情已透出 5 个 network_* 字段(Network Performance 数据已就绪views.py:670-980

三、系统调研 · 现状缺口

  • ⚠️ BI「加联盟原始值」独立导出链路未定位——消费方仅 admin View 透出 JSON;api/ 与其他 commands grep 无命中
  • ⚠️ 中台 §3.1 BlueAff Performance 双栏未实现(View 仅 network_raw 一栏)
  • ⚠️ Portal §1.2 新取值逻辑未落地——summary 仍读旧 metrics + 主表字段
  • ⚠️ PRD §2.3 子表 impact_event_payout / Admitad actions_detail 在工作树未找到,属未落地
  • 声明值表无 DB 迁移文件(项目 DB-first / 外部建表)
  • 其余 16 联盟 Parser/connector 均未实现(一期边界内的现状)

四、系统设计 · 数据流

沿用既有单向链路,无新链路

列表接口(joined/active) → 逐 offer 字段接口(programmedetails / Contracts/Active)
   → affiliate_offer._declared_metrics_payload()
   → parse_declared_metrics()  [按 network 取 Parser]
   → aggregate.load_declared_metrics()
   → save_offer_aggregate()    [同事务]
   → DeclaredMetricsPersistence.save()  [update_or_create 镜像]
   → blueaff_offer_declared_metrics
   → ba_admin View 透出 / BI 直读表  ⟶  OP 看数

本期复用现有表,不加列、不迁移(5 字段已覆盖,cookie 在主表)。

四、系统设计 · 改造点最小集

按闸门顺序(待量纲/矛盾拍板后再动):

  1. 口径修正
    • Awin 拒单率/转化率量纲:若归一,单点改 AwinDeclaredMetricsParser改前 grep network_rejection_rate 全项目消费方;若保持现状则零改动 + 回写 PRD 勘误
    • Impact avg_payment:⚠️ 依赖头号矛盾复核——确认无分支则零改动
  2. BI 取数出口:复用 admin 透出,或给 BI 一条只读查询,无需新写后端看板
  3. 同步覆盖确认:已就位,本期不动
本期明确不改:calculate_offer_metrics.py · Portal(apps/、api/) · 中台 §3.1 双栏 · §1.2 自算 · 中间件/认证 · 其余 16 联盟 connector

风险与应对

风险严重度应对
一期范围自相矛盾,验收无基准开工前书面锁定 callout vs §0.1/§3 边界(闸门②)
量纲不可逆 / BI 历史不可比修正前对齐唯一量纲、固化表注释,必要时回刷(闸门①)
save 严格镜像 None→NULL 抹除历史区分「确不提供」与「响应异常」;核验证明 Cloudflare 拦截会 raise→跳过 offer,风险窗口比初判窄
18 联盟鉴权/限流各异、期望膨胀逐家独立排期 + 限流/重试,本期不铺开
Impact 折算线性近似 / INVOICED 地板值BI 标注该列为近似/下界估计,非对账权威
Portal §1.2 价值本期不兑现向业务方明确分期预期

🗑️ 被剔除结论(反驳核验的价值)

12 条风险 → 反驳核验剔除 7 条伪高危,存活 5 条。事实多属实,但定性夸大或语境错配:

  • Awin 拒单率量纲冲突属高危 → 有意自洽决策(4 处一致),仅需 PRD 一行勘误
  • Impact 未实现 LOCKED/INVOICED 分支分支不存在,代码已正确、spec 已批准
  • cookie 跨表 + 与 Attribution Period 共用列覆盖 → 事实错误,两列分立无覆盖
  • 中台双栏未实现是中危缺口 → 属后续期范围,计算规则未定无数可填
  • EPC 系数四处不一致差 25% → 数学错误:÷1.25 = ×0.8,与兜底一致
  • declared_metrics 变更检测漏更新 → 机制描述错误,save 无条件全字段覆盖
  • Cloudflare 拦截拉空 NULL 覆盖致 BI 全空 → 拦截时 raise→跳过 offer,走不到 save
启示:这 7 条若不做反驳核验,极易把「已有设计 / 有意取舍 / 文档措辞」误判为待修缺陷而返工。

收尾 · 下一步

28
subagent fan-out
5 / 12
风险存活
7
伪高危剔除
置信度

下一步:先与 PRD 方对齐 头号矛盾 + 4 个阻塞项,再走 prd-workflow 正式模式(人在环串行,产出 decision.md + technical.md 最终对齐文档)。

这是初评,非最终方案。技术设计在阻塞项锁定前不应固化。