修复奖励
This commit is contained in:
parent
675f45bf44
commit
c09433bf29
@ -131,6 +131,11 @@ func (g *Gateways) GetRewardGroupDetail(ctx context.Context, groupID int64) (Rew
|
|||||||
return g.RewardQuery.GetRewardGroupDetail(ctx, groupID)
|
return g.RewardQuery.GetRewardGroupDetail(ctx, groupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindRewardGroupDetail 透传到奖励查询网关,按名称查找奖励组详情。
|
||||||
|
func (g *Gateways) FindRewardGroupDetail(ctx context.Context, sysOrigin string, name string) (RewardGroupDetail, error) {
|
||||||
|
return g.RewardQuery.FindRewardGroupDetail(ctx, sysOrigin, name)
|
||||||
|
}
|
||||||
|
|
||||||
// GetUserProfile 透传到资料网关。
|
// GetUserProfile 透传到资料网关。
|
||||||
func (g *Gateways) GetUserProfile(ctx context.Context, userID int64) (UserProfile, error) {
|
func (g *Gateways) GetUserProfile(ctx context.Context, userID int64) (UserProfile, error) {
|
||||||
return g.Profile.GetUserProfile(ctx, userID)
|
return g.Profile.GetUserProfile(ctx, userID)
|
||||||
@ -365,6 +370,11 @@ func (g *RewardQueryGateway) GetRewardGroupDetail(ctx context.Context, groupID i
|
|||||||
return g.client.GetRewardGroupDetail(ctx, groupID)
|
return g.client.GetRewardGroupDetail(ctx, groupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindRewardGroupDetail 按名称查询奖励组详情。
|
||||||
|
func (g *RewardQueryGateway) FindRewardGroupDetail(ctx context.Context, sysOrigin string, name string) (RewardGroupDetail, error) {
|
||||||
|
return g.client.FindRewardGroupDetail(ctx, sysOrigin, name)
|
||||||
|
}
|
||||||
|
|
||||||
// GetNobleVIPAbility 查询贵族 VIP 能力配置。
|
// GetNobleVIPAbility 查询贵族 VIP 能力配置。
|
||||||
func (g *RewardQueryGateway) GetNobleVIPAbility(ctx context.Context, sourceID int64) (PropsNobleVIPAbility, error) {
|
func (g *RewardQueryGateway) GetNobleVIPAbility(ctx context.Context, sourceID int64) (PropsNobleVIPAbility, error) {
|
||||||
return g.client.GetNobleVIPAbility(ctx, sourceID)
|
return g.client.GetNobleVIPAbility(ctx, sourceID)
|
||||||
|
|||||||
@ -253,6 +253,13 @@ type RewardGroupDetail struct {
|
|||||||
RewardConfigList []RewardGroupItem `json:"rewardConfigList"`
|
RewardConfigList []RewardGroupItem `json:"rewardConfigList"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type rewardGroupPage struct {
|
||||||
|
Records []RewardGroupDetail `json:"records"`
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
Current int `json:"current"`
|
||||||
|
Size int `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
type UserTotalRecharge struct {
|
type UserTotalRecharge struct {
|
||||||
ID Int64Value `json:"id"`
|
ID Int64Value `json:"id"`
|
||||||
UserID Int64Value `json:"userId"`
|
UserID Int64Value `json:"userId"`
|
||||||
@ -336,6 +343,7 @@ type resultResponse[T any] struct {
|
|||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Body T `json:"body"`
|
Body T `json:"body"`
|
||||||
|
Data T `json:"data"`
|
||||||
Success *bool `json:"success"`
|
Success *bool `json:"success"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,15 +706,128 @@ func (c *Client) SendOfficialNoticeCustomize(ctx context.Context, req OfficialNo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetRewardGroupDetail(ctx context.Context, groupID int64) (RewardGroupDetail, error) {
|
func (c *Client) GetRewardGroupDetail(ctx context.Context, groupID int64) (RewardGroupDetail, error) {
|
||||||
endpoint := c.cfg.Java.OtherBaseURL + "/props-activity/reward/group/client/getByGroupId?id=" + url.QueryEscape(strconv.FormatInt(groupID, 10))
|
detail, err := c.getInnerRewardGroupDetail(ctx, groupID)
|
||||||
|
if err == nil && rewardGroupDetailHasContent(detail) {
|
||||||
|
return detail, nil
|
||||||
|
}
|
||||||
|
if fallback, fallbackErr := c.getConsoleRewardGroupDetail(ctx, groupID); fallbackErr == nil && rewardGroupDetailHasContent(fallback) {
|
||||||
|
return fallback, nil
|
||||||
|
} else if err == nil && fallbackErr != nil {
|
||||||
|
return detail, nil
|
||||||
|
}
|
||||||
|
return detail, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getInnerRewardGroupDetail(ctx context.Context, groupID int64) (RewardGroupDetail, error) {
|
||||||
|
endpoint := strings.TrimRight(c.cfg.Java.OtherBaseURL, "/") + "/props-activity/reward/group/client/getByGroupId?id=" + url.QueryEscape(strconv.FormatInt(groupID, 10))
|
||||||
var resp resultResponse[RewardGroupDetail]
|
var resp resultResponse[RewardGroupDetail]
|
||||||
if err := c.getJSON(ctx, endpoint, nil, &resp); err != nil {
|
if err := c.getJSON(ctx, endpoint, nil, &resp); err != nil {
|
||||||
return RewardGroupDetail{}, err
|
return RewardGroupDetail{}, err
|
||||||
}
|
}
|
||||||
if int64(resp.Body.ID) == 0 {
|
detail := resp.Body
|
||||||
|
if int64(detail.ID) == 0 {
|
||||||
|
detail = resp.Data
|
||||||
|
}
|
||||||
|
if int64(detail.ID) == 0 {
|
||||||
return RewardGroupDetail{}, fmt.Errorf("empty reward group response")
|
return RewardGroupDetail{}, fmt.Errorf("empty reward group response")
|
||||||
}
|
}
|
||||||
return resp.Body, nil
|
return detail, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) getConsoleRewardGroupDetail(ctx context.Context, groupID int64) (RewardGroupDetail, error) {
|
||||||
|
baseURL := strings.TrimRight(strings.TrimSpace(c.cfg.Java.ConsoleBaseURL), "/")
|
||||||
|
if baseURL == "" {
|
||||||
|
return RewardGroupDetail{}, fmt.Errorf("console base url is empty")
|
||||||
|
}
|
||||||
|
endpoint := baseURL + "/props/activity/reward/group/" + url.PathEscape(strconv.FormatInt(groupID, 10))
|
||||||
|
var detail RewardGroupDetail
|
||||||
|
if err := c.getJSON(ctx, endpoint, nil, &detail); err != nil {
|
||||||
|
return RewardGroupDetail{}, err
|
||||||
|
}
|
||||||
|
if int64(detail.ID) == 0 {
|
||||||
|
return RewardGroupDetail{}, fmt.Errorf("empty reward group response")
|
||||||
|
}
|
||||||
|
return detail, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func rewardGroupDetailHasContent(detail RewardGroupDetail) bool {
|
||||||
|
return int64(detail.ID) > 0 && len(detail.RewardConfigList) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) FindRewardGroupDetail(ctx context.Context, sysOrigin string, name string) (RewardGroupDetail, error) {
|
||||||
|
groupName := strings.TrimSpace(name)
|
||||||
|
if groupName == "" {
|
||||||
|
return RewardGroupDetail{}, fmt.Errorf("reward group name is empty")
|
||||||
|
}
|
||||||
|
if detail, err := c.findInnerRewardGroupDetail(ctx, sysOrigin, groupName); err == nil && rewardGroupDetailHasContent(detail) {
|
||||||
|
return detail, nil
|
||||||
|
}
|
||||||
|
return c.findConsoleRewardGroupDetail(ctx, sysOrigin, groupName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) findInnerRewardGroupDetail(ctx context.Context, sysOrigin string, name string) (RewardGroupDetail, error) {
|
||||||
|
endpoint := strings.TrimRight(c.cfg.Java.OtherBaseURL, "/") + "/props-activity/reward/group/client/page"
|
||||||
|
payload := map[string]any{
|
||||||
|
"current": 1,
|
||||||
|
"cursor": 1,
|
||||||
|
"limit": 10,
|
||||||
|
"name": name,
|
||||||
|
"shelfStatus": true,
|
||||||
|
"size": 10,
|
||||||
|
}
|
||||||
|
if origin := strings.TrimSpace(sysOrigin); origin != "" {
|
||||||
|
payload["sysOrigin"] = origin
|
||||||
|
}
|
||||||
|
var resp resultResponse[rewardGroupPage]
|
||||||
|
if err := c.postJSON(ctx, endpoint, payload, nil, &resp); err != nil {
|
||||||
|
return RewardGroupDetail{}, err
|
||||||
|
}
|
||||||
|
page := resp.Body
|
||||||
|
if len(page.Records) == 0 {
|
||||||
|
page = resp.Data
|
||||||
|
}
|
||||||
|
return pickRewardGroupDetailByName(page.Records, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) findConsoleRewardGroupDetail(ctx context.Context, sysOrigin string, name string) (RewardGroupDetail, error) {
|
||||||
|
baseURL := strings.TrimRight(strings.TrimSpace(c.cfg.Java.ConsoleBaseURL), "/")
|
||||||
|
if baseURL == "" {
|
||||||
|
return RewardGroupDetail{}, fmt.Errorf("console base url is empty")
|
||||||
|
}
|
||||||
|
values := url.Values{}
|
||||||
|
values.Set("current", "1")
|
||||||
|
values.Set("cursor", "1")
|
||||||
|
values.Set("limit", "10")
|
||||||
|
values.Set("name", name)
|
||||||
|
values.Set("shelfStatus", "true")
|
||||||
|
values.Set("size", "10")
|
||||||
|
if origin := strings.TrimSpace(sysOrigin); origin != "" {
|
||||||
|
values.Set("sysOrigin", origin)
|
||||||
|
}
|
||||||
|
endpoint := baseURL + "/props/activity/reward/group/page?" + values.Encode()
|
||||||
|
var page rewardGroupPage
|
||||||
|
if err := c.getJSON(ctx, endpoint, nil, &page); err != nil {
|
||||||
|
return RewardGroupDetail{}, err
|
||||||
|
}
|
||||||
|
return pickRewardGroupDetailByName(page.Records, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pickRewardGroupDetailByName(records []RewardGroupDetail, name string) (RewardGroupDetail, error) {
|
||||||
|
if len(records) == 0 {
|
||||||
|
return RewardGroupDetail{}, fmt.Errorf("empty reward group page response")
|
||||||
|
}
|
||||||
|
target := strings.TrimSpace(name)
|
||||||
|
for _, record := range records {
|
||||||
|
if strings.TrimSpace(record.Name) == target && rewardGroupDetailHasContent(record) {
|
||||||
|
return record, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, record := range records {
|
||||||
|
if rewardGroupDetailHasContent(record) {
|
||||||
|
return record, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return records[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) MapUserTotalRecharge(ctx context.Context, userIDs []int64) (map[int64][]UserTotalRecharge, error) {
|
func (c *Client) MapUserTotalRecharge(ctx context.Context, userIDs []int64) (map[int64][]UserTotalRecharge, error) {
|
||||||
|
|||||||
@ -77,3 +77,66 @@ func TestResolveRegionCodeByCountryCodeUsesRegionConfig(t *testing.T) {
|
|||||||
t.Fatalf("region config calls = %d, want cached 1", calls)
|
t.Fatalf("region config calls = %d, want cached 1", calls)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetRewardGroupDetailAcceptsDataWrapper(t *testing.T) {
|
||||||
|
groupID := int64(2056981527522242600)
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodGet || r.URL.Path != "/props-activity/reward/group/client/getByGroupId" {
|
||||||
|
t.Fatalf("request = %s %s, want GET /props-activity/reward/group/client/getByGroupId", r.Method, r.URL.Path)
|
||||||
|
}
|
||||||
|
if r.URL.Query().Get("id") != "2056981527522242600" {
|
||||||
|
t.Fatalf("id query = %q", r.URL.Query().Get("id"))
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
_, _ = w.Write([]byte(`{"data":{"id":"2056981527522242600","name":"累计充值10美金","rewardConfigList":[{"id":"1","type":"PROPS","detailType":"AVATAR_FRAME","name":"Frame","quantity":"1","sourceUrl":"https://example.com/frame.svga"}]}}`))
|
||||||
|
}))
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client := New(config.Config{
|
||||||
|
HTTP: config.HTTPConfig{Timeout: time.Second},
|
||||||
|
Java: config.JavaConfig{OtherBaseURL: server.URL},
|
||||||
|
})
|
||||||
|
got, err := client.GetRewardGroupDetail(context.Background(), groupID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetRewardGroupDetail() error = %v", err)
|
||||||
|
}
|
||||||
|
if int64(got.ID) != groupID || len(got.RewardConfigList) != 1 {
|
||||||
|
t.Fatalf("detail = %+v, want group with one reward item", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetRewardGroupDetailFallsBackToConsoleEndpoint(t *testing.T) {
|
||||||
|
groupID := int64(2056981527522242600)
|
||||||
|
var innerCalls, consoleCalls int
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/props-activity/reward/group/client/getByGroupId", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
innerCalls++
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
_, _ = w.Write([]byte(`{"body":{"id":"2056981527522242600","name":"累计充值10美金","rewardConfigList":[]}}`))
|
||||||
|
})
|
||||||
|
mux.HandleFunc("/console/props/activity/reward/group/2056981527522242600", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
consoleCalls++
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
_, _ = w.Write([]byte(`{"id":"2056981527522242600","name":"累计充值10美金","rewardConfigList":[{"id":"1","type":"GIFT","name":"Gift","quantity":"1","cover":"https://example.com/gift.png"}]}`))
|
||||||
|
})
|
||||||
|
server := httptest.NewServer(mux)
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client := New(config.Config{
|
||||||
|
HTTP: config.HTTPConfig{Timeout: time.Second},
|
||||||
|
Java: config.JavaConfig{
|
||||||
|
OtherBaseURL: server.URL,
|
||||||
|
ConsoleBaseURL: server.URL + "/console",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
got, err := client.GetRewardGroupDetail(context.Background(), groupID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetRewardGroupDetail() error = %v", err)
|
||||||
|
}
|
||||||
|
if innerCalls != 1 || consoleCalls != 1 {
|
||||||
|
t.Fatalf("calls inner=%d console=%d, want 1/1", innerCalls, consoleCalls)
|
||||||
|
}
|
||||||
|
if len(got.RewardConfigList) != 1 || got.RewardConfigList[0].Name != "Gift" {
|
||||||
|
t.Fatalf("detail = %+v, want fallback reward item", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -117,7 +117,7 @@ ORDER BY claims.last_claim_time DESC, claims.user_id ASC`
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rewardItems := s.loadRewardItemsMap(ctx, claimDetailLevels(details))
|
rewardItems := s.loadRewardItemsMap(ctx, sysOrigin, claimDetailLevels(details))
|
||||||
records = make([]RechargeRewardClaimRecordView, 0, len(rows))
|
records = make([]RechargeRewardClaimRecordView, 0, len(rows))
|
||||||
for _, row := range rows {
|
for _, row := range rows {
|
||||||
records = append(records, rechargeRewardClaimRecordView(row, displayMonth, rechargeDate, details[row.UserID], rewardItems))
|
records = append(records, rechargeRewardClaimRecordView(row, displayMonth, rechargeDate, details[row.UserID], rewardItems))
|
||||||
|
|||||||
@ -39,7 +39,7 @@ func (s *Service) GetConfig(ctx context.Context, sysOrigin string) (*RechargeRew
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rewardItems := s.loadRewardItemsMap(ctx, levels)
|
rewardItems := s.loadRewardItemsMap(ctx, configRow.SysOrigin, levels)
|
||||||
return &RechargeRewardConfigResponse{
|
return &RechargeRewardConfigResponse{
|
||||||
Configured: true,
|
Configured: true,
|
||||||
ID: configRow.ID,
|
ID: configRow.ID,
|
||||||
@ -60,7 +60,7 @@ func (s *Service) SaveConfig(ctx context.Context, req SaveRechargeRewardConfigRe
|
|||||||
return nil, NewAppError(http.StatusBadRequest, "invalid_timezone", err.Error())
|
return nil, NewAppError(http.StatusBadRequest, "invalid_timezone", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
levels, err := s.normalizeLevelInputs(req.LevelConfigs)
|
levels, err := s.normalizeLevelInputs(ctx, sysOrigin, req.LevelConfigs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ func (s *Service) SaveConfig(ctx context.Context, req SaveRechargeRewardConfigRe
|
|||||||
return s.GetConfig(ctx, rechargeRewardSysOriginBySavedID(ctx, s.db, savedConfigID, sysOrigin))
|
return s.GetConfig(ctx, rechargeRewardSysOriginBySavedID(ctx, s.db, savedConfigID, sysOrigin))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) normalizeLevelInputs(inputs []RechargeRewardLevelInput) ([]model.RechargeRewardLevel, error) {
|
func (s *Service) normalizeLevelInputs(ctx context.Context, sysOrigin string, inputs []RechargeRewardLevelInput) ([]model.RechargeRewardLevel, error) {
|
||||||
if len(inputs) == 0 {
|
if len(inputs) == 0 {
|
||||||
return nil, NewAppError(http.StatusBadRequest, "invalid_level_configs", "levelConfigs is required")
|
return nil, NewAppError(http.StatusBadRequest, "invalid_level_configs", "levelConfigs is required")
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ func (s *Service) normalizeLevelInputs(inputs []RechargeRewardLevelInput) ([]mod
|
|||||||
if amountCents <= 0 {
|
if amountCents <= 0 {
|
||||||
return nil, NewAppError(http.StatusBadRequest, "invalid_recharge_amount", "rechargeAmount must be greater than 0")
|
return nil, NewAppError(http.StatusBadRequest, "invalid_recharge_amount", "rechargeAmount must be greater than 0")
|
||||||
}
|
}
|
||||||
rewardGroupID := item.RewardGroupID.Int64Ptr()
|
rewardGroupID := s.resolveRewardGroupID(ctx, sysOrigin, item.RewardGroupID.Int64Ptr(), item.RewardGroupName)
|
||||||
if item.RewardGold <= 0 && (rewardGroupID == nil || *rewardGroupID <= 0) {
|
if item.RewardGold <= 0 && (rewardGroupID == nil || *rewardGroupID <= 0) {
|
||||||
return nil, NewAppError(http.StatusBadRequest, "invalid_reward", "rewardGold or rewardGroupId is required")
|
return nil, NewAppError(http.StatusBadRequest, "invalid_reward", "rewardGold or rewardGroupId is required")
|
||||||
}
|
}
|
||||||
@ -188,6 +188,22 @@ func (s *Service) normalizeLevelInputs(inputs []RechargeRewardLevelInput) ([]mod
|
|||||||
return rows, nil
|
return rows, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) resolveRewardGroupID(ctx context.Context, sysOrigin string, rewardGroupID *int64, rewardGroupName string) *int64 {
|
||||||
|
normalized := normalizeRewardGroupID(rewardGroupID)
|
||||||
|
if normalized == nil || s.java == nil || strings.TrimSpace(rewardGroupName) == "" {
|
||||||
|
return normalized
|
||||||
|
}
|
||||||
|
if detail, err := s.java.GetRewardGroupDetail(ctx, *normalized); err == nil && rewardGroupDetailHasItems(detail) {
|
||||||
|
return normalized
|
||||||
|
}
|
||||||
|
detail, err := s.java.FindRewardGroupDetail(ctx, sysOrigin, rewardGroupName)
|
||||||
|
if err != nil || int64(detail.ID) <= 0 {
|
||||||
|
return normalized
|
||||||
|
}
|
||||||
|
resolved := int64(detail.ID)
|
||||||
|
return &resolved
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) loadConfigBundle(ctx context.Context, sysOrigin string) (*rechargeRewardConfigBundle, error) {
|
func (s *Service) loadConfigBundle(ctx context.Context, sysOrigin string) (*rechargeRewardConfigBundle, error) {
|
||||||
sysOrigin = s.normalizeSysOrigin(sysOrigin)
|
sysOrigin = s.normalizeSysOrigin(sysOrigin)
|
||||||
|
|
||||||
|
|||||||
@ -224,6 +224,46 @@ INSERT INTO likei_wallet.user_freight_balance_running_water (accept_user_id, sys
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetHomeFallsBackToRewardGroupNameWhenStoredIDLostPrecision(t *testing.T) {
|
||||||
|
actualGroupID := int64(2056723577461338114)
|
||||||
|
roundedGroupID := int64(2056723577461338000)
|
||||||
|
service, _ := newTestService(t, rechargeRewardTestGateway{
|
||||||
|
groups: map[int64]integration.RewardGroupDetail{
|
||||||
|
actualGroupID: {
|
||||||
|
ID: integration.Int64Value(actualGroupID),
|
||||||
|
Name: "累充活动$50",
|
||||||
|
RewardConfigList: []integration.RewardGroupItem{
|
||||||
|
{ID: integration.Int64Value(1), Type: "BADGE", Name: "recharge50$", Quantity: integration.Int64Value(30), Cover: "https://example.com/badge.png"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if _, err := service.SaveConfig(context.Background(), SaveRechargeRewardConfigRequest{
|
||||||
|
SysOrigin: "LIKEI",
|
||||||
|
Enabled: true,
|
||||||
|
Timezone: "Asia/Riyadh",
|
||||||
|
LevelConfigs: []RechargeRewardLevelInput{
|
||||||
|
{Level: 1, RechargeAmount: mustAmount(t, "50"), RewardGroupID: ptrFlexibleInt64(roundedGroupID), RewardGroupName: "累充活动$50", Enabled: true},
|
||||||
|
},
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatalf("SaveConfig() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := service.GetConfig(context.Background(), "LIKEI")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetConfig() error = %v", err)
|
||||||
|
}
|
||||||
|
if len(resp.LevelConfigs) != 1 || len(resp.LevelConfigs[0].RewardItems) != 1 {
|
||||||
|
t.Fatalf("reward items = %+v, want fallback by reward group name", resp.LevelConfigs)
|
||||||
|
}
|
||||||
|
if resp.LevelConfigs[0].RewardGroupID == nil || *resp.LevelConfigs[0].RewardGroupID != actualGroupID {
|
||||||
|
t.Fatalf("rewardGroupId = %v, want resolved actual group id %d", resp.LevelConfigs[0].RewardGroupID, actualGroupID)
|
||||||
|
}
|
||||||
|
if got := resp.LevelConfigs[0].RewardItems[0].Name; got != "recharge50$" {
|
||||||
|
t.Fatalf("reward item name = %q, want recharge50$", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPageClaimRecordsUsesActualReceiveRecords(t *testing.T) {
|
func TestPageClaimRecordsUsesActualReceiveRecords(t *testing.T) {
|
||||||
groupID := int64(9001)
|
groupID := int64(9001)
|
||||||
service, db := newTestService(t, rechargeRewardTestGateway{
|
service, db := newTestService(t, rechargeRewardTestGateway{
|
||||||
@ -408,6 +448,15 @@ func (g rechargeRewardTestGateway) GetRewardGroupDetail(_ context.Context, group
|
|||||||
return integration.RewardGroupDetail{}, fmt.Errorf("group not found")
|
return integration.RewardGroupDetail{}, fmt.Errorf("group not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g rechargeRewardTestGateway) FindRewardGroupDetail(_ context.Context, _ string, name string) (integration.RewardGroupDetail, error) {
|
||||||
|
for _, detail := range g.groups {
|
||||||
|
if detail.Name == name {
|
||||||
|
return detail, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return integration.RewardGroupDetail{}, fmt.Errorf("group not found")
|
||||||
|
}
|
||||||
|
|
||||||
func (g rechargeRewardTestGateway) MapUserTotalRecharge(context.Context, []int64) (map[int64][]integration.UserTotalRecharge, error) {
|
func (g rechargeRewardTestGateway) MapUserTotalRecharge(context.Context, []int64) (map[int64][]integration.UserTotalRecharge, error) {
|
||||||
return g.total, nil
|
return g.total, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,7 +83,7 @@ func (s *Service) GetHome(ctx context.Context, user AuthUser) (*RechargeRewardHo
|
|||||||
resp.NextRechargeAmount = formatAmountCents(next.RechargeAmountCents)
|
resp.NextRechargeAmount = formatAmountCents(next.RechargeAmountCents)
|
||||||
resp.NextRechargeAmountCents = next.RechargeAmountCents
|
resp.NextRechargeAmountCents = next.RechargeAmountCents
|
||||||
}
|
}
|
||||||
rewardItems := s.loadRewardItemsMap(ctx, bundle.Levels)
|
rewardItems := s.loadRewardItemsMap(ctx, resp.SysOrigin, bundle.Levels)
|
||||||
matchedLevel := 0
|
matchedLevel := 0
|
||||||
if matchedOK {
|
if matchedOK {
|
||||||
matchedLevel = matched.Level
|
matchedLevel = matched.Level
|
||||||
|
|||||||
@ -131,6 +131,7 @@ func sortLevels(levels []rechargeRewardLevelSnapshot) {
|
|||||||
|
|
||||||
func (s *Service) loadRewardItemsMap(
|
func (s *Service) loadRewardItemsMap(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
sysOrigin string,
|
||||||
levels []rechargeRewardLevelSnapshot,
|
levels []rechargeRewardLevelSnapshot,
|
||||||
) map[int64][]RechargeRewardRewardItem {
|
) map[int64][]RechargeRewardRewardItem {
|
||||||
if s.java == nil {
|
if s.java == nil {
|
||||||
@ -138,10 +139,14 @@ func (s *Service) loadRewardItemsMap(
|
|||||||
}
|
}
|
||||||
groupIDs := make([]int64, 0)
|
groupIDs := make([]int64, 0)
|
||||||
seen := make(map[int64]struct{})
|
seen := make(map[int64]struct{})
|
||||||
|
groupNames := make(map[int64]string)
|
||||||
for _, level := range levels {
|
for _, level := range levels {
|
||||||
if level.RewardGroupID == nil || *level.RewardGroupID <= 0 {
|
if level.RewardGroupID == nil || *level.RewardGroupID <= 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if strings.TrimSpace(level.RewardGroupName) != "" {
|
||||||
|
groupNames[*level.RewardGroupID] = level.RewardGroupName
|
||||||
|
}
|
||||||
if _, exists := seen[*level.RewardGroupID]; exists {
|
if _, exists := seen[*level.RewardGroupID]; exists {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -153,15 +158,23 @@ func (s *Service) loadRewardItemsMap(
|
|||||||
result := make(map[int64][]RechargeRewardRewardItem, len(groupIDs))
|
result := make(map[int64][]RechargeRewardRewardItem, len(groupIDs))
|
||||||
for _, groupID := range groupIDs {
|
for _, groupID := range groupIDs {
|
||||||
detail, err := s.java.GetRewardGroupDetail(ctx, groupID)
|
detail, err := s.java.GetRewardGroupDetail(ctx, groupID)
|
||||||
if err != nil {
|
if err != nil || !rewardGroupDetailHasItems(detail) {
|
||||||
result[groupID] = []RechargeRewardRewardItem{}
|
if fallback, fallbackErr := s.java.FindRewardGroupDetail(ctx, sysOrigin, groupNames[groupID]); fallbackErr == nil && rewardGroupDetailHasItems(fallback) {
|
||||||
continue
|
detail = fallback
|
||||||
|
} else {
|
||||||
|
result[groupID] = []RechargeRewardRewardItem{}
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
result[groupID] = rewardItemsFromGroup(detail)
|
result[groupID] = rewardItemsFromGroup(detail)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func rewardGroupDetailHasItems(detail integration.RewardGroupDetail) bool {
|
||||||
|
return len(detail.RewardConfigList) > 0
|
||||||
|
}
|
||||||
|
|
||||||
func rewardItemsFromGroup(detail integration.RewardGroupDetail) []RechargeRewardRewardItem {
|
func rewardItemsFromGroup(detail integration.RewardGroupDetail) []RechargeRewardRewardItem {
|
||||||
items := make([]RechargeRewardRewardItem, 0, len(detail.RewardConfigList))
|
items := make([]RechargeRewardRewardItem, 0, len(detail.RewardConfigList))
|
||||||
for _, item := range detail.RewardConfigList {
|
for _, item := range detail.RewardConfigList {
|
||||||
|
|||||||
@ -35,6 +35,7 @@ type rechargeRewardDB interface {
|
|||||||
type rechargeRewardJavaGateway interface {
|
type rechargeRewardJavaGateway interface {
|
||||||
GetUserProfile(ctx context.Context, userID int64) (integration.UserProfile, error)
|
GetUserProfile(ctx context.Context, userID int64) (integration.UserProfile, error)
|
||||||
GetRewardGroupDetail(ctx context.Context, groupID int64) (integration.RewardGroupDetail, error)
|
GetRewardGroupDetail(ctx context.Context, groupID int64) (integration.RewardGroupDetail, error)
|
||||||
|
FindRewardGroupDetail(ctx context.Context, sysOrigin string, name string) (integration.RewardGroupDetail, error)
|
||||||
MapUserTotalRecharge(ctx context.Context, userIDs []int64) (map[int64][]integration.UserTotalRecharge, error)
|
MapUserTotalRecharge(ctx context.Context, userIDs []int64) (map[int64][]integration.UserTotalRecharge, error)
|
||||||
GetThisMonthTotalPersonalRecharge(ctx context.Context, userID int64) (integration.DecimalString, error)
|
GetThisMonthTotalPersonalRecharge(ctx context.Context, userID int64) (integration.DecimalString, error)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user