195 lines
5.7 KiB
Go
195 lines
5.7 KiB
Go
package voiceroomredpacket
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"time"
|
|
|
|
"chatapp3-golang/internal/model"
|
|
"chatapp3-golang/internal/utils"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// GetConfig 返回 App 当前红包配置和用户今日发送次数。
|
|
func (s *Service) GetConfig(ctx context.Context, user AuthUser) (*ConfigResponse, error) {
|
|
snapshot, err := s.loadConfig(ctx, user.SysOrigin)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
todayCount := 0
|
|
if user.UserID > 0 {
|
|
location := resolveLocation(snapshot.Timezone)
|
|
count, err := s.loadDailySendCount(ctx, snapshot.SysOrigin, user.UserID, dayKey(time.Now().In(location)))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
todayCount = count
|
|
}
|
|
resp := configResponse(snapshot)
|
|
resp.TodaySendCount = todayCount
|
|
return resp, nil
|
|
}
|
|
|
|
// GetAdminConfig 返回后台配置。
|
|
func (s *Service) GetAdminConfig(ctx context.Context, sysOrigin string) (*ConfigResponse, error) {
|
|
snapshot, err := s.loadConfig(ctx, sysOrigin)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return configResponse(snapshot), nil
|
|
}
|
|
|
|
// SaveAdminConfig 保存后台配置。
|
|
func (s *Service) SaveAdminConfig(ctx context.Context, req SaveConfigRequest) (*ConfigResponse, error) {
|
|
sysOrigin := normalizeSysOrigin(req.SysOrigin)
|
|
timezone := normalizeTimezone(req.Timezone)
|
|
if _, err := time.LoadLocation(timezone); err != nil {
|
|
return nil, NewAppError(http.StatusBadRequest, "invalid_timezone", err.Error())
|
|
}
|
|
amountOptions := req.AmountOptions
|
|
if len(amountOptions) == 0 {
|
|
amountOptions = defaultAmountOptions()
|
|
}
|
|
countOptions := req.CountOptions
|
|
if len(countOptions) == 0 {
|
|
countOptions = defaultCountOptions()
|
|
}
|
|
dailyLimit := req.DailySendLimit
|
|
if dailyLimit <= 0 {
|
|
dailyLimit = defaultDailySendLimit
|
|
}
|
|
delaySeconds := req.DelaySeconds
|
|
if delaySeconds <= 0 {
|
|
delaySeconds = defaultDelaySeconds
|
|
}
|
|
refundAfterSeconds := req.RefundAfterSeconds
|
|
if refundAfterSeconds <= 0 {
|
|
refundAfterSeconds = defaultRefundAfterSeconds
|
|
}
|
|
|
|
var configID int64
|
|
if err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
now := time.Now()
|
|
var row model.VoiceRoomRedPacketConfig
|
|
err := tx.Where("sys_origin = ?", sysOrigin).First(&row).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
id, idErr := utils.NextID()
|
|
if idErr != nil {
|
|
return idErr
|
|
}
|
|
row = model.VoiceRoomRedPacketConfig{
|
|
ID: id,
|
|
SysOrigin: sysOrigin,
|
|
CreateTime: now,
|
|
}
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
row.Enabled = req.Enabled
|
|
row.DailySendLimit = dailyLimit
|
|
row.DelaySeconds = delaySeconds
|
|
row.RefundAfterSeconds = refundAfterSeconds
|
|
row.Timezone = timezone
|
|
row.AmountOptions = joinInt64CSV(amountOptions)
|
|
row.CountOptions = joinIntCSV(countOptions)
|
|
row.UpdateTime = now
|
|
if row.CreateTime.IsZero() {
|
|
row.CreateTime = now
|
|
}
|
|
if err := tx.Save(&row).Error; err != nil {
|
|
return err
|
|
}
|
|
configID = row.ID
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
_ = configID
|
|
return s.GetAdminConfig(ctx, sysOrigin)
|
|
}
|
|
|
|
func (s *Service) loadConfig(ctx context.Context, sysOrigin string) (configSnapshot, error) {
|
|
sysOrigin = normalizeSysOrigin(sysOrigin)
|
|
var row model.VoiceRoomRedPacketConfig
|
|
err := s.db.WithContext(ctx).Where("sys_origin = ?", sysOrigin).First(&row).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return configSnapshot{
|
|
SysOrigin: sysOrigin,
|
|
Enabled: false,
|
|
DailySendLimit: defaultDailySendLimit,
|
|
DelaySeconds: defaultDelaySeconds,
|
|
RefundAfterSeconds: defaultRefundAfterSeconds,
|
|
Timezone: defaultTimezone,
|
|
AmountOptions: defaultAmountOptions(),
|
|
CountOptions: defaultCountOptions(),
|
|
}, nil
|
|
}
|
|
if err != nil {
|
|
return configSnapshot{}, err
|
|
}
|
|
return configSnapshot{
|
|
ID: row.ID,
|
|
SysOrigin: row.SysOrigin,
|
|
Enabled: row.Enabled,
|
|
DailySendLimit: positiveOrDefault(row.DailySendLimit, defaultDailySendLimit),
|
|
DelaySeconds: positiveOrDefault(row.DelaySeconds, defaultDelaySeconds),
|
|
RefundAfterSeconds: positiveOrDefault(row.RefundAfterSeconds, defaultRefundAfterSeconds),
|
|
Timezone: normalizeTimezone(row.Timezone),
|
|
AmountOptions: parseInt64CSV(row.AmountOptions, defaultAmountOptions()),
|
|
CountOptions: parseIntCSV(row.CountOptions, defaultCountOptions()),
|
|
Configured: true,
|
|
UpdateTime: row.UpdateTime,
|
|
}, nil
|
|
}
|
|
|
|
func configResponse(snapshot configSnapshot) *ConfigResponse {
|
|
return &ConfigResponse{
|
|
Configured: snapshot.Configured,
|
|
ID: snapshot.ID,
|
|
SysOrigin: snapshot.SysOrigin,
|
|
Enabled: snapshot.Enabled,
|
|
DailySendLimit: snapshot.DailySendLimit,
|
|
DelaySeconds: snapshot.DelaySeconds,
|
|
RefundAfterSeconds: snapshot.RefundAfterSeconds,
|
|
Timezone: snapshot.Timezone,
|
|
AmountOptions: append([]int64(nil), snapshot.AmountOptions...),
|
|
CountOptions: append([]int(nil), snapshot.CountOptions...),
|
|
UpdateTime: formatTime(snapshot.UpdateTime),
|
|
}
|
|
}
|
|
|
|
func positiveOrDefault(value, fallback int) int {
|
|
if value <= 0 {
|
|
return fallback
|
|
}
|
|
return value
|
|
}
|
|
|
|
func resolveLocation(timezone string) *time.Location {
|
|
location, err := time.LoadLocation(normalizeTimezone(timezone))
|
|
if err != nil {
|
|
return time.UTC
|
|
}
|
|
return location
|
|
}
|
|
|
|
func dayKey(t time.Time) string {
|
|
return t.Format("20060102")
|
|
}
|
|
|
|
func (s *Service) loadDailySendCount(ctx context.Context, sysOrigin string, userID int64, day string) (int, error) {
|
|
var row model.VoiceRoomRedPacketDailyCounter
|
|
err := s.db.WithContext(ctx).
|
|
Where("sys_origin = ? AND user_id = ? AND day_key = ?", sysOrigin, userID, day).
|
|
First(&row).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return 0, nil
|
|
}
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return row.SendCount, nil
|
|
}
|