Commit Graph
108 Commits
Author SHA1 Message Date
yml2213 4dc2f5ca90 fix(claim): 统一所有买家领取链接为 H5 订单号格式 2026-11-02 22:11:22 +08:00
yml2213 3989b0a649 fix(admin): 修复履约渠道分页并统一列表分页状态 2026-11-02 19:49:31 +08:00
yml2213 d871b93fde feat(admin): 增加履约渠道批量删除并统一分页配置 2026-11-02 17:31:55 +08:00
yml2213 55e3c4e21b test(fulfillment): 清理履约集成测试生成数据 2026-11-02 15:49:33 +08:00
yml2213 6bf28489e0 fix(finance): 重写履约路由迁移与统一渠道配置
重写 120/121 迁移,统一内部 SKU、渠道 id、config_json 和旧规则转换。

后台渠道配置改读统一渠道表,卡券与人工配置不再写旧规则。

增加安全渠道切换,并排除已关闭、失败或过期的历史任务载体。

按生产 119 基线重跑迁移、完整履约财务链路和严格预检。
2026-11-02 15:29:13 +08:00
yml2213 2f87445ed9 fix(finance): 收敛内部 SKU 履约路由与载体状态
统一内部 SKU 与渠道主/兜底解析,禁止并列主渠道。

运营指定渠道改为先创建真实载体,失败保持明确 pending。

历史缺载体、多载体冲突和自动发货兜底统一由管道修复。

