diff --git a/internal/service/rechargereward/claim_records.go b/internal/service/rechargereward/claim_records.go index d084ab8..ddf6c1f 100644 --- a/internal/service/rechargereward/claim_records.go +++ b/internal/service/rechargereward/claim_records.go @@ -283,6 +283,9 @@ func claimDetailPayloads( if detail.ResourceGroupID != nil { items = rewardItems[*detail.ResourceGroupID] } + if items == nil { + items = []RechargeRewardRewardItem{} + } result = append(result, RechargeRewardLevelPayload{ ID: detail.ActivityID, Level: level, @@ -313,6 +316,9 @@ func reachedRechargeRewardLevels( if level.RewardGroupID != nil { items = rewardItems[*level.RewardGroupID] } + if items == nil { + items = []RechargeRewardRewardItem{} + } result = append(result, RechargeRewardLevelPayload{ ID: level.ID, Level: level.Level, @@ -332,6 +338,10 @@ func reachedRechargeRewardLevels( func rechargeRewardClaimedRewards(levels []RechargeRewardLevelPayload) []RechargeRewardClaimedRewardPayload { result := make([]RechargeRewardClaimedRewardPayload, 0, len(levels)) for _, level := range levels { + items := level.RewardItems + if items == nil { + items = []RechargeRewardRewardItem{} + } result = append(result, RechargeRewardClaimedRewardPayload{ Level: level.Level, RechargeAmount: level.RechargeAmount, @@ -339,7 +349,7 @@ func rechargeRewardClaimedRewards(levels []RechargeRewardLevelPayload) []Recharg RewardGold: level.RewardGold, RewardGroupID: level.RewardGroupID, RewardGroupName: level.RewardGroupName, - RewardItems: level.RewardItems, + RewardItems: items, }) } return result diff --git a/internal/service/rechargereward/config_test.go b/internal/service/rechargereward/config_test.go index fa38d2b..7d1073d 100644 --- a/internal/service/rechargereward/config_test.go +++ b/internal/service/rechargereward/config_test.go @@ -2,7 +2,9 @@ package rechargereward import ( "context" + "encoding/json" "fmt" + "strings" "testing" "time" @@ -113,7 +115,7 @@ func TestSaveConfigUpsertsBySysOrigin(t *testing.T) { } func TestGetHomeUsesJavaRechargeAndMarksLevels(t *testing.T) { - groupID := int64(9001) + groupID := int64(2056981527522242600) java := rechargeRewardTestGateway{ total: map[int64][]integration.UserTotalRecharge{ 42: { @@ -132,7 +134,14 @@ func TestGetHomeUsesJavaRechargeAndMarksLevels(t *testing.T) { ID: integration.Int64Value(groupID), Name: "Gift Box", RewardConfigList: []integration.RewardGroupItem{ - {ID: integration.Int64Value(1), Type: "PROP", Name: "Frame", Quantity: integration.Int64Value(1), Cover: "https://example.com/frame.png"}, + { + ID: integration.Int64Value(1), + Type: "PROPS", + DetailType: "AVATAR_FRAME", + Name: "Frame", + Quantity: integration.Int64Value(1), + SourceURL: "https://example.com/frame.svga", + }, }, }, }, @@ -196,6 +205,23 @@ INSERT INTO likei_wallet.user_freight_balance_running_water (accept_user_id, sys if len(resp.LevelConfigs[0].RewardItems) != 1 || resp.LevelConfigs[0].RewardItems[0].Name != "Frame" { t.Fatalf("reward items = %+v", resp.LevelConfigs[0].RewardItems) } + if got := resp.LevelConfigs[0].RewardItems[0]; got.Type != "AVATAR_FRAME" || got.Cover != "https://example.com/frame.svga" { + t.Fatalf("reward item display fields = %+v", got) + } + if resp.LevelConfigs[1].RewardItems == nil { + t.Fatalf("gold-only level RewardItems = nil, want empty slice") + } + encoded, err := json.Marshal(resp) + if err != nil { + t.Fatalf("marshal response: %v", err) + } + body := string(encoded) + if !strings.Contains(body, `"rewardGroupId":"2056981527522242600"`) { + t.Fatalf("encoded rewardGroupId is not a string: %s", body) + } + if strings.Contains(body, `"rewardItems":null`) { + t.Fatalf("encoded rewardItems contains null: %s", body) + } } func TestPageClaimRecordsUsesActualReceiveRecords(t *testing.T) { diff --git a/internal/service/rechargereward/mapper.go b/internal/service/rechargereward/mapper.go index 36f7bac..f092b16 100644 --- a/internal/service/rechargereward/mapper.go +++ b/internal/service/rechargereward/mapper.go @@ -47,6 +47,9 @@ func buildLevelPayloads( if level.RewardGroupID != nil { items = rewardItems[*level.RewardGroupID] } + if items == nil { + items = []RechargeRewardRewardItem{} + } payloads = append(payloads, RechargeRewardLevelPayload{ ID: level.ID, Level: level.Level, @@ -74,6 +77,9 @@ func buildAdminLevelPayloads( if level.RewardGroupID != nil { items = rewardItems[*level.RewardGroupID] } + if items == nil { + items = []RechargeRewardRewardItem{} + } payloads = append(payloads, RechargeRewardLevelPayload{ ID: level.ID, Level: level.Level, @@ -148,25 +154,62 @@ func (s *Service) loadRewardItemsMap( for _, groupID := range groupIDs { detail, err := s.java.GetRewardGroupDetail(ctx, groupID) if err != nil { + result[groupID] = []RechargeRewardRewardItem{} continue } - items := make([]RechargeRewardRewardItem, 0, len(detail.RewardConfigList)) - for _, item := range detail.RewardConfigList { - items = append(items, RechargeRewardRewardItem{ - ID: int64(item.ID), - Type: strings.TrimSpace(item.Type), - Name: strings.TrimSpace(item.Name), - Content: strings.TrimSpace(item.Content), - Quantity: int64(item.Quantity), - Cover: strings.TrimSpace(item.Cover), - Remark: strings.TrimSpace(item.Remark), - }) - } - result[groupID] = items + result[groupID] = rewardItemsFromGroup(detail) } return result } +func rewardItemsFromGroup(detail integration.RewardGroupDetail) []RechargeRewardRewardItem { + items := make([]RechargeRewardRewardItem, 0, len(detail.RewardConfigList)) + for _, item := range detail.RewardConfigList { + items = append(items, RechargeRewardRewardItem{ + ID: int64(item.ID), + Type: rewardItemDisplayType(item), + Name: strings.TrimSpace(item.Name), + Content: strings.TrimSpace(item.Content), + Quantity: int64(item.Quantity), + Cover: firstNonEmpty(item.Cover, item.SourceURL), + Remark: strings.TrimSpace(item.Remark), + }) + } + return items +} + +func rewardItemDisplayType(item integration.RewardGroupItem) string { + itemType := strings.ToUpper(strings.TrimSpace(item.Type)) + detailType := strings.ToUpper(strings.TrimSpace(item.DetailType)) + if itemType == "PROPS" { + if detailType != "" && detailType != "PROPS" { + return detailType + } + if isVipRewardItem(item) { + return "NOBLE_VIP" + } + } + return itemType +} + +func isVipRewardItem(item integration.RewardGroupItem) bool { + name := strings.ToUpper(strings.TrimSpace(item.Name)) + remark := strings.ToUpper(strings.TrimSpace(item.Remark)) + return strings.Contains(name, "VIP") || + strings.Contains(name, "NOBLE") || + strings.Contains(remark, "VIP") || + strings.Contains(remark, "NOBLE") +} + +func firstNonEmpty(values ...string) string { + for _, value := range values { + if trimmed := strings.TrimSpace(value); trimmed != "" { + return trimmed + } + } + return "" +} + func totalRechargeCents(entries []integration.UserTotalRecharge) int64 { var total int64 for _, entry := range entries { diff --git a/internal/service/rechargereward/types.go b/internal/service/rechargereward/types.go index d5fa380..d0bcd48 100644 --- a/internal/service/rechargereward/types.go +++ b/internal/service/rechargereward/types.go @@ -75,7 +75,7 @@ type RechargeRewardLevelPayload struct { RechargeAmount string `json:"rechargeAmount"` RechargeAmountCents int64 `json:"rechargeAmountCents"` RewardGold int64 `json:"rewardGold"` - RewardGroupID *int64 `json:"rewardGroupId,omitempty"` + RewardGroupID *int64 `json:"rewardGroupId,string,omitempty"` RewardGroupName string `json:"rewardGroupName,omitempty"` RewardItems []RechargeRewardRewardItem `json:"rewardItems"` Enabled bool `json:"enabled"` @@ -175,7 +175,7 @@ type RechargeRewardClaimedRewardPayload struct { RechargeAmount string `json:"rechargeAmount"` RechargeAmountCents int64 `json:"rechargeAmountCents"` RewardGold int64 `json:"rewardGold"` - RewardGroupID *int64 `json:"rewardGroupId,omitempty"` + RewardGroupID *int64 `json:"rewardGroupId,string,omitempty"` RewardGroupName string `json:"rewardGroupName,omitempty"` RewardItems []RechargeRewardRewardItem `json:"rewardItems"` }