255 lines
7.9 KiB
Go
255 lines
7.9 KiB
Go
package registerreward
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"chatapp3-golang/internal/model"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// registerRewardDailyRecordRow 是后台分页查询时使用的中间结果,补齐了用户展示资料。
|
|
type registerRewardDailyRecordRow struct {
|
|
model.ResidentRegisterRewardLog
|
|
Account string `gorm:"column:account"` // 用户账号
|
|
UserAvatar string `gorm:"column:user_avatar"` // 用户头像
|
|
UserNickname string `gorm:"column:user_nickname"` // 用户昵称
|
|
CountryCode string `gorm:"column:country_code"` // 国家编码
|
|
CountryName string `gorm:"column:country_name"` // 国家名称
|
|
}
|
|
|
|
// PageDailyRecords 分页返回指定日期的注册奖励领取记录,供后台查看当日限额使用情况。
|
|
func (s *RegisterRewardService) PageDailyRecords(
|
|
ctx context.Context,
|
|
sysOrigin string,
|
|
claimDate string,
|
|
cursor int,
|
|
limit int,
|
|
) (*RegisterRewardDailyRecordPageResponse, error) {
|
|
normalizedSysOrigin := strings.ToUpper(strings.TrimSpace(sysOrigin))
|
|
if normalizedSysOrigin == "" {
|
|
return nil, NewAppError(http.StatusBadRequest, "bad_request", "sysOrigin is required")
|
|
}
|
|
|
|
resolvedClaimDate := normalizeRegisterRewardClaimDate(claimDate)
|
|
page, size := normalizeRegisterRewardPage(cursor, limit)
|
|
|
|
configRow, err := s.loadRegisterRewardConfig(ctx, normalizedSysOrigin)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
dailyLimit := int64(0)
|
|
if configRow != nil {
|
|
dailyLimit = configRow.DailyLimit
|
|
}
|
|
|
|
var total int64
|
|
if err := s.newDailyRecordBaseQuery(ctx, normalizedSysOrigin, resolvedClaimDate).
|
|
Count(&total).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
occupiedCount, err := s.countDailyRecordsByGrantMode(
|
|
ctx,
|
|
normalizedSysOrigin,
|
|
resolvedClaimDate,
|
|
registerRewardGrantModeIssueReward,
|
|
"",
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
issuedCount, err := s.countDailyRecordsByGrantMode(
|
|
ctx,
|
|
normalizedSysOrigin,
|
|
resolvedClaimDate,
|
|
registerRewardGrantModeIssueReward,
|
|
registerRewardStatusSuccess,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
successCount, err := s.countDailyRecordsByStatus(
|
|
ctx,
|
|
normalizedSysOrigin,
|
|
resolvedClaimDate,
|
|
registerRewardStatusSuccess,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
records := make([]RegisterRewardDailyRecordView, 0)
|
|
if total > 0 {
|
|
var rows []registerRewardDailyRecordRow
|
|
if err := s.newDailyRecordBaseQuery(ctx, normalizedSysOrigin, resolvedClaimDate).
|
|
Select("log.*, user.account, user.user_avatar, user.user_nickname, user.country_code, user.country_name").
|
|
Joins("LEFT JOIN user_base_info AS user ON user.id = log.user_id").
|
|
Order("log.create_time desc").
|
|
Order("log.id desc").
|
|
Offset((page - 1) * size).
|
|
Limit(size).
|
|
Find(&rows).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
records = make([]RegisterRewardDailyRecordView, 0, len(rows))
|
|
for _, row := range rows {
|
|
records = append(records, toRegisterRewardDailyRecordView(row))
|
|
}
|
|
}
|
|
|
|
resp := &RegisterRewardDailyRecordPageResponse{
|
|
Date: resolvedClaimDate,
|
|
LimitEnabled: dailyLimit > 0,
|
|
DailyLimit: dailyLimit,
|
|
OccupiedCount: occupiedCount,
|
|
IssuedCount: issuedCount,
|
|
SuccessCount: successCount,
|
|
RemainingCount: resolveRegisterRewardRemainingCount(
|
|
dailyLimit,
|
|
occupiedCount,
|
|
),
|
|
Records: records,
|
|
Total: total,
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
// newDailyRecordBaseQuery 创建后台领取记录分页的基础查询。
|
|
func (s *RegisterRewardService) newDailyRecordBaseQuery(
|
|
ctx context.Context,
|
|
sysOrigin string,
|
|
claimDate string,
|
|
) *gorm.DB {
|
|
return s.repo.DB.WithContext(ctx).
|
|
Table("resident_register_reward_log AS log").
|
|
Where("log.sys_origin = ? AND log.claim_date = ?", sysOrigin, claimDate)
|
|
}
|
|
|
|
// countDailyRecordsByGrantMode 统计某天某系统在指定发奖模式下的记录数。
|
|
func (s *RegisterRewardService) countDailyRecordsByGrantMode(
|
|
ctx context.Context,
|
|
sysOrigin string,
|
|
claimDate string,
|
|
grantMode string,
|
|
status string,
|
|
) (int64, error) {
|
|
query := s.newDailyRecordBaseQuery(ctx, sysOrigin, claimDate).
|
|
Where("log.grant_mode = ?", grantMode)
|
|
if strings.TrimSpace(status) != "" {
|
|
query = query.Where("log.status = ?", strings.ToUpper(strings.TrimSpace(status)))
|
|
}
|
|
|
|
var total int64
|
|
if err := query.Count(&total).Error; err != nil {
|
|
return 0, err
|
|
}
|
|
return total, nil
|
|
}
|
|
|
|
// countDailyRecordsByStatus 统计某天某系统在指定处理状态下的记录数。
|
|
func (s *RegisterRewardService) countDailyRecordsByStatus(
|
|
ctx context.Context,
|
|
sysOrigin string,
|
|
claimDate string,
|
|
status string,
|
|
) (int64, error) {
|
|
var total int64
|
|
if err := s.newDailyRecordBaseQuery(ctx, sysOrigin, claimDate).
|
|
Where("log.status = ?", strings.ToUpper(strings.TrimSpace(status))).
|
|
Count(&total).Error; err != nil {
|
|
return 0, err
|
|
}
|
|
return total, nil
|
|
}
|
|
|
|
// toRegisterRewardDailyRecordView 把数据库行转换成后台页面直接可用的结构。
|
|
func toRegisterRewardDailyRecordView(row registerRewardDailyRecordRow) RegisterRewardDailyRecordView {
|
|
claimResult := deriveRegisterRewardClaimResult(row.Status, row.GrantMode)
|
|
return RegisterRewardDailyRecordView{
|
|
ID: row.ID,
|
|
SysOrigin: row.SysOrigin,
|
|
UserID: row.UserID,
|
|
Account: row.Account,
|
|
UserAvatar: row.UserAvatar,
|
|
UserNickname: row.UserNickname,
|
|
CountryCode: row.CountryCode,
|
|
CountryName: row.CountryName,
|
|
ClaimDate: row.ClaimDate,
|
|
GrantMode: row.GrantMode,
|
|
ClaimResult: claimResult,
|
|
ClaimResultText: formatRegisterRewardClaimResultText(claimResult),
|
|
GoldAmount: row.GoldAmount,
|
|
RewardGroupID: row.RewardGroupID,
|
|
Status: strings.ToUpper(strings.TrimSpace(row.Status)),
|
|
ErrorMessage: strings.TrimSpace(row.ErrorMessage),
|
|
CreateTime: formatRegisterRewardTime(row.CreateTime),
|
|
UpdateTime: formatRegisterRewardTime(row.UpdateTime),
|
|
}
|
|
}
|
|
|
|
// normalizeRegisterRewardPage 规范分页参数,避免非法页码或 pageSize。
|
|
func normalizeRegisterRewardPage(cursor int, limit int) (int, int) {
|
|
if cursor <= 0 {
|
|
cursor = 1
|
|
}
|
|
if limit <= 0 {
|
|
limit = 20
|
|
}
|
|
if limit > 100 {
|
|
limit = 100
|
|
}
|
|
return cursor, limit
|
|
}
|
|
|
|
// resolveRegisterRewardRemainingCount 计算当前日期还剩余多少可发名额。
|
|
func resolveRegisterRewardRemainingCount(dailyLimit int64, occupiedCount int64) int64 {
|
|
if dailyLimit <= 0 {
|
|
return 0
|
|
}
|
|
if occupiedCount >= dailyLimit {
|
|
return 0
|
|
}
|
|
return dailyLimit - occupiedCount
|
|
}
|
|
|
|
// deriveRegisterRewardClaimResult 统一归并后台页面展示的领取结果。
|
|
func deriveRegisterRewardClaimResult(status string, grantMode string) string {
|
|
normalizedStatus := strings.ToUpper(strings.TrimSpace(status))
|
|
normalizedGrantMode := strings.ToUpper(strings.TrimSpace(grantMode))
|
|
|
|
switch {
|
|
case normalizedGrantMode == registerRewardGrantModeQuotaExhausted && normalizedStatus == registerRewardStatusSuccess:
|
|
return registerRewardClaimResultQuotaExhausted
|
|
case normalizedGrantMode == registerRewardGrantModeIssueReward && normalizedStatus == registerRewardStatusSuccess:
|
|
return registerRewardClaimResultRewarded
|
|
case normalizedGrantMode == registerRewardGrantModeIssueReward && normalizedStatus == registerRewardStatusFailed:
|
|
return registerRewardClaimResultFailed
|
|
case normalizedGrantMode == registerRewardGrantModeIssueReward && normalizedStatus == registerRewardStatusPending:
|
|
return registerRewardClaimResultPending
|
|
case normalizedStatus == registerRewardStatusSkipped:
|
|
return registerRewardClaimResultSkipped
|
|
default:
|
|
return registerRewardClaimResultPending
|
|
}
|
|
}
|
|
|
|
// formatRegisterRewardClaimResultText 返回后台页面展示用的中文领取结果文案。
|
|
func formatRegisterRewardClaimResultText(claimResult string) string {
|
|
switch strings.ToUpper(strings.TrimSpace(claimResult)) {
|
|
case registerRewardClaimResultRewarded:
|
|
return "已发放"
|
|
case registerRewardClaimResultQuotaExhausted:
|
|
return "名额已满,视为领取成功"
|
|
case registerRewardClaimResultFailed:
|
|
return "发奖失败,待补发"
|
|
case registerRewardClaimResultSkipped:
|
|
return "已跳过"
|
|
default:
|
|
return "发放中"
|
|
}
|
|
}
|