迁移人工配置与旧 sku_code 规则,补充严格预检和集成测试。
2026-11-02 15:02:49 +08:00
yml2213 5fe33b0b46 feat(finance): 统一内部 SKU 驱动的履约与财务分流
- 新增 internal_sku_mappings / internal_sku_channels,平台字段统一映射到内部中文 SKU
- 下单入口按内部 SKU 渠道决策修正默认人工路由,自动发货补全 dash sku
- 财务 channel_assign 读取统一渠道表;卡券/人工能力兜底,自动发货/接单要求真实载体
- carrier reconciliation 自动补自动发货任务和接单工单
- pending 落明确原因:无内部 SKU / 无渠道能力 / 无履约载体
- 合并、重判、旧 sku_code 规则清理、部署后 preflight 核对脚本
- 待分类队列按内部 SKU 聚合并展示原因
2026-11-02 14:17:08 +08:00
yml2213 531a23d78b feat(finance): 下单入口补内部 SKU,卡券/人工按商品能力兜底
- 纯数字/空内部 SKU 入口查 internal_sku_mappings,补 spec.skuNick
- 快照记录 internalSku/source,便于审计
- 财务 channel_assign 对卡券/人工使用商品渠道能力兜底(source=auto_mapping)
- 自动发货/接单仍要求真实任务/工单载体,避免只改口径
2026-11-02 13:52:40 +08:00
yml2213 a501f9f2e0 feat(finance): 内部 SKU 平台字段映射基础
- 新增 internal_sku_mappings,支持 provider/shop 级和全局映射
- 新增解析与 upsert 服务,priority/精确范围优先
- 新增纯数字内部 SKU 的中文映射回填脚本(默认 dry-run)
2026-11-02 13:49:31 +08:00
yml2213 03566aee2b fix(finance): 待分类队列按内部中文 SKU 去重与分流
- 同一内部 SKU 的不同平台 SKU 合并为一行(显示平台 SKU 列表)
- 指定渠道按 internal_sku 批量更新,并生成 internal_sku 规则
- 渠道候选的 internal_sku 优先取中文 manual_sku_key/sku_name
2026-11-02 13:32:05 +08:00
yml2213 3c4c81003f feat(finance): 商品渠道能力、自动发货转人工与成本异常收口
- 商品可同时支持自动发货/人工,新增渠道能力与成本冲销字段
- 卡券缺商品时按内部中文 SKU 自动建 tpv: 商品并补渠道规则
- 自动发货失败转人工并冲销原渠道成本
- 配置成本后按最早缺失订单生效并立即补算、关闭异常
- tpv: 商品来源计入第三方卡券
2026-11-02 13:17:15 +08:00
yml2213 fd6d2d561b feat(pipeline): 渠道判定后立即归一商品并算成本
- 新增按订单项定向归一,避免新判定订单等冷通道
- 判定/指定渠道后立即归一 → 算成本 → 按业务日回填事实与总账
- 提取 refreshFactsForDates 供管道与渠道服务复用
2026-11-01 15:21:53 +08:00
yml2213 fca836eb4b feat(cost-center): 卡券商品创建即生成渠道规则,补齐成本项预设
- 新建 tpv: 商品时自动写 third_party_voucher 规则,避免新卡券 SKU 停在待分类
- 成本项预设新增「第三方卡券采购成本」
2026-11-01 14:46:14 +08:00
yml2213 a62f6e1ec8 fix(pipeline): 变更按业务日回填,异常自动收口,载体管道加游标
- 渠道判定/成本快照返回受影响业务日,任务按日重算事实与总账
- 人工配置或载体补齐后,manual_config_missing / carrier_missing 自动关闭
- carrier_dispatch 使用水位游标,避免每轮从 id=0 重扫
2026-10-31 20:41:43 +08:00
yml2213 6cd6401eca refactor(finance)!: 事实维度与接口字段统一改名 channel
- migration 114 将 sales_daily_facts.fulfillment_mode 重命名为 channel
- DTO/查询参数/前端类型从 fulfillmentMode 统一为 channel
- 成本中心类型 FulfillmentMode 更名为 FulfillmentChannel,并补齐卡券/待分类/归档取值
- 销售事实响应分组改为 byChannel
2026-10-31 20:26:15 +08:00
yml2213 d979ef50d6 perf(pipeline): 订单项管道改用水位游标并只扫缺失
- 新增 watermark-store:统一读写游标/日水位/失败原因
- 渠道判定、商品归一、成本快照从上次游标继续,到表尾后回绕重试
- 成本快照只处理没有有效快照的订单项,避免每 5 分钟全量重扫
2026-10-31 20:17:33 +08:00
yml2213 0ce3c8fa97 feat(fulfillment): 渠道联动与管道兜底
- 人工配置保存/删除同步渠道规则,人工确认写 channel/status
- 按 SKU 指定渠道默认同时落规则
- 管道补充:载体缺失、人工成本未记录、事实与总账按水位追赶
2026-10-31 19:52:22 +08:00
yml2213 65b7f4f9dc refactor(finance)!: 强制渠道模型,移除旧履约方式与同步链路
- 删除 fulfillment_mode 相关的旧同步/回填链路与定时任务
- 删除 cost_finance_sync、成本快照同步、人工商品归一等遗留服务
- 迁移 113 直接删除 order_items.fulfillment_mode 及其索引约束
- 断代脚本自带归档步骤,不再依赖独立回填脚本
- 退款/事实/总账统一走渠道版销售事实
2026-10-31 19:52:03 +08:00
yml2213 8cdc2423d5 feat(fulfillment): 新增渠道判定管道,规则优先、载体证据兜底
- 只写 channel/status/source,不再由「有没有任务」反推渠道
- 同优先级多渠道判为冲突并保持 pending,进配置冲突队列
- 运营指定渠道即锁定,自动判定不再覆盖
- 待分类队列按 SKU 聚合,支持按 SKU 批量指定
2026-10-31 18:12:06 +08:00
yml2213 fba0a13d44 fix(fulfillment): 履约回填改用 keyset 分页并补充待回填部分索引
- 迁移 108:order_items (id) WHERE fulfillment_mode IS NULL 部分索引
  生产已 CONCURRENTLY 预建;取 5000 条待回填 id 4.8s → 4.9ms
- reconcilePendingFulfillmentModes 增加 afterId / lastScannedId,批内固定 id > 游标
- 新增 resolveReconcileCursor:游标单调前进,未前进或不足一批即结束
- backfill-fulfillment-mode 支持 --afterId 断点续跑
2026-10-29 15:10:28 +08:00
yml2213 63ae32d18c refactor(finance): 成本模型与履约方式正交,拆分成本中心巨型文件
后端:
- 删除 services/admin/admin-cost-center-service.ts(4,248 行),拆为
  services/cost-center/ 下 5 个模块:
  cost-center-shared(类型/枚举/归一化/映射/costModelScopeSql)、
  cost-center-overview(总览与选项)、
  product-catalog(商品与渠道映射)、
  template-bootstrap(模板引导、自动发货同步、工单证据回填)、
  cost-definition(成本项/版本/异常/预览/快照)
- cost_items.carrier_type / cost_type 改为单一 cost_model;专属模型只对
  对应履约方式生效,通用模型对所有履约方式生效
- cost_snapshots / cost_exceptions 删除载体列;按履约方式筛异常改用
  IN 半连接(248k 异常下 EXISTS 逐行回表 2.7s -> 170ms)
