guke
b3c4898c5d
fix(alembic): cps_v2_platforms 兼容 SQLite 且可重跑
...
batch_alter_table 包 ALTER(SQLite 无原生 ALTER COLUMN),server_default 按方言分叉(PG ::jsonb / SQLite 纯文本),add_column 加 _has_column 存在性守卫,让历史半应用的 SQLite 库自愈重跑。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-25 16:21:50 +08:00
marco
b1849834f7
fix(alembic): merge meituan_coupon_image_meta 与 comparison/ad 双 head
2026-06-24 20:50:21 +08:00
chenshuobo
b07ccb4bf5
feat(meituan-coupon): 采集记录头图大小/类型 + 读取侧缩放口子 + 回填脚本 ( #71 )
...
Reviewed-on: #71
Co-authored-by: chenshuobo <chenshuobo@wonderable.ai >
Co-committed-by: chenshuobo <chenshuobo@wonderable.ai >
2026-06-23 21:09:10 +08:00
marco
e81fd0a176
fix(alembic): 合并多 head( #65 device 迁移 + comparison_token_cols)
...
#65 的 device 迁移链与 comparison_token_cols 都从 ceb286289426 分叉成双 head,alembic upgrade head 报 Multiple head revisions;加 merge 迁移 4dc2af7ebe74 合并(空 DDL 仅接链)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-23 17:58:30 +08:00
chenshirui
a6f55a00b8
feat(device): 无障碍保护存活心跳检测 + 掉线后置检测(pull) ( #65 )
...
Co-authored-by: 陈世睿 <2839904623@qq.com >
Reviewed-on: #65
Co-authored-by: chenshirui <chenshirui@wonderable.ai >
Co-committed-by: chenshirui <chenshirui@wonderable.ai >
2026-06-23 17:33:38 +08:00
marco
a584e1f59f
feat(comparison): 比价记录累计 LLM token(入/出)并在 admin 展示
...
server 从 llm_calls[].usage 累加 prompt/completion_tokens 落库,admin 比价记录列表/详情据此展示 token 数与估算成本;配套迁移 comparison_token_cols。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-23 17:24:54 +08:00
chenshuobo
f868414966
feat(feedback): 补齐反馈历史审核发奖闭环 ( #66 )
...
- 新增反馈审核字段和迁移,支持 pending/adopted/rejected、未采纳原因和采纳金币
- 增加用户端反馈历史 records 接口和 admin 采纳/拒绝接口
- 采纳时同事务写状态、金币流水和审计日志,拦截重复审核
- 验证:pytest tests/test_feedback.py tests/test_admin_write.py tests/test_admin_read.py
---------
Co-authored-by: lowmaster-chen <1119780489@qq.com >
Reviewed-on: #66
Co-authored-by: chenshuobo <chenshuobo@wonderable.ai >
Co-committed-by: chenshuobo <chenshuobo@wonderable.ai >
2026-06-22 23:18:42 +08:00
zhuzihao
8a2f72d366
feat(user): 昵称上限放宽到 20 字(与客户端/原型一致) ( #63 )
...
Co-authored-by: zzhyyyyy <2685922758@qq.com >
Reviewed-on: #63
Co-authored-by: zhuzihao <zhuzihao@wonderable.ai >
Co-committed-by: zhuzihao <zhuzihao@wonderable.ai >
2026-06-21 00:16:40 +08:00
marco
f7a3ef2e0b
feat(internal): 启动确认窗 agent 兜底样本落盘(pricebot 回写)
...
- 新增内部端点 POST /internal/launch-confirm-sample(X-Internal-Secret 鉴权):
pricebot 对没见过文案的启动确认窗用 LLM 兜底放行后,把样本(host 包 / 弹窗树 /
LLM plan / 设备 locale 机型)回写落 launch_confirm_sample 表,供研发人工沉淀回
pricebot 规则 yaml
- 配套: model LaunchConfirmSample + schema + repo(都上报不去重) + alembic 迁移
launch_confirm_sample_table(down_revision=cps_wx_user) + main 注册 router +
models/__init__ 登记
- docs: 后端技术实现.md 加 §6.5 pricebot 回写内部端点说明
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-20 13:39:45 +08:00
marco
7fd70a264d
feat(cps): 微信网页授权接入——落地页拿 openid/昵称头像,用户级群统计
...
- 服务号网页授权(WX_MP_APPID/SECRET,区别于 App 的 WECHAT_APP_ID):
落地页 base 静默拿 openid;点「领券」补 userinfo 拿昵称头像(交互触发避快照页)
- 新表 cps_wx_user + cps_click 加 openid + 迁移;integrations/wx_oauth
- /c/{code} 授权链路 + 回调 /wx/oauth/cb + cookie 免重复授权;click 带 openid
- admin 群详情加「群内微信用户」(领券画像)端点
- 下单归因到人需 user-level sid,本期只做身份+领券侧
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-19 11:44:11 +08:00
marco
a2fd666203
feat(admin): 比价记录 debug 页后端——补全链路 + DB 迁移
...
model/schema 的 debug 字段已在 4ee6de2 起头,本次补完整条链路:
- repo upsert 存客户端环境/性能字段;端点同机拉 pricebot llm_calls 落库 + 算 llm次数/重试
- schema 加 platform_results 透传(admin「卡在哪一步」从 raw_payload 读)
- admin 比价记录查询接口(按 user_id/phone 列表分页 + 详情含 llm_calls)
- 迁移 comparison_debug_fields: 给 comparison_record 加环境/性能/llm_calls 列(全 nullable)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-17 22:33:33 +08:00
marco
d55f47fc59
feat(cps): 淘宝活动落地页图做活——每活动关联图,运营上传/选已有
...
- model: cps_activity.image_url + 迁移 cps_activity_image 回填存量淘宝活动为现有图
- admin: 新建淘宝活动必传图(上传 /upload-image 或选已有 /activity-images),存绝对 URL
- 落地页 cps_redirect: 按 link→activity 取图展示,缺图兜底默认图,img src 经 html.escape
- media: save_cps_image + to_abs_media_url(基于 CPS_REDIRECT_BASE,跨域 admin-web 可显示)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-17 21:32:10 +08:00
marco
3a40f617bd
feat(cps): 后端接入淘宝/京东多平台(payload + 群多平台 + 复制统计 + 迁移)
...
- model: cps_group.platforms 多选 / cps_activity.payload(淘口令/京东链接)
/ cps_link.sid 可空 + 复制统计
- admin API: 群与活动平台多选、批量生成落地页短链 referral-links、对账字段可空
- 落地页 cps_redirect: 淘宝展示淘口令(记 copy 事件) / 京东 302 / 美团原逻辑
- 迁移 cps_v2_platforms: 加 platforms/payload/event_type 列, sid 放宽可空(含 downgrade)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-17 19:21:20 +08:00
marco
277f9b16a2
feat(cps): 群发券分发与对账 + 短链点击追踪
...
群(sid)/活动池/转链(带sid)/美团 query_order 按 sid 对账/按群统计;
短链 /c/{code} 记点击(PV/UV)→302 跳美团,点击→下单漏斗。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-17 10:00:29 +08:00
marco
9d93b70b9b
feat(user): username 对外展示 + 默认昵称 + 存量回填
...
代提工作区既有的他人在制品(非本次 CPS);CPS 迁移链 cps_tables 依赖其
b3f1a2c4d5e6 迁移,需一并提交。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-17 10:00:29 +08:00
marco
f97048ff56
fix(alembic): 合并多 head (store_mapping_jd_dl_invalid + ad_revenue) 修复 0.1.2 部署
...
PR #56 的 jd_deeplink_invalid 迁移与 ad_revenue 报表迁移从同一 branchpoint
分叉成双 head, 部署时 alembic upgrade head 报 "Multiple head revisions"。
加一个 no-op merge 节点统一 DAG, 两支迁移列不冲突。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-16 01:39:05 +08:00
marco
f15ca74a22
feat(store-mapping): JD 缓存 deeplink 失效标记(对标淘宝) ( #56 )
...
Reviewed-on: #56
2026-06-16 01:25:57 +08:00
ouzhou
f7d86011c1
feat(ad-revenue): admin 广告收益报表(按 用户/日期/类型/应用/代码位 聚合) ( #54 )
...
- 新增 GET /admin/api/ad-revenue-report:展示条数/收益 + 复用金币审计逐条复算做发奖对账
- ad_ecpm/ad_reward/ad_feed_reward 各加 app_env + our_code_id 两列(alembic 迁移)
- ecpm-report / feed-reward 接收并落库 app_env/our_code_id;激励发奖按 ad_session_id 回填
- ad_audit 抽出 audit_rows,报表与逐条审计复用同一复算口径
- 组级 matched 改「组内逐条全一致」,避免应发和==实发和的互相抵消掩盖错误
- list_feedbacks 改 offset 分页并返回 total(配合 admin 页码分页)
- 反馈正文上限 _CONTENT_MAX 2000→200
- 文档:新增 admin-ad-revenue-report,更新 ecpm/feed-reward/feedback 及对应 db docs
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
---------
Co-authored-by: OuYingJun1024 <1034284404@qq.com >
Reviewed-on: #54
Co-authored-by: ouzhou <ouzhou@wonderable.ai >
Co-committed-by: ouzhou <ouzhou@wonderable.ai >
2026-06-15 23:13:14 +08:00
marco
9ec9d2389d
feat(store_mapping): 淘宝缓存 deeplink 失效检测→标记→回退(app-server 侧) ( #53 )
...
加 taobao_deeplink_invalid_at 列(迁移+model);mark_taobao_deeplink_invalid 按 shopId 标记所有行;lookup_nearest 过滤失效淘宝候选;新增 POST /internal/store-mapping/invalidate。+ 7 单测。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
Reviewed-on: #53
2026-06-15 18:07:32 +08:00
liujiahui
8fa55eec3e
fix(coupon): 领券弹窗频控按 App 独立 + debug 全重置补全 ( #52 )
...
bug: 弹窗 engagement 表只按 (device, 日) 全局记一条,美团弹过/领过就把整台设备当天
标记 engage,淘宝/京东被压住不弹。需求是美团/淘宝/京东各自独立、每日各弹一次。
改动:
- model: CouponPromptEngagement 加 package 列,唯一约束 (device,日) → (device,package,日)
- alembic: 新增迁移 coupon_engage_per_package(加列 + 改唯一约束, batch_alter_table)
- repository: has_engaged_today / mark_engagement 加 package 维度;新增 reset_today_completion
- api: should-show / dismiss 接收 package;coupon_step(step=0) 按 App 记 engagement;
补 /prompt/shown 接口(客户端一直在调但后端缺失, 原 404);
补 /completed-today/reset(开发设置全重置用, 解首页卡置灰)
验证: curl 端到端 —— 美团弹过后 should-show 美团=false 淘宝/京东=true;
shown/reset/completion-reset 端点全 ok。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
---------
Co-authored-by: no_gen_mu <liujianhishen@gmail.com >
Reviewed-on: #52
Co-authored-by: liujiahui <liujiahui@wonderable.ai >
Co-committed-by: liujiahui <liujiahui@wonderable.ai >
2026-06-14 23:41:54 +08:00
marco
8659a7ed2b
feat(store_mapping): 跨平台店铺映射表 + pricebot 内部上报端点 ( #48 )
...
新增「平台店铺表」资产层: 淘宝比价拿到 shopId 后, pricebot server→server 把跨平台
店铺身份(各平台 id/名 + 地理 + 来源)落库, 作为未来"我见过这家店→跳过重搜/匹配"的源头。
与 price_observation(价格事实)平行、独立。
- models/store_mapping.py: store_mapping 表 22 列 —— 跨平台身份(id/name_taobao/meituan/jd)
+ 地理(city/geohash/lng/lat/taobao_address) + 溯源(source_platform/trace_id/device/user)
+ 淘宝原料(share_url/resolved_url/deeplink) + attrs(JSONB) + created_at。
- schemas/store_mapping.py + repositories/store_mapping.py: append-only, trace_id 幂等
(pricebot 重试/replay 不重复写; 并发 IntegrityError 兜底返已存在行), 跨方言安全。
- api/internal/store.py: POST /internal/store-mapping(复用 price.py 共享密钥 X-Internal-Secret 校验)。
- 注册 model(__init__) + router(main.py); 迁移 store_mapping_table 接现 head coin_txn_task_ref_uq。
验证: alembic 单 head + 零模型/迁移漂移; TestClient 全链(无密钥401/有密钥inserted=1/幂等inserted=0/错密钥401)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
Reviewed-on: #48
2026-06-14 01:24:29 +08:00
ouzhou
8d7b91219a
feat(wallet): 解绑微信前对待审核提现二次确认 ( #46 )
...
## 改动
解绑微信前若有**待审核(reviewing)**提现单,首次解绑被拦下返回二次确认,用户确认后带 `force=true` 才真解绑。
- `schemas`: `UnbindWechatRequest{force}` + `UnbindWechatResultOut{needs_confirm, message}`
- `repositories`: `has_reviewing_withdraw`(只看 reviewing)
- `api`: `unbind-wechat` 接受可选 body(兼容旧无 body 客户端);`bound` 返回真实绑定态
- `docs/api`: 同步协议
## 为什么只拦 reviewing
reviewing 单解绑后审核打款会回读空 openid → 自动退回现金(钱不丢、只为让用户知情);pending 转账已在途、解绑影响不到,不拦。
配套客户端见 shaguabijia-app-android 同名分支。
🤖 Generated with [Claude Code](https://claude.com/claude-code )
---------
Co-authored-by: OuYingJun1024 <1034284404@qq.com >
Reviewed-on: #46
Co-authored-by: ouzhou <ouzhou@wonderable.ai >
Co-committed-by: ouzhou <ouzhou@wonderable.ai >
2026-06-13 03:53:43 +08:00
marco
e8bd12cc1f
feat(onboarding): force_onboarding 改设备维度 + admin 设备管理 + status 查询
...
废弃 force_onboarding(运营按用户强制引导,客户端不认——被 onboarding_completed 压过),
改用 onboarding_completion(设备+账号 维度),admin 直接增删该表记录控制重走。
- 删 force_onboarding: User 列 + auth/admin schema + admin 接口 + mutations + repo
clear + /onboarding/complete 调用 + 3 测试;新增 alembic 迁移删列
- admin 设备管理: 列设备(按 device 聚合) / 重置单设备 / 全部重置(清 onboarding_completion)
- 新增 GET /api/v1/user/onboarding/status: 客户端已登录启动查"本设备是否要重走引导"
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-12 00:51:47 +08:00
marco
5f9af204ea
fix(alembic): 合并 user_force_onboarding 与 comparison_idx/coupon_daily 双 head
...
#43 的 user_force_onboarding 迁移挂在 onboarding_completion 上,与
d4b87c5847de(comparison_status_created_idx + coupon_daily 合并、同样以
onboarding_completion 为父) 形成并列双 head,alembic upgrade head 报
Multiple head revisions,ecs1 部署会在迁移步失败未重启。
加纯合并迁移 9b894f5fff05 (Revises: d4b87c5847de, user_force_onboarding)
收敛为单 head,upgrade/downgrade no-op 不改 schema。本会话第 2 次、历史第 3
次此类问题(前为 a8c47fc4dc39 / be5e94e / f01db5d77dac)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-10 22:49:33 +08:00
zhuzihao
3d07461ef5
feat(force-onboarding): 运营一键开启新手引导 — User.force_onboarding + admin 接口 + /me 带出 + 走完自动清 ( #43 )
...
- User 新增 force_onboarding 列(仿 debug_trace_enabled)+ 迁移 user_force_onboarding。
- POST /admin/api/users/{id}/force-onboarding(operator 角色 + 审计 user.force_onboarding.set)。
- UserOut(/me 与登录响应)带出该字段;/api/v1/user/onboarding/complete 走完即自动清回 false,只触发一次。
- 测试:admin 设置+审计+角色守卫、走完引导自动清标记。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
---------
Co-authored-by: zzhyyyyy <2685922758@qq.com >
Reviewed-on: #43
Co-authored-by: zhuzihao <zhuzihao@wonderable.ai >
Co-committed-by: zhuzihao <zhuzihao@wonderable.ai >
2026-06-10 22:27:06 +08:00
ouzhou
db399a40fa
feat(admin): 首页门面数字保底/护栏 + 轮播种子真实化与批量 + 比价记录索引 ( #42 )
...
- ops_stat: 真实值 offset→保底(max);初始基数过只增不减护栏
- ops_marquee: 脱敏名手机尾号+中文昵称混合;金额长尾;时间随机抖动;真实+种子不足兜底补满;真实记录查询 ~30s 缓存
- comparison_record: 复合索引 (status, created_at) + 迁移(PG CONCURRENTLY);修复 alembic 多 head(merge 改挂 onboarding_completion)
- 轮播种子批量删除/启用接口 + ids 上限;docs 同步
- 附带并行会话 WIP:admin users / wallet
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
---------
Co-authored-by: OuYingJun1024 <1034284404@qq.com >
Reviewed-on: #42
Co-authored-by: ouzhou <ouzhou@wonderable.ai >
Co-committed-by: ouzhou <ouzhou@wonderable.ai >
2026-06-10 22:26:51 +08:00
zzhyyyyy
dacb37e3e1
feat(onboarding): 新手引导完成按 设备+账号 去重(表/模型/仓储/端点/迁移/测试)
...
- onboarding_completion 表(user_id+device_id 唯一约束)+ model + repository
- POST /api/v1/user/onboarding/complete 标记完成;登录响应 TokenWithUser.onboarding_completed
(按登录请求带的 device_id 判定是否已走过引导,跨卸载重装稳定)
- alembic 迁移 onboarding_completion(rebase 到最新 main 后已链在 coupon_daily_completion 之后,单 head)
- docs/database 文档 + tests/test_onboarding.py + run.bat(本地启动脚本)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-10 18:32:51 +08:00
liujiahui
0890e693d7
feat(coupon): 今日跑完整轮领券后端记录 + 查询(首页置灰源) ( #34 )
...
新增 coupon_daily_completion 表:按 (device_id, 自然日) 记"今天是否已跑完
整轮领券(到 done 帧)"。客户端据此把首页「去领取」卡置灰、不可点。
口径(用户决策 A 方案):到 done 即算,不管单券成败 —— 失败/跳过常是无障碍/
环境问题,重复点也补不回来。判断维度 device_id,与 engagement/claim 一致。
- model CouponDailyCompletion(uq device+complete_date,仿 CouponPromptEngagement)
- repo has_completed_today / mark_completed_today(幂等 upsert + IntegrityError 兜底)
- schema CouponCompletedTodayOut(completed: bool)
- coupon_step 透传链路在 action.command=="done" 那帧 best-effort 写完成记录
(pricebot 只在整轮全跑完才保留 command=="done",故无需再判 continue)
- GET /api/v1/coupon/completed-today?device_id= 供首页查询
- alembic 迁移 coupon_daily_completion(down_revision=0cf18d590b1d 当前 head)
合并后需 alembic upgrade head,否则 /completed-today 500。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
---------
Co-authored-by: no_gen_mu <liujianhishen@gmail.com >
Reviewed-on: #34
Co-authored-by: liujiahui <liujiahui@wonderable.ai >
Co-committed-by: liujiahui <liujiahui@wonderable.ai >
2026-06-10 16:07:33 +08:00
marco
be5e94ed6d
fix(alembic): 线性化 f8d3b1e60a27 接 a8c47fc4dc39,消除与 #33 mergepoint 平行的双 head
...
f8d3b1e60a27 最初基于旧 main(#31 双 head)写、down_revision 指向那对父;但 #33 已用 a8c47fc4dc39 合并那对 head,合入 main 后 a8c47 与 f8d3 平行 → 又成双 head,alembic upgrade head 报 Multiple heads、deploy 迁移会失败。
改 f8d3 的 down_revision 为 a8c47fc4dc39(线性接其后、只加两列),收口单 head。已 SQLite upgrade head 验证整链可 apply。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-10 15:43:54 +08:00
marco
953a05a5e6
feat(debug-trace): 调试链接权限 + trace_url 落库与按权限下发 ( #35 )
...
- user 加 debug_trace_enabled、comparison_record 加 trace_url
- 迁移 f8d3b1e60a27:加两列,down_revision 用 tuple 顺带合并既存双 head(invite_fingerprint_table + 044dce6e9b1f)
- UserOut 加 debug_trace_enabled → /me 与登录响应带出
- ComparisonRecordIn/Out 加 trace_url;upsert 落库
- /compare/records 列表与详情按 user.debug_trace_enabled 下发;详情连 raw_payload 里那份一并抹掉,防权限绕过
- admin 加 POST /users/{id}/debug-trace(operator + 审计),列表带该字段
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
Reviewed-on: #35
2026-06-10 15:35:08 +08:00
marco
cfc54ac2be
fix(alembic): 合并 invite_fingerprint 与 044 双 head 修复 Multiple heads 部署失败
...
#31 的 invite_fingerprint_table 迁移 down_revision 挂在 0cf18d590b1d,与 #30
的 044dce6e9b1f(ad_reward+withdraw 合并) 形成并列双 head,alembic upgrade head
报 "Multiple head revisions are present",ecs1 部署在迁移步失败未重启。
加纯合并迁移 a8c47fc4dc39 (Revises: invite_fingerprint_table, 044dce6e9b1f)
收敛为单 head,upgrade/downgrade 为 no-op 不改 schema。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-10 02:28:56 +08:00
xiebing
b2f5a53dd8
feat(invite): 被邀请人列表接口 + 指纹归因(任务3) ( #31 )
...
- GET /invitees: 分页 + 名字降级兜底(昵称→微信昵称→脱敏手机号)
- 指纹归因: 落地页采集 + (IP,设备型号)反查撞库 + 时间窗口闸
- test_invite: +5 个列表测试(脱敏/倒序/昵称优先/分页/空), 修指纹测试跨用例串味
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
Reviewed-on: #31
Co-authored-by: xiebing <xiebing@wonderable.ai >
Co-committed-by: xiebing <xiebing@wonderable.ai >
2026-06-09 21:48:48 +08:00
wuqi
a828b51d9f
feat(alembic): 添加合并广告奖励会话与提现安全的迁移脚本 ( #30 )
...
Reviewed-on: #30
Co-authored-by: wuqi <wuqi@wonderable.ai >
Co-committed-by: wuqi <wuqi@wonderable.ai >
2026-06-09 18:10:58 +08:00
ouzhou
d7c29c0883
feat(coin): 金币数值体系二期——看广告按 eCPM 发奖 + ad_session_id 幂等 + 签到膨胀固定金币 ( #28 )
...
- rewards: 激励视频实发改按 calculate_ad_reward_coin(eCPM, 当日第N次) 公式;AD_REWARD_COIN/MAX_AD_REWARD_COIN 降为历史兼容口径;新增 SIGNIN_BOOST_COIN=2000
- 签到膨胀: Day1-13 看完激励视频额外发固定金币、Day14 不允许 (signin.py / signin-boost)
- ad_session_id 幂等: ad_ecpm/ad_reward/ad_feed_reward 记录加 ad_session_id 列 + 唯一索引(新迁移 coin_reward_phase2 / ad_feed_reward_session)
- ad.py + schemas + repositories: ecpm-report / feed-reward / reward-status / test-grant 改造;config_schema 增 signin_boost_coin;admin stats overview 补充
- 同步 docs/api + docs/database + docs/integrations/pangle 及 tests(test_ad_reward / test_welfare)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
---------
Co-authored-by: OuYingJun1024 <1034284404@qq.com >
Reviewed-on: #28
Co-authored-by: ouzhou <ouzhou@wonderable.ai >
Co-committed-by: ouzhou <ouzhou@wonderable.ai >
2026-06-09 01:56:47 +08:00
ouzhou
6432497af1
feat: 后端接入微信提现人工审核与资金安全校验 ( #27 )
...
提现申请改为先扣款并进入待审核,审核通过后才发起微信打款,审核拒绝或微信失败时自动退款。
新增运营后台提现列表的关键词搜索、日期筛选、快捷筛选和排序参数,并支持批量通过、批量拒绝、批量刷新查单。
新增微信支付配置健康检查、现金账本校验、自动对账 worker 和单实例保护。
新增数据库唯一索引,约束同一用户未完成提现和同一提现单重复退款,提升并发安全性。
---------
Co-authored-by: OuYingJun1024 <1034284404@qq.com >
Reviewed-on: #27
Co-authored-by: ouzhou <ouzhou@wonderable.ai >
Co-committed-by: ouzhou <ouzhou@wonderable.ai >
2026-06-09 01:56:37 +08:00
marco
97f0fb210f
fix(alembic): merge coupon_state + invite 双 head 为单一 head
...
coupon_state_tables 与 invite_code_and_relation 都挂在 11a1d08c6f55 下、是兄弟迁移,
合 main 后形成两个 head,alembic upgrade head 会报 Multiple head revisions 致部署失败。
本 merge 迁移(无 schema 变更)把两条链并起来,恢复单一 head。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-08 05:54:55 +08:00
marco
4d392f44f5
feat(invite): 好友邀请后端(注册即生效,邀请人+被邀请人各发1万金币) ( #24 )
...
- user.invite_code 列 + invite_relation 表(invitee_user_id 唯一 = 幂等防重复发奖)
- GET /api/v1/invite/me(我的码+分享链接+战绩)、POST /api/v1/invite/bind
- 复用 wallet.grant_coins 同事务发币;自邀屏蔽 / 无效码 / 新用户闸(注册72h内才发)
- alembic 迁移(11a1d08c6f55 -> invite_code_and_relation)+ 8 个测试(钱路/幂等/并发兜底全覆盖)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
Reviewed-on: #24
2026-06-08 04:57:55 +08:00
marco
357ba27499
feat(coupon): 领券今日状态后端(弹窗频控 + 领券记录) ( #23 )
...
- 两张表 + Alembic 迁移:coupon_prompt_engagement(device×日,弹窗频控源)/ coupon_claim_record(device×券×日,领券记录·资产)
- coupon/step 透传顺手写库:step0 写 engagement(claim_started);响应解析 last_coupon_result/coupon_results 幂等写 claim record(按 coupon_id 去重,避免 done 帧 last 与 coupon_results 重复在 autoflush=False 下撞唯一约束回滚整批)
- 新增 GET /coupon/prompt/should-show(弹窗判据)+ POST /coupon/prompt/dismiss(拒绝通知,透传链路看不到拒绝)
- 判断按 device_id(券发到设备登录的外卖账号,比 user 更贴近登录环境);user_id 仅资产留痕、可空
- MVP 先不去重(队列照旧全发);pricebot 未改
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
Reviewed-on: #23
2026-06-08 03:20:51 +08:00
marco
ece41086cd
新增美团 CPS 券定时抓取入库(北京试点),作为"销量/佣金排序"的本地数据源 ( #18 )
...
背景:美团搜索/供给对销量排序支持差(实测乱序)、且有 402 限流和单次召回上限,不适合
每次实时打接口排序。改为定时把券抓进本地 meituan_coupon 表,查询时从库里捞、自己按
销量/佣金排。
本次内容:
- app/models/meituan_coupon.py:新表模型。字段尽量全(售价/原价/销量档/佣金率/佣金额/
门店/距离/品牌/图 等),raw 列存整条原始返回避免漏字段;(source, product_view_sign) 唯一。
- alembic/versions/meituan_coupon_table.py:建表迁移(挂在 withdraw_review_ad_watch 之后)。
- scripts/pull_meituan_coupons.py:ETL,抓 3 路并按 (source, product_view_sign) upsert:
1) 外卖·搜"外卖"(platform=1)翻到尽头
2) 外卖·搜"美食"(platform=1)翻到尽头
3) 到店·多业务线供给(到餐+到综+酒店+门票)翻到尽头
支持 --once(单轮,给 cron;线上每 1h)/ --loop --interval(本地循环,默认 10min)
+ 运行锁防重叠 + --prune-hours 清理陈旧券(默认 24h)。
- app/models/__init__.py:注册新模型。
实测:北京一轮约 2.5 分钟、入库约 2700 条;销量/佣金可直接从库里排序。
给接手同事:
- 仅北京(city_id 固定);v2 再加 per商圈 union 突破全城单次召回上限。
- 销量仅粗档位且约 51% 的券才有,查询需 WHERE sale_volume_num IS NOT NULL
(PG 的 DESC 默认把 NULL 排最前);佣金、价格 100% 有值。
- productViewSign/skuViewId 跨渠道会变,不能当全局 id;跨源去重用 dedup_key=md5(品牌|名|价)。
- 待做:查询接口(从库捞 + dedup_key 去重 + 按销量/佣金排,返回前端)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
---------
Co-authored-by: chenshuobo <1119780489@qq.com >
Reviewed-on: #18
2026-06-08 00:16:25 +08:00
ouzhou
766666601e
feat(platform): 首页门面三统计 + 运营后台展示模式配置 ( #22 )
...
Co-authored-by: OuYingJun1024 <1034284404@qq.com >
Reviewed-on: #22
Reviewed-by: marco <marco@wonderable.ai >
Co-authored-by: ouzhou <ouzhou@wonderable.ai >
Co-committed-by: ouzhou <ouzhou@wonderable.ai >
2026-06-07 23:17:27 +08:00
marco
f5d1a1a20d
feat(price-observation): 价格观测资产表 + pricebot 内部上报端点 ( #21 )
...
比价沉淀的价格事实(平台/门店/菜篮/到手价/时间/来源)无条件落库,server 侧存储、
与登录无关,独立于用户视角的 comparison_record。是未来"别人查过同店→秒回价格"
价格大数据的源头(先存数据,用法后续)。
- models/price_observation.py: 新增 price_observation 表。结构化列(平台/门店/价格/
红包/地理/来源)+ dishes/attrs 两个 JSONB 兜底列;(trace_id,platform,scope) 幂等
唯一约束;observed_at/store_name/geohash/source_device_id/source_user_id 等索引
- alembic/versions/price_observation_table.py: 建表迁移,down_revision=wx_transfer_auth
(已核为当前唯一 head,无多 head 风险)
- schemas/ + repositories/price_observation.py: 批量收发模型 + 跨方言(PG/SQLite)幂等
批量插入(先查 trace 已有 (platform,scope) 只插新的,并发撞唯一约束则回滚跳过)
- api/internal/price.py: 新增 POST /internal/price-observation,X-Internal-Secret 头校验
(常量时间比较,未配密钥→503),server→server 专用,不走用户 JWT
- core/config.py + main.py: 新增 INTERNAL_API_SECRET 配置 + 注册内部路由
- .env.example: INTERNAL_API_SECRET(须与 pricebot 侧同值,留空=内部写端点关闭)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
---------
Co-authored-by: pure <pure@192.168 .0.104>
Reviewed-on: #21
2026-06-07 03:31:35 +08:00
marco
b59dc3ac19
feat(wallet): 微信商家转账「用户授权免确认收款」(免确认到账) ( #16 )
...
提现从「每次跳微信确认」升级为免确认模式:首次授权一次,之后审核通过直接到账,用户零跳转。
方式一(首单转账顺带授权 pre-transfer-with-authorization)+ 方式二(显式开启 user-confirm-authorization)。
- 新增 wechat_transfer_authorization 表(user 1:1,out_authorization_no/authorization_id/state) + 迁移
- wxpay.py 新增 apply/query/close_transfer_authorization + pre_transfer_with_authorization + transfer_with_authorization
- repositories/wallet.py 授权 CRUD + sync/_refresh_active_auth + execute_withdraw_transfer 三分叉
(active->免确认转账 / 无授权且配了回调->方式一 / 未配->退化原确认模式);失效回查授权权威判定,绝不盲退
- /wallet/transfer-auth(开启)/status/close 路由 + withdraw-info 增 transfer_auth_enabled
- 授权结果回调 stub /api/v1/wxpay/transfer-auth-notify(一期仅应答不验签,真值靠 query 轮询)
- config 增 WXPAY_AUTH_NOTIFY_URL
一期无回调验签;二期补 V3 平台证书验签 + AEAD 解密。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
Reviewed-on: #16
2026-06-06 18:52:42 +08:00
marco
07c0b7502c
feat(welfare): 提现人工审核流程 + 看广告每日时长限流(防刷主闸) ( #15 )
...
提现人工审核(提现不再即时打款):
- models/wallet.py: WithdrawOrder 状态机改为
reviewing →(审核通过)→ pending → success/failed;reviewing →(驳回)→ rejected(已退款),
默认态 pending → reviewing(扣现金建单但不打款);新增 user_name 列(实名, 微信达额转账要求)
- admin/routers/withdraw.py + admin/schemas/wallet.py: 运营后台审核接口(通过触发微信转账 / 驳回退款)
- api/v1/wallet.py + repositories/wallet.py: 发起提现进 reviewing 态, 驳回退回现金并写 withdraw_refund
- schemas/welfare.py: 提现出参增 reviewing/rejected 状态 + fail_reason
看广告每日时长限流(防刷主闸 + 次数兜底):
- 新增 models/ad_watch_log.py: 按 (user_id, watch_date) 聚合当日观看秒数
- 新增 repositories/ad_watch.py: watched_seconds_today / add_watch_seconds(夹 [0, MAX_SINGLE_WATCH_SECONDS])
- api/v1/ad.py: 新增 POST /ad/watch-report(JWT 取 user, 落时长返当日累计);
/ad/reward-status 增 watched_seconds_today / limit / remaining
- schemas/ad.py: WatchReportIn/Out
- core/rewards.py: 新增 DAILY_AD_WATCH_SECONDS_LIMIT=50 分钟(主闸)+ MAX_SINGLE_WATCH_SECONDS=120;
DAILY_AD_REWARD_LIMIT 20→200 改作次数兜底(防前端少报时长绕过时长闸, 又不误伤看短广告的正常用户)
- repositories/ad_reward.py + models/__init__.py: 接入新表与时长闸
alembic: withdraw_review_and_ad_watch 迁移(withdraw_order.user_name 列 + ad_watch_log 表)
tests: 补 test_ad_reward / test_withdraw
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
---------
Co-authored-by: pure <pure@192.168 .0.104>
Reviewed-on: #15
2026-06-06 04:51:50 +08:00
marco
67a9a15775
feat(admin): app_config 运营配置后台(rewards 等常量可后台配置) ( #14 )
...
- 新增 app_config 表 + model/repository/config_schema + admin config 路由与 schema + 测试
- rewards.py 及 ad_reward/signin/task/wallet/comparison_milestone repositories 接入可配置项;ad.py / admin/main.py 配套
- alembic merge(ebb6af5c0b56)合并本地 app_config(cfg1a2b3c4d5)与 incoming price_report/best_deeplink(b7e2c1a9f4d3)两 head
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
Reviewed-on: #14
2026-06-06 04:13:08 +08:00
zhangxianze
4506677483
feat(report): 上报更低价后端——price_report 表 + 提交/列表接口 ( #13 )
...
Co-authored-by: xianze <ze@192.168 .0.138>
Reviewed-on: #13
Co-authored-by: zhangxianze <zhangxianze@wonderable.ai >
Co-committed-by: zhangxianze <zhangxianze@wonderable.ai >
2026-06-06 00:42:39 +08:00
marco
b50495bebe
feat: 短信接入极光真实发送 + 新增运营 admin 后台子应用
...
短信(SMS_MOCK 切 mock/real):
- integrations/sms.py 重写: real 模式走极光短信 REST /v1/messages 自定义验证码(本服务 secrets
生成 6 位码 + 进程内存 + 本地校验一次性/防爆破), 鉴权复用极光一键登录 JG_APP_KEY/MASTER_SECRET
(同一极光应用, 上线只需 SMS_MOCK=false); mock 仍"任意6位通过"不动其余测试
- 防刷四层: 单号冷却 + 单号每日上限 + 单IP rate_limit(/sms/send 10/min、/sms/login 20/min)
+ 单码失败次数作废; SmsError 带 status_code 映射 429/503/400
- config 增 SMS_SEND_ENDPOINT/SIGN_ID/TEMPLATE_ID/CODE_LENGTH/DAILY_LIMIT/MAX_VERIFY_ATTEMPTS;
test_auth 加 real 模式单测; sms.md/后端技术实现/待办账本同步
admin 后台(app/admin/ 独立子应用, uvicorn app.admin.main:admin_app :8771):
- 复用主仓 models/repositories/integrations + 同库, 鉴权完全隔离(ADMIN_JWT_SECRET≠JWT_SECRET_KEY
+ payload typ=admin + bcrypt 密码 + 可选 IP 白名单); 主 app 不 import 本包, admin 崩不影响主进程
- 路由: 登录 / 账号管理(RBAC: super_admin·finance·operator) / 用户列表+360详情+封禁+手动调币 /
钱包流水 / 提现重试对账 / 反馈工单 / 数据大盘; 全写操作落 admin_audit_log(涉钱与业务写同事务)
- 涉钱逻辑(调微信/退款/对账)复用 app.repositories.wallet 不重写
- 新增 models/admin.py(AdminUser/AdminAuditLog) + admin_tables 迁移 + create_admin.py +
deploy/shaguabijia-admin.service; 依赖加 bcrypt
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-04 03:02:41 +08:00
OuYingJun1024
9521cd96ce
chore(alembic): merge comparison_milestone 和 savings_report_fields 两个 head
2026-06-02 09:53:25 +08:00
ouzhou
da7ce69494
feat(ad): eCPM 上报接口 + 冷却策略解耦纯函数 + savings JSONB 跨库修复 ( #8 )
...
- 新增 POST /api/v1/ad/ecpm-report:激励视频展示后客户端上报本次 eCPM,落 ad_ecpm_record 做内部收益统计(model/repository/schema/alembic 迁移 + 接口文档)
- 看广告冷却策略抽到 app/core/ad_cooldown.py 纯函数;ad_reward.today_status 只取数据,换策略只改这一处
- savings.dishes 改 JSON().with_variant(JSONB,"postgresql"):SQLite 无 visit_JSONB 会让 create_all 编译崩,修复后测试套件恢复
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
---------
Co-authored-by: OuYingJun1024 <1034284404@qq.com >
Reviewed-on: #8
Co-authored-by: ouzhou <ouzhou@wonderable.ai >
Co-committed-by: ouzhou <ouzhou@wonderable.ai >
2026-06-01 22:23:15 +08:00
zhangxianze
288766443a
feat(记账): 比价省钱记账后端 M1(savings_record 唯一真相表 + /order/report + demo 兜底) ( #10 )
...
从最新 origin/main 重拉的干净分支,只含本人记账改动,不含 marco 的归因订单(order_record)——后者是另一条未合并分支 feat/user-order-records 的功能,此前被误用 git add -A 和记账混进了 feat/savings-accounting-m1。本分支不带它:savings_record 升级为唯一真相表(新增原价/比价价/支付渠道/源平台/幂等键等列,迁移 savings_report_fields 直接挂 f01db5d77dac、不经 order_record_table);/order/report 改写 savings_record(source='compare'),省额=源平台原价−实付;展示 /api/v1/savings/* 真实优先 demo 兜底。无 order_record 的 model/repo/迁移/路由。alembic 单一 head + pytest 54 passed。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
---------
Co-authored-by: xianze <ze@192.168 .0.138>
Reviewed-on: #10
Co-authored-by: zhangxianze <zhangxianze@wonderable.ai >
Co-committed-by: zhangxianze <zhangxianze@wonderable.ai >
2026-06-01 21:29:52 +08:00
marco
c3c64fa06d
chore: alembic merge revision + PG 迁移指南文档 ( #7 )
...
PostgreSQL 迁移 (#6 ) 之后两个分支引入了独立 heads (ef96beb47b1e +
d1e2f3a4b5c6), 必须合并成单一 head 才能 alembic upgrade head 顺利跑通。
- alembic/versions/f01db5d77dac_merge_pg_jsonb_and_feedback_heads.py:
空 op 的 merge revision, 把两个 heads 收敛为 f01db5d77dac
- docs/postgres-migration.md: SQLite → PostgreSQL 迁移指南
(背景/动机/操作步骤/无真实用户数据假设, 上线前补 pgloader 演练等)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
Reviewed-on: #7
2026-05-30 18:13:11 +08:00