212 lines
6.3 KiB
Go
212 lines
6.3 KiB
Go
package roomturnoverreward
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"chatapp3-golang/internal/model"
|
|
"chatapp3-golang/internal/utils"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// GetConfig 返回系统当前房间流水奖励配置;未配置时返回默认档位草稿。
|
|
func (s *Service) GetConfig(ctx context.Context, sysOrigin string) (*RoomTurnoverRewardConfigResponse, error) {
|
|
sysOrigin = s.normalizeSysOrigin(sysOrigin)
|
|
|
|
var configRow model.RoomTurnoverRewardConfig
|
|
err := s.repo.DB.WithContext(ctx).
|
|
Where("sys_origin = ?", sysOrigin).
|
|
First(&configRow).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return &RoomTurnoverRewardConfigResponse{
|
|
Configured: false,
|
|
SysOrigin: sysOrigin,
|
|
Enabled: false,
|
|
Timezone: s.defaultTimezone(),
|
|
LevelConfigs: defaultLevelPayloads(),
|
|
}, nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
levels, err := s.loadLevels(ctx, configRow.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &RoomTurnoverRewardConfigResponse{
|
|
Configured: true,
|
|
ID: configRow.ID,
|
|
SysOrigin: configRow.SysOrigin,
|
|
Enabled: configRow.Enabled,
|
|
Timezone: configRow.Timezone,
|
|
UpdateTime: formatDateTime(configRow.UpdateTime),
|
|
LevelConfigs: buildLevelPayloads(levels),
|
|
}, nil
|
|
}
|
|
|
|
// SaveConfig 保存系统级房间流水奖励配置;同一系统只保留一份当前配置。
|
|
func (s *Service) SaveConfig(ctx context.Context, req SaveRoomTurnoverRewardConfigRequest) (*RoomTurnoverRewardConfigResponse, error) {
|
|
requestID := req.ID.Int64()
|
|
sysOrigin := s.normalizeSysOrigin(req.SysOrigin)
|
|
timezone := strings.TrimSpace(req.Timezone)
|
|
if timezone == "" {
|
|
timezone = s.defaultTimezone()
|
|
}
|
|
if _, err := time.LoadLocation(timezone); err != nil {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_timezone", err.Error())
|
|
}
|
|
|
|
levels, err := s.normalizeLevelInputs(req.LevelConfigs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if req.Enabled {
|
|
hasEnabledLevel := false
|
|
for _, level := range levels {
|
|
if level.Enabled {
|
|
hasEnabledLevel = true
|
|
break
|
|
}
|
|
}
|
|
if !hasEnabledLevel {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_level_configs", "enabled config must contain at least one enabled level")
|
|
}
|
|
}
|
|
|
|
var savedConfigID int64
|
|
if err := s.repo.DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
now := time.Now()
|
|
var configRow model.RoomTurnoverRewardConfig
|
|
if requestID > 0 {
|
|
err := tx.Where("id = ?", requestID).First(&configRow).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return NewAppError(http.StatusNotFound, "room_turnover_reward_config_not_found", "config not found")
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if strings.TrimSpace(req.SysOrigin) == "" {
|
|
sysOrigin = configRow.SysOrigin
|
|
}
|
|
} else {
|
|
err := tx.Where("sys_origin = ?", sysOrigin).First(&configRow).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
configID, idErr := utils.NextID()
|
|
if idErr != nil {
|
|
return idErr
|
|
}
|
|
configRow = model.RoomTurnoverRewardConfig{
|
|
ID: configID,
|
|
SysOrigin: sysOrigin,
|
|
CreateTime: now,
|
|
}
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
configRow.SysOrigin = sysOrigin
|
|
configRow.Enabled = req.Enabled
|
|
configRow.Timezone = timezone
|
|
configRow.UpdateTime = now
|
|
if configRow.CreateTime.IsZero() {
|
|
configRow.CreateTime = now
|
|
}
|
|
|
|
if err := tx.Save(&configRow).Error; err != nil {
|
|
return err
|
|
}
|
|
if err := tx.Where("config_id = ?", configRow.ID).Delete(&model.RoomTurnoverRewardLevel{}).Error; err != nil {
|
|
return err
|
|
}
|
|
for index := range levels {
|
|
levels[index].ConfigID = configRow.ID
|
|
levels[index].CreateTime = now
|
|
levels[index].UpdateTime = now
|
|
}
|
|
if err := tx.Create(&levels).Error; err != nil {
|
|
return err
|
|
}
|
|
savedConfigID = configRow.ID
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s.GetConfig(ctx, sysOriginBySavedID(ctx, s.repo.DB, savedConfigID, sysOrigin))
|
|
}
|
|
|
|
func (s *Service) normalizeLevelInputs(inputs []RoomTurnoverRewardLevelInput) ([]model.RoomTurnoverRewardLevel, error) {
|
|
if len(inputs) == 0 {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_level_configs", "levelConfigs is required")
|
|
}
|
|
|
|
seenLevels := make(map[int]struct{}, len(inputs))
|
|
seenThresholds := make(map[int64]struct{}, len(inputs))
|
|
rows := make([]model.RoomTurnoverRewardLevel, 0, len(inputs))
|
|
for _, item := range inputs {
|
|
if item.Level <= 0 {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_level", "level must be greater than 0")
|
|
}
|
|
if item.TurnoverThreshold <= 0 {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_turnover_threshold", "turnoverThreshold must be greater than 0")
|
|
}
|
|
if item.RewardGold <= 0 {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_reward_gold", "rewardGold must be greater than 0")
|
|
}
|
|
if _, exists := seenLevels[item.Level]; exists {
|
|
return nil, NewAppError(http.StatusBadRequest, "duplicate_level", "levelConfigs must not contain duplicate levels")
|
|
}
|
|
if _, exists := seenThresholds[item.TurnoverThreshold]; exists {
|
|
return nil, NewAppError(http.StatusBadRequest, "duplicate_turnover_threshold", "levelConfigs must not contain duplicate thresholds")
|
|
}
|
|
seenLevels[item.Level] = struct{}{}
|
|
seenThresholds[item.TurnoverThreshold] = struct{}{}
|
|
id, err := utils.NextID()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rows = append(rows, model.RoomTurnoverRewardLevel{
|
|
ID: id,
|
|
Level: item.Level,
|
|
TurnoverThreshold: item.TurnoverThreshold,
|
|
RewardGold: item.RewardGold,
|
|
Enabled: item.Enabled,
|
|
})
|
|
}
|
|
|
|
sort.Slice(rows, func(i, j int) bool {
|
|
return rows[i].TurnoverThreshold < rows[j].TurnoverThreshold
|
|
})
|
|
return rows, nil
|
|
}
|
|
|
|
func (s *Service) loadLevels(ctx context.Context, configID int64) ([]model.RoomTurnoverRewardLevel, error) {
|
|
var levels []model.RoomTurnoverRewardLevel
|
|
if configID <= 0 {
|
|
return levels, nil
|
|
}
|
|
err := s.repo.DB.WithContext(ctx).
|
|
Where("config_id = ?", configID).
|
|
Order("level asc").
|
|
Find(&levels).Error
|
|
return levels, err
|
|
}
|
|
|
|
func sysOriginBySavedID(ctx context.Context, db roomTurnoverRewardDB, configID int64, fallback string) string {
|
|
if configID <= 0 {
|
|
return fallback
|
|
}
|
|
var row model.RoomTurnoverRewardConfig
|
|
if err := db.WithContext(ctx).Select("sys_origin").Where("id = ?", configID).First(&row).Error; err != nil {
|
|
return fallback
|
|
}
|
|
return row.SysOrigin
|
|
}
|