- sales_daily_facts.carrier_type -> fulfillment_mode
- 人工支出按 cost_model 归类;履约方式只读 order_items.fulfillment_mode
- 移除 syncOpenCostExceptionCarrierTypes:异常表已无载体列可同步

前端:
- AdminCostCenterPage.tsx(2,887 行 -> 18 行转发),拆为
  pages/admin/cost-center/ 下 8 个 Panel + shared + CostCenterContext
- CostCarrierType 删除;新增 FulfillmentMode / ProductSource / CostModel
- 销售毛利页 carrierType -> fulfillmentMode

同步补两个索引:idx_order_items_fulfillment_id(异常半连接)、
idx_work_categories_name(商品目录分类 lateral join)。
2026-10-23 16:06:25 +08:00
yml2213 5d1ba11523 feat(finance): 统一履约事实并改造人工账单分类 2026-10-23 13:35:48 +08:00
yml2213 4b081d88c5 feat(douyin-mashida): 抖音按 SKU 三层分类接入(对齐 91/快手)
- sku_code 恒为内部 SKU(不再被英文 sku 覆写);英文 sku / 引流标题分别落 snapshot
- 命中映射 → affiliate_dash;未命中不再兜底 manual_dispatch(无执行载体 = 待人工,不建任务)
- 抖音映射支持「常量表 + 后台 skuMapping 增量」,新增商品不必发版
- 载体唯一守卫:命中自动发货的订单项不再建工单
- 券 cert_link 与命中解耦(/h5 一律按订单号拼);券写入工单 material_json.douyinMashidaVoucher
- 新增/修正 16 例单测;后端全量 717 例 / 0 失败
2026-10-14 13:00:49 +08:00
yml2213 4fce07a621 refactor(douyin-mashida)!: 纠偏——删掉自建的皮肤通道,改回复用 affiliate_dash
上一轮我把皮肤交付做成了「另建一套执行器 + 独立领取接口 + 只提交账号就结束」,
跟买家实际要走的过程不一致(真正的完成信号是「扫码绑定后的 UID == 买家填的 UID」),
而且核销还触发了老通知逻辑,给买家**又发了一条 /redeem** —— 买家收到两条链接。
本次按用户要求改回**完全复用仓库现成的 affiliate_dash 通道**(= 旧的快手皮肤自动发货)。

**删掉**
- 执行器 `douyin_mashida_skin`(含 registry/types/planner/bootstrap/路由白名单注册)
- `services/claim/claim-skin-service.ts`、`routes/claim-skin.ts`、`/api/v1/claim-skin` 挂载
- 迁移 096 的 `claim_submission_json` 全链路(task-repo / rows / inputs / task-detail /
  admin-read-service 的 claimSubmission),并新增 **097 兜底迁移**把该列 DROP 掉
- 顺带清掉上一轮专为已删接口加的死代码(utils/http.ts 的 buildMessageSuccessPayload 等)

**改回复用**
- `resolveOrderItemClaimLink`:通用解析(只看订单项、不看执行器)→
  `buildConfiguredClaimUrl(claimLinkBase, token)`;多履约单元取 task id 最小并告警;
  **绝不回退** hash 形态的 `buildClaimUrl`
- `cert_link` 与付款后那条**唯一**消息共用同一个解析结果
- **核销后不再给抖音买家发第二条消息**(`shouldNotifyBuyerAfterVerify` 只放行非抖音 provider)
- 买家侧走既有流程:输 UID → 二维码 → 扫码绑定 → 比对 UID → delivered/REDEEMED;
  在 delivered 分支 best-effort 核销平台券(幂等、失败只 warn,不拖慢买家响应)
- 后台回显链接改按 **order.provider** 判断(抖音用 `claimLinkBase`)

**SQL 守卫**:允许「删除历史迁移」,但强制要求「同时新增兜底迁移」配对
(修改历史迁移仍禁止),并把改动来源换成 `git status --porcelain`(否则未跟踪的新迁移看不见)

`npm run check`:tests 671 / pass 668 / fail 0 / skipped 3(含新增的物品图回退用例)
2026-10-09 16:13:39 +08:00
yml2213 56ad06239b fix(fulfillment): 抖音未命中皮肤映射时显式回落人工,避免静默漏单
原本未命中的抖音订单项只靠全局 `unmatchedExecutorKey` 兜底,而线上/联调环境该值
可能是空串(dev 库实测就是 `unmatchedExecutorKey=''`)——那种配置下未命中的抖音订单
既不建履约任务、也不进人工,等于**静默漏单**(需求要求的是「接单平台走人工」)。

