2026-05-26 20:06:23 +08:00

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")
}