diff --git a/internal/service/managercenter/service.go b/internal/service/managercenter/service.go index b1da867..a7c10b4 100644 --- a/internal/service/managercenter/service.go +++ b/internal/service/managercenter/service.go @@ -759,7 +759,7 @@ func (s *Service) loadGiftableNobleVIPAbility(ctx context.Context, propsID int64 return propsNobleVIPAbilityRow{}, serverError("vip_ability_query_failed", err.Error()) } if row.VIPLevel > maxGiftableVIPLevel { - return propsNobleVIPAbilityRow{}, badRequest("vip_not_giftable", "only noble VIP level 1-3 can be gifted") + return propsNobleVIPAbilityRow{}, badRequest("vip_not_giftable", "only noble VIP level 1-5 can be gifted") } return row, nil } @@ -857,7 +857,7 @@ func propsRowToView(row propsSourceRecordRow, vipLevels map[int64]int) (PropsVie if row.Type == propsTypeNobleVIP { var exists bool level, exists = vipLevels[row.ID] - if !exists || level > 3 { + if !exists || level > maxGiftableVIPLevel { return PropsView{}, false } } diff --git a/internal/service/managercenter/service_test.go b/internal/service/managercenter/service_test.go index 0f818d4..074245a 100644 --- a/internal/service/managercenter/service_test.go +++ b/internal/service/managercenter/service_test.go @@ -107,10 +107,14 @@ func TestListPropsRequiresAdminFreeAndFiltersVIPLevels(t *testing.T) { propsSourceRecordRow{ID: 102, Type: propsTypeRide, Name: "Paid ride", AdminFree: false}, propsSourceRecordRow{ID: 201, Type: propsTypeNobleVIP, Name: "VIP 3", AdminFree: true}, propsSourceRecordRow{ID: 204, Type: propsTypeNobleVIP, Name: "VIP 4", AdminFree: true}, + propsSourceRecordRow{ID: 205, Type: propsTypeNobleVIP, Name: "VIP 5", AdminFree: true}, + propsSourceRecordRow{ID: 206, Type: propsTypeNobleVIP, Name: "VIP 6", AdminFree: true}, ) seedAbilities(t, service.db.(*gorm.DB), propsNobleVIPAbilityRow{ID: 201, VIPLevel: 3}, propsNobleVIPAbilityRow{ID: 204, VIPLevel: 4}, + propsNobleVIPAbilityRow{ID: 205, VIPLevel: 5}, + propsNobleVIPAbilityRow{ID: 206, VIPLevel: 6}, ) resp, err := service.ListProps(context.Background(), AuthUser{UserID: 1}, "") @@ -129,10 +133,16 @@ func TestListPropsRequiresAdminFreeAndFiltersVIPLevels(t *testing.T) { t.Fatalf("records = %+v, non-admin-free props must be hidden", resp.Records) } if item, ok := got[201]; !ok || item.Days != defaultVIPGiftDays || item.VIPLevel != 3 { - t.Fatalf("vip 201 = %+v, want level 3 with 3 days", item) + t.Fatalf("vip 201 = %+v, want level 3 with default VIP days", item) } - if _, ok := got[204]; ok { - t.Fatalf("records = %+v, VIP level 4 must be hidden", resp.Records) + if item, ok := got[204]; !ok || item.VIPLevel != 4 { + t.Fatalf("vip 204 = %+v, want level 4 visible", item) + } + if item, ok := got[205]; !ok || item.VIPLevel != 5 { + t.Fatalf("vip 205 = %+v, want level 5 visible", item) + } + if _, ok := got[206]; ok { + t.Fatalf("records = %+v, VIP level 6 must be hidden", resp.Records) } } @@ -145,18 +155,32 @@ func TestListPropsReturnsVIPLevelConfigs(t *testing.T) { model.VipLevelConfig{ID: 302, SysOrigin: "LIKEI", Level: 2, LevelCode: "VIP2", DisplayName: "VIP 2", Enabled: false, DurationDays: 30}, model.VipLevelConfig{ID: 303, SysOrigin: "ATYOU", Level: 1, LevelCode: "VIP1", DisplayName: "ATYOU VIP 1", Enabled: true, DurationDays: 30}, model.VipLevelConfig{ID: 304, SysOrigin: "LIKEI", Level: 4, LevelCode: "VIP4", DisplayName: "VIP 4", Enabled: true, DurationDays: 30}, + model.VipLevelConfig{ID: 305, SysOrigin: "LIKEI", Level: 5, LevelCode: "VIP5", DisplayName: "VIP 5", Enabled: true, DurationDays: 30}, + model.VipLevelConfig{ID: 306, SysOrigin: "LIKEI", Level: 6, LevelCode: "VIP6", DisplayName: "VIP 6", Enabled: true, DurationDays: 30}, ) resp, err := service.ListProps(context.Background(), AuthUser{UserID: 1, SysOrigin: "LIKEI"}, propsTypeNobleVIP) if err != nil { t.Fatalf("ListProps() error = %v", err) } - if len(resp.Records) != 1 { - t.Fatalf("records = %+v, want only one enabled LIKEI vip config", resp.Records) + if len(resp.Records) != 3 { + t.Fatalf("records = %+v, want enabled LIKEI vip configs up to level 5", resp.Records) } - got := resp.Records[0] - if got.ID.Int64() != 301 || got.Type != propsTypeNobleVIP || got.VIPLevel != 1 || got.Days != 30 { - t.Fatalf("vip props = %+v, want config 301 level 1", got) + got := map[int64]PropsView{} + for _, item := range resp.Records { + got[item.ID.Int64()] = item + } + if item := got[301]; item.Type != propsTypeNobleVIP || item.VIPLevel != 1 || item.Days != 30 { + t.Fatalf("vip props 301 = %+v, want config 301 level 1", item) + } + if item := got[304]; item.Type != propsTypeNobleVIP || item.VIPLevel != 4 || item.Days != 30 { + t.Fatalf("vip props 304 = %+v, want config 304 level 4", item) + } + if item := got[305]; item.Type != propsTypeNobleVIP || item.VIPLevel != 5 || item.Days != 30 { + t.Fatalf("vip props 305 = %+v, want config 305 level 5", item) + } + if _, ok := got[306]; ok { + t.Fatalf("records = %+v, VIP level 6 must be hidden", resp.Records) } } @@ -398,12 +422,12 @@ func TestSendVIPUsesVIPLevelConfig(t *testing.T) { seedVIPConfigs(t, db, model.VipLevelConfig{ ID: 301, SysOrigin: "LIKEI", - Level: 3, - LevelCode: "VIP3", - DisplayName: "VIP 3", + Level: 5, + LevelCode: "VIP5", + DisplayName: "VIP 5", Enabled: true, DurationDays: 30, - PriceGold: 3000, + PriceGold: 5000, }) resp, err := service.SendProps(context.Background(), AuthUser{UserID: 1, SysOrigin: "LIKEI"}, SendPropsRequest{ @@ -413,7 +437,7 @@ func TestSendVIPUsesVIPLevelConfig(t *testing.T) { if err != nil { t.Fatalf("SendProps() error = %v", err) } - if !resp.Success || resp.Type != propsTypeNobleVIP || resp.VIPLevel != 3 || resp.Days != 30 { + if !resp.Success || resp.Type != propsTypeNobleVIP || resp.VIPLevel != 5 || resp.Days != 30 { t.Fatalf("resp = %+v, want vip gift success", resp) } @@ -421,8 +445,8 @@ func TestSendVIPUsesVIPLevelConfig(t *testing.T) { if err := db.Where("sys_origin = ? AND user_id = ?", "LIKEI", int64(2)).First(&state).Error; err != nil { t.Fatalf("load state: %v", err) } - if state.Level != 3 || state.Status != vipStatusActive { - t.Fatalf("state = %+v, want vip3 active", state) + if state.Level != 5 || state.Status != vipStatusActive { + t.Fatalf("state = %+v, want vip5 active", state) } var orders int64 if err := db.Model(&model.VipOrderRecord{}).Where("user_id = ? AND order_type = ?", int64(2), vipOrderTypeGMGift).Count(&orders).Error; err != nil { @@ -432,7 +456,7 @@ func TestSendVIPUsesVIPLevelConfig(t *testing.T) { t.Fatalf("orders = %d, want 1", orders) } var records int64 - if err := db.Model(&gmVIPGiftRecordRow{}).Where("user_id = ? AND vip_level = ?", int64(2), 3).Count(&records).Error; err != nil { + if err := db.Model(&gmVIPGiftRecordRow{}).Where("user_id = ? AND vip_level = ?", int64(2), 5).Count(&records).Error; err != nil { t.Fatalf("count gift records: %v", err) } if records != 1 { @@ -493,9 +517,9 @@ func TestSendVIPRejectsLevelAboveGiftLimit(t *testing.T) { seedVIPConfigs(t, db, model.VipLevelConfig{ ID: 304, SysOrigin: "LIKEI", - Level: 4, - LevelCode: "VIP4", - DisplayName: "VIP 4", + Level: 6, + LevelCode: "VIP6", + DisplayName: "VIP 6", Enabled: true, DurationDays: 30, }) diff --git a/internal/service/managercenter/types.go b/internal/service/managercenter/types.go index 00b4df2..8511ebd 100644 --- a/internal/service/managercenter/types.go +++ b/internal/service/managercenter/types.go @@ -28,9 +28,10 @@ const ( vipGiftOrigin = "VIP_PURCHASE" vipGiftOriginDesc = "VIP purchase" - defaultGiftDays = 7 - defaultVIPGiftDays = 30 - maxGiftableVIPLevel = 3 + defaultGiftDays = 7 + defaultVIPGiftDays = 30 + // 经理中心 VIP 赠送按当前运营范围放开 VIP1-VIP5;列表和发放校验共用该上限,避免展示可选但提交失败。 + maxGiftableVIPLevel = 5 accountStatusNormal = "NORMAL" accountStatusFreeze = "FREEZE"