改为在抖音分支里显式指定回落:命中权威映射 → `douyin_mashida_skin`;
未命中 → 直接以 `preferredExecutorKey=manual_dispatch` 选中人工通道,不依赖全局配置。

实测(dev 真实配置,`unmatchedExecutorKey` 为空串):
  幸运币2个 / 套装-浪漫天命   → douyin_mashida_skin(isConfigured=true)
  代练上分-星耀到王者(未命中)→ manual_dispatch(isConfigured=true)
  空 SKU                      → manual_dispatch
  对照 91卡券/快手             → 行为不变(未配映射仍 isConfigured=false)
2026-10-09 15:09:58 +08:00
yml2213 56a8184576 feat(douyin-mashida): 皮肤自动发货(按内部 SKU 分流 + 领取链接 + 买家领取接口)
抖音码速达的皮肤类商品改为「自动发货 + 领取链接」:买家不用输订单号,点链接直接领。

**分流(按内部 SKU)**
- 平台闸门放行 `provider='douyin_mashida' && platform='doudian'`,走**独立分支**
  (原有 91/快手路径一行未动,避免外溢)
- 判据:内部 SKU(`sku_order_list[].code`,即 order_items.sku_code)命中权威表
  `AFFILIATE_DASH_SKU_MAPPING` → 新执行器 `douyin_mashida_skin`;未命中 → `manual_dispatch`
- 皮肤判定与商品图同源(都用那张权威表),保证「能路由 ⇒ 有图」
- 履约路由新增 `internal_sku` 匹配维度(`rules[].internalSku`,NFKC+去空白+小写,exact/contains);
  旧规则缺 `matchField` 时默认 `product_name`,**归一化/优先级/回退顺序完全不变**

**执行器与领取 token**
- 新增 `douyin-mashida-skin-executor`:建 claim token、置 `link_generated/pending_claim`,
  `resolveDeliveryLink` 返回本站路径式领取链接;注册进 registry、planner 分支、
  bootstrap 种子 profile(`抖音皮肤自动发货`);进 `ROUTABLE_EXECUTOR_KEYS`
- token 粒度 = 一个履约单元一个(`claim_tokens.task_id` 唯一);一单多项时
  cert_link/买家消息取 task id 最小的那个并告警

**cert_link 与发消息**
- 皮肤订单且该订单项已有 token 且配了 `claimLinkBase` → `cert_link = claimLinkBase/token`;
  其它情况一律用 `certLink`(老行为不变)
- 领取链接**只认** `claimLinkBase`,绝不回退 `buildClaimUrl`/`orders.claimBaseUrl`
  (那是 hash 形式的打手领取页,语义不同)
- 付款建单+发券成功后按 `messageTemplate`(`{link}/{sku}/{orderNo}/{productTitle}`)
  经 `order.message` 发给买家;best-effort,失败只记 warn

**买家领取接口**
- `GET/POST /api/v1/claim-skin/:token`(限流、公开);详情含内部SKU/引流标题/商品图/
  数量/金额/支付时间/动态表单字段;token 失效给明确 errorCode(404/410/409),不打 500
- 提交账号:先核销平台券再落记录(避免「记账了但券没核销」的资损),已提交幂等

**隐私**
- 买家游戏账号落 `fulfillment_tasks.claim_submission_json`(迁移 096),
  **不进** `work_orders.material_json`(那是发给打手的素材);详情接口不返回券码明文/手机号/地址/open_id
