feat(server): pro 套餐设备上限 5 → 3

- seed(sqlite/mysql 000007)+ 001_init:pro max_devices 5→3(全新库直接对)
- 新增迁移 000019(sqlite/mysql,up/down):UPDATE plans SET max_devices=3
  WHERE code='pro' —— 已迁移的线上库靠它更新;down 回退 5
- 000002/001 注释同步(free 1 / pro 3 / team 10)
- 测试:sqlite_migrate 期望版本 18→19;devices 集成测试 pro 断言 5→3
- free(1)/team(10)不变

注:设备上限当前仍未强制执行(登录注册 MaxDevices=0),仅数据/展示口径;
真正启用+超限 UX 见 todo #16。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-07-01 18:07:03 +08:00
parent 58211d2fb8
commit 27dc59ed63
10 changed files with 19 additions and 11 deletions
@@ -172,15 +172,15 @@ func TestFullChain(t *testing.T) {
ctx := context.Background()
userID := createUser(t, db, "chain@example.com", "active")
// 7-day pro trial → effective plan pro (max 5).
// 7-day pro trial → effective plan pro (max 3).
giveSubscription(t, db, userID, "pro", "trial", time.Now().UTC().Add(7*24*time.Hour))
plan, apiErr := svc.ResolvePlan(ctx, userID)
if apiErr != nil {
t.Fatalf("ResolvePlan: %v", apiErr)
}
if plan.PlanCode != "pro" || plan.MaxDevices != 5 {
t.Fatalf("want pro/5, got %s/%d", plan.PlanCode, plan.MaxDevices)
if plan.PlanCode != "pro" || plan.MaxDevices != 3 {
t.Fatalf("want pro/3, got %s/%d", plan.PlanCode, plan.MaxDevices)
}
devUUID := newUUID(t, db)
+2 -2
View File
@@ -29,8 +29,8 @@ func TestSQLiteMigrateUpDown(t *testing.T) {
if dirty {
t.Fatalf("schema dirty after MigrateUp")
}
if v != 18 {
t.Errorf("version = %d, want 18", v)
if v != 19 {
t.Errorf("version = %d, want 19", v)
}
// 2. Core tables exist.