240 lines
7.1 KiB
Go
240 lines
7.1 KiB
Go
package rechargereward
|
|
|
|
import (
|
|
"context"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"chatapp3-golang/internal/integration"
|
|
"chatapp3-golang/internal/model"
|
|
)
|
|
|
|
func configSnapshotFromModel(row model.RechargeRewardConfig) rechargeRewardConfigSnapshot {
|
|
return rechargeRewardConfigSnapshot{
|
|
ID: row.ID,
|
|
SysOrigin: row.SysOrigin,
|
|
Enabled: row.Enabled,
|
|
Timezone: normalizeRechargeRewardTimezone(row.Timezone),
|
|
UpdateTime: row.UpdateTime,
|
|
}
|
|
}
|
|
|
|
func levelSnapshotFromModel(row model.RechargeRewardLevel) rechargeRewardLevelSnapshot {
|
|
return rechargeRewardLevelSnapshot{
|
|
ID: row.ID,
|
|
Level: row.Level,
|
|
RechargeAmountCents: row.RechargeAmountCents,
|
|
RewardGold: row.RewardGold,
|
|
RewardGroupID: row.RewardGroupID,
|
|
RewardGroupName: strings.TrimSpace(row.RewardGroupName),
|
|
Enabled: row.Enabled,
|
|
}
|
|
}
|
|
|
|
func buildLevelPayloads(
|
|
levels []rechargeRewardLevelSnapshot,
|
|
rewardItems map[int64][]RechargeRewardRewardItem,
|
|
currentRechargeCents int64,
|
|
matchedLevel int,
|
|
) []RechargeRewardLevelPayload {
|
|
payloads := make([]RechargeRewardLevelPayload, 0, len(levels))
|
|
for _, level := range levels {
|
|
if !level.Enabled {
|
|
continue
|
|
}
|
|
var items []RechargeRewardRewardItem
|
|
if level.RewardGroupID != nil {
|
|
items = rewardItems[*level.RewardGroupID]
|
|
}
|
|
if items == nil {
|
|
items = []RechargeRewardRewardItem{}
|
|
}
|
|
payloads = append(payloads, RechargeRewardLevelPayload{
|
|
ID: level.ID,
|
|
Level: level.Level,
|
|
RechargeAmount: formatAmountCents(level.RechargeAmountCents),
|
|
RechargeAmountCents: level.RechargeAmountCents,
|
|
RewardGold: level.RewardGold,
|
|
RewardGroupID: level.RewardGroupID,
|
|
RewardGroupName: level.RewardGroupName,
|
|
RewardItems: items,
|
|
Enabled: level.Enabled,
|
|
Reached: currentRechargeCents >= level.RechargeAmountCents,
|
|
Current: matchedLevel > 0 && level.Level == matchedLevel,
|
|
})
|
|
}
|
|
return payloads
|
|
}
|
|
|
|
func buildAdminLevelPayloads(
|
|
levels []rechargeRewardLevelSnapshot,
|
|
rewardItems map[int64][]RechargeRewardRewardItem,
|
|
) []RechargeRewardLevelPayload {
|
|
payloads := make([]RechargeRewardLevelPayload, 0, len(levels))
|
|
for _, level := range levels {
|
|
var items []RechargeRewardRewardItem
|
|
if level.RewardGroupID != nil {
|
|
items = rewardItems[*level.RewardGroupID]
|
|
}
|
|
if items == nil {
|
|
items = []RechargeRewardRewardItem{}
|
|
}
|
|
payloads = append(payloads, RechargeRewardLevelPayload{
|
|
ID: level.ID,
|
|
Level: level.Level,
|
|
RechargeAmount: formatAmountCents(level.RechargeAmountCents),
|
|
RechargeAmountCents: level.RechargeAmountCents,
|
|
RewardGold: level.RewardGold,
|
|
RewardGroupID: level.RewardGroupID,
|
|
RewardGroupName: level.RewardGroupName,
|
|
RewardItems: items,
|
|
Enabled: level.Enabled,
|
|
})
|
|
}
|
|
return payloads
|
|
}
|
|
|
|
func pickMatchedLevel(levels []rechargeRewardLevelSnapshot, currentRechargeCents int64) (rechargeRewardLevelSnapshot, bool) {
|
|
var matched rechargeRewardLevelSnapshot
|
|
ok := false
|
|
for _, level := range levels {
|
|
if !level.Enabled || level.RechargeAmountCents <= 0 {
|
|
continue
|
|
}
|
|
if currentRechargeCents >= level.RechargeAmountCents && (!ok || level.RechargeAmountCents > matched.RechargeAmountCents) {
|
|
matched = level
|
|
ok = true
|
|
}
|
|
}
|
|
return matched, ok
|
|
}
|
|
|
|
func pickNextLevel(levels []rechargeRewardLevelSnapshot, currentRechargeCents int64) (rechargeRewardLevelSnapshot, bool) {
|
|
for _, level := range levels {
|
|
if !level.Enabled || level.RechargeAmountCents <= currentRechargeCents {
|
|
continue
|
|
}
|
|
return level, true
|
|
}
|
|
return rechargeRewardLevelSnapshot{}, false
|
|
}
|
|
|
|
func sortLevels(levels []rechargeRewardLevelSnapshot) {
|
|
sort.Slice(levels, func(i, j int) bool {
|
|
if levels[i].RechargeAmountCents == levels[j].RechargeAmountCents {
|
|
return levels[i].Level < levels[j].Level
|
|
}
|
|
return levels[i].RechargeAmountCents < levels[j].RechargeAmountCents
|
|
})
|
|
}
|
|
|
|
func (s *Service) loadRewardItemsMap(
|
|
ctx context.Context,
|
|
sysOrigin string,
|
|
levels []rechargeRewardLevelSnapshot,
|
|
) map[int64][]RechargeRewardRewardItem {
|
|
if s.java == nil {
|
|
return map[int64][]RechargeRewardRewardItem{}
|
|
}
|
|
groupIDs := make([]int64, 0)
|
|
seen := make(map[int64]struct{})
|
|
groupNames := make(map[int64]string)
|
|
for _, level := range levels {
|
|
if level.RewardGroupID == nil || *level.RewardGroupID <= 0 {
|
|
continue
|
|
}
|
|
if strings.TrimSpace(level.RewardGroupName) != "" {
|
|
groupNames[*level.RewardGroupID] = level.RewardGroupName
|
|
}
|
|
if _, exists := seen[*level.RewardGroupID]; exists {
|
|
continue
|
|
}
|
|
seen[*level.RewardGroupID] = struct{}{}
|
|
groupIDs = append(groupIDs, *level.RewardGroupID)
|
|
}
|
|
sort.Slice(groupIDs, func(i, j int) bool { return groupIDs[i] < groupIDs[j] })
|
|
|
|
result := make(map[int64][]RechargeRewardRewardItem, len(groupIDs))
|
|
for _, groupID := range groupIDs {
|
|
detail, err := s.java.GetRewardGroupDetail(ctx, groupID)
|
|
if err != nil || !rewardGroupDetailHasItems(detail) {
|
|
if fallback, fallbackErr := s.java.FindRewardGroupDetail(ctx, sysOrigin, groupNames[groupID]); fallbackErr == nil && rewardGroupDetailHasItems(fallback) {
|
|
detail = fallback
|
|
} else {
|
|
result[groupID] = []RechargeRewardRewardItem{}
|
|
continue
|
|
}
|
|
}
|
|
result[groupID] = rewardItemsFromGroup(detail)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func rewardGroupDetailHasItems(detail integration.RewardGroupDetail) bool {
|
|
return len(detail.RewardConfigList) > 0
|
|
}
|
|
|
|
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 {
|
|
total += parseIntegrationAmountCents(integrationAmount(entry.Amount))
|
|
}
|
|
return total
|
|
}
|
|
|
|
func formatDateTime(t time.Time) string {
|
|
if t.IsZero() {
|
|
return ""
|
|
}
|
|
return t.Format("2006-01-02 15:04:05")
|
|
}
|