2026-10-09 15:06:43 +08:00
yml2213 98dc675b88 Revert "feat(claim): Rock 同一提货号过期后自动换新二维码"
This reverts commit 9d981c253f.
2026-10-06 18:08:20 +08:00
yml2213andCursor 9d981c253f feat(claim): Rock 同一提货号过期后自动换新二维码
腾讯活动链接会过期,领取页不能一直用第一次的签名。过期后向 0666 重取同一提取码的新链接,不另发提货号。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-06 18:02:17 +08:00
yml2213andCursor 1239393fc2 perf: 筛选统计去掉 JSON 兜底,并补上 orders 覆盖索引
去掉 work_orders 堆访问后,JOIN 会把 orders 整表扫进 Hash Right Join。
领取页在快照新鲜时不再打上游;快手出网统一 10 秒超时。倒计时改为自适应间隔。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 15:05:38 +08:00
yml2213andCursor b7d246e5b9 fix(admin): 任务列表商品名与执行器标签改为中文展示
建单时不再把英文 sku 写入商品名,列表按映射反查中文名,并将 Affiliate Dash 等标签本地化。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 13:03:47 +08:00
yml2213andCursor b2d92d1559 style: 修复 claim/affiliate-dash Prettier 格式
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 12:40:01 +08:00
yml2213andCursor 8e0cb7e295 fix(claim): 领取页展示游戏角色名,并说明乐玩免扫码场景
持久化 affiliate_dash roleName/gameChannel;免扫码授权时明确提示,有绑定链接时提交前仍可显示二维码。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 12:39:47 +08:00
yml2213andCursor e20505bc8e style: 修复 pre-push Prettier 格式检查失败
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 10:47:38 +08:00
yml2213andCursor 4a3b4ec14d refactor(fulfillment): 固化 91 中文名→英文 SKU 权威映射表
91 继续用中文编码;解析优先查内置常量表,配置仅作临时覆盖,Admin 改为展示权威表。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 20:33:42 +08:00
yml2213andCursor b3aad0044c refactor(fulfillment): 移除飞飞/乐玩通道,仅保留 affiliate_dash
新单只路由 affiliate_dash(未命中走 manual_dispatch);历史飞飞/乐玩任务保留只读 stub,避免订单重同步失败。同步清理 cloudtentacles 调度、Admin 写路径与相关 env。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 17:29:47 +08:00
yml2213 62049fa284 fix(manual-executor): 人工派单准备后电子凭证核销补充告警日志 2026-09-10 10:09:09 +08:00
yml2213 076b113ae5 feat(kuaishou-industry): 实现电子凭证自动核销推进器与查码流程优化
- 新增 voucher-auto-consume-service,对非发单平台大厅待发布任务实现生成即核销与发码成功闭环核销
- 严格保留发单平台待发布工单(pending_material/unassigned)在大厅发布时核销逻辑
- manual-executor 在任务生成进入 MANUAL_REVIEW 时直接触发核销
- send-code-service 在发码出站回调成功后自动调度非大厅任务的凭证核销
- 优化 query-code-service 查码接口,避免发码初期误报 4012002 订单不存在
- 标记废弃 kuaishou_feifei 渠道模块
- 补齐 voucher-auto-consume-service 单元测试用例
2026-09-10 10:01:40 +08:00
yml2213 81ae04dae0 接入 ESLint 并清理未使用代码
- 前后端接入 ESLint 10 扁平配置(typescript-eslint 类型感知检查 + react-hooks/react-refresh),新增 lint / lint:check / lint:fix 脚本并纳入 check 链路
- 清理全部 no-unused-vars 与 no-useless-assignment 警告,修复 floating promises、正则转义等问题
- 删除确认无引用的死代码(markKuaishouCloudBindUrlRefreshFailed、未使用 helper 等)
2026-08-16 18:04:55 +08:00
yml2213 5c7c3e14e3 统一前后端代码格式化配置 2026-08-16 17:27:12 +08:00
yml2213 e097ddad3d 支持领取链接长期有效 2026-08-11 14:06:29 +08:00
yml2213 e72c936986 优化履约路由回退策略 2026-08-11 11:38:47 +08:00
yml2213 3d747aa5aa 补全历史履约通道优先级 2026-08-11 11:00:11 +08:00
yml2213 49705f2774 优化 affiliate-dash 商户单号 2026-08-11 09:48:05 +08:00
yml2213 bcde47ef97 彻底修复 lewan 自动发货问题-8-8-2 2026-08-08 23:43:29 +08:00
yml2213 6e41d7e0db 彻底修复 lewan 自动发货问题-8-8 2026-08-08 23:08:05 +08:00
yml2213 7196752d44 失效号码清理下沉到刷新流程:所有触发路径(claim轮询/91交付/回收/后台)遇无权限号码统一清空绑定,不再反复打上游 2026-08-08 15:14:59 +08:00
yml2213 5a1c5a3759 回收遇无权限号码直接清空任务绑定不再重试:已手动退号的旧绑定一次性收敛,发货收尾视号码已释放 2026-08-08 14:59:23 +08:00
yml2213 2b3954d0e3 修复履约路由总开关关闭后仍回退默认配置自动发货:总开关关闭即停止自动履约 2026-08-08 14:56:28 +08:00
yml2213 6d0534296c 修复取号账号与退号账号混用:操作已有号码严格锁定取号账号,禁止静默 fallback 到其他账号 2026-08-08 14:23:11 +08:00
yml2213 995de86322 修复 lewan 虚拟号配额被占满:过期绑定自动回收、退号失败不再追加取号、取号占满增加冷却 2026-08-08 02:15:13 +08:00