2026-04-16 16:11:09 +08:00
|
|
|
|
# Journal - zl-q
|
2026-04-10 16:45:45 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
> Development session records for worktree: feat-starter-package-purchase-tracking
|
2026-04-10 16:45:45 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
## Session 1: 新人初始礼包购买追踪功能 - 计划制定
|
2026-04-10 18:51:30 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
**Date**: 2026-04-16
|
|
|
|
|
|
**Task**: starter-package-purchase-tracking
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
|
|
|
|
|
### Summary
|
|
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
在独立 worktree 中创建新人初始礼包购买追踪功能的实现计划。
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
### Background
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
用户需求:追踪用户是否已购买新人初始礼包($0.99/60积分),以便前端支付页面决定是否展示该礼包。
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
### Analysis
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
1. **现有数据结构分析**
|
|
|
|
|
|
- `register_bonus_claims` 表已存在,用于注册送分去重
|
|
|
|
|
|
- 表结构包含:`email_hash`(唯一)、`user_email_snapshot`、`first_user_id_snapshot`、`balance_snapshot`、`grant_event_id`
|
|
|
|
|
|
- 已支持删除账号后重注册恢复余额的功能
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
2. **设计方案**
|
|
|
|
|
|
- 在 `register_bonus_claims` 添加 `has_purchased_starter_pack` 字段
|
|
|
|
|
|
- 利用现有 `email_hash` 唯一约束保证同一邮箱只能购买一次
|
|
|
|
|
|
- 后端提供 `/api/v1/points/starter-pack/eligibility` API
|
|
|
|
|
|
- 前端根据 API 返回决定是否展示礼包
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
3. **参考现有实现**
|
|
|
|
|
|
- 已有计划文档:`docs/plans/ios-new-user-pack-payment-plan.md`
|
|
|
|
|
|
- 完整支付计划包含:支付订单表、支付事件审计表、验单流程等
|
|
|
|
|
|
- 本期仅实现资格查询,不涉及支付流程
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
### Implementation Plan
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
#### Phase 1: 数据库层
|
|
|
|
|
|
- 创建 Alembic 迁移:`20260416_0001_add_starter_pack_tracking.py`
|
|
|
|
|
|
- 添加字段:`has_purchased_starter_pack BOOLEAN NOT NULL DEFAULT FALSE`
|
|
|
|
|
|
- 更新 Model:`backend/src/models/register_bonus_claims.py`
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
#### Phase 2: 后端 API
|
|
|
|
|
|
- Schema:定义 `StarterPackEligibilityResponse`、`StarterPackInfo`
|
|
|
|
|
|
- Repository:添加 `has_purchased_starter_pack()` 方法
|
|
|
|
|
|
- Service:实现 `check_starter_pack_eligibility()` 逻辑
|
|
|
|
|
|
- Router:添加 `GET /api/v1/points/starter-pack/eligibility` 路由
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
#### Phase 3: 前端集成
|
|
|
|
|
|
- 创建 API 调用层
|
|
|
|
|
|
- 更新支付页面 UI 展示逻辑
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
#### Phase 4: 文档与测试
|
|
|
|
|
|
- 更新协议文档
|
|
|
|
|
|
- 编写单元测试和集成测试
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
### Key Decisions
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
1. **字段命名**:`has_purchased_starter_pack`(布尔型),简洁明确
|
|
|
|
|
|
2. **API 设计**:仅返回资格状态和礼包信息,不涉及支付逻辑
|
|
|
|
|
|
3. **本期限制**:
|
|
|
|
|
|
- 不实现支付流程
|
|
|
|
|
|
- 不实现支付验证
|
|
|
|
|
|
- `has_purchased_starter_pack` 字段暂时只读
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
### Files Created
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
| File | Purpose |
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|------|---------|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
| `.trellis/tasks/04-16-starter-package-purchase-tracking/task.json` | 任务配置 |
|
|
|
|
|
|
| `.trellis/tasks/04-16-starter-package-purchase-tracking/prd.md` | 需求与实现计划 |
|
2026-04-15 16:50:29 +08:00
|
|
|
|
|
|
|
|
|
|
### Next Steps
|
|
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
1. 实现 Phase 1:数据库迁移和 Model 更新
|
|
|
|
|
|
2. 实现 Phase 2:后端 API
|
|
|
|
|
|
3. 实现 Phase 3:前端集成
|
|
|
|
|
|
4. 实现 Phase 4:文档与测试
|
2026-04-15 18:19:25 +08:00
|
|
|
|
|
|
|
|
|
|
### Status
|
|
|
|
|
|
|
2026-04-16 16:11:09 +08:00
|
|
|
|
# **In Progress** - 计划已制定,等待实现
|
2026-04-16 16:15:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Session 2: 新人初始礼包购买追踪功能实现
|
|
|
|
|
|
|
|
|
|
|
|
**Date**: 2026-04-16
|
|
|
|
|
|
**Task**: 新人初始礼包购买追踪功能实现
|
|
|
|
|
|
|
|
|
|
|
|
### Summary
|
|
|
|
|
|
|
|
|
|
|
|
(Add summary)
|
|
|
|
|
|
|
|
|
|
|
|
### Main Changes
|
|
|
|
|
|
|
|
|
|
|
|
## 功能概述
|
|
|
|
|
|
|
|
|
|
|
|
实现新人初始礼包购买追踪功能,支持动态套餐配置和按国家/地区区分。
|
|
|
|
|
|
|
|
|
|
|
|
## 后端实现
|
|
|
|
|
|
|
|
|
|
|
|
| 模块 | 变更 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| 数据库 | 添加 `has_purchased_starter_pack` 字段到 `register_bonus_claims` |
|
|
|
|
|
|
| 配置管理 | 创建 `backend/src/core/config/packages/` 静态配置加载层 |
|
|
|
|
|
|
| 路径工具 | 创建 `backend/src/utils/paths.py` 统一路径管理 |
|
|
|
|
|
|
| API | 新增 `GET /api/v1/points/packages` 返回可用套餐 |
|
|
|
|
|
|
| 默认值 | Profile 默认国家改为 `US`(ISO 3166-1 alpha-2) |
|
|
|
|
|
|
|
|
|
|
|
|
## 前端实现
|
|
|
|
|
|
|
|
|
|
|
|
| 模块 | 变更 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| 数据模型 | 创建 `ProductCode` 枚举约束,前后端类型安全 |
|
|
|
|
|
|
| API 调用 | 新增 `PointsApi.getPackages()` |
|
|
|
|
|
|
| UI | `CoinCenterScreen` 动态渲染套餐,移除硬编码 |
|
|
|
|
|
|
| l10n | 添加 `settingsCoinPackStarter` 翻译 |
|
|
|
|
|
|
|
|
|
|
|
|
## 配置文件
|
|
|
|
|
|
|
|
|
|
|
|
- `backend/src/core/config/static/packages/us.yaml` - 美国区套餐配置
|
|
|
|
|
|
- `backend/src/core/config/static/packages/default.yaml` - 默认套餐配置
|
|
|
|
|
|
|
|
|
|
|
|
## 技术亮点
|
|
|
|
|
|
|
|
|
|
|
|
- ProductCode 枚举约束:后端 Pydantic Literal + 前端 Dart enum
|
|
|
|
|
|
- 统一路径管理:移除 5 处硬编码路径拼接
|
|
|
|
|
|
- Cross-layer 检查:修复 `profile_api.dart` fallback 不一致问题
|
|
|
|
|
|
|
|
|
|
|
|
## 文件统计
|
|
|
|
|
|
|
|
|
|
|
|
- 38 files changed
|
|
|
|
|
|
- +1452 insertions
|
|
|
|
|
|
- -2535 deletions
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Git Commits
|
|
|
|
|
|
|
|
|
|
|
|
| Hash | Message |
|
|
|
|
|
|
|------|---------|
|
|
|
|
|
|
| `ff40ff9` | (see git log) |
|
|
|
|
|
|
| `fd0df28` | (see git log) |
|
|
|
|
|
|
|
|
|
|
|
|
### Testing
|
|
|
|
|
|
|
|
|
|
|
|
- [OK] (Add test results)
|
|
|
|
|
|
|
|
|
|
|
|
### Status
|
|
|
|
|
|
|
|
|
|
|
|
[OK] **Completed**
|
|
|
|
|
|
|
|
|
|
|
|
### Next Steps
|
|
|
|
|
|
|
|
|
|
|
|
- None - task complete
|