2026-04-29 18:45:52 +08:00

167 lines
4.5 KiB
Go

package vip
import (
"context"
"net/http"
"strconv"
"strings"
"time"
"chatapp3-golang/internal/model"
)
// PageOrders returns VIP purchase records for the admin page.
func (s *Service) PageOrders(
ctx context.Context,
sysOrigin string,
userID int64,
status string,
orderType string,
cursor int,
limit int,
) (*OrderPageResponse, error) {
sysOrigin = normalizeSysOrigin(sysOrigin)
if sysOrigin == "" {
return nil, NewAppError(http.StatusBadRequest, "bad_request", "sysOrigin is required")
}
page, size := normalizePage(cursor, limit)
query := s.db.WithContext(ctx).Model(&model.VipOrderRecord{}).Where("sys_origin = ?", sysOrigin)
if userID > 0 {
query = query.Where("user_id = ?", userID)
}
if normalizedStatus := strings.ToUpper(strings.TrimSpace(status)); normalizedStatus != "" {
query = query.Where("status = ?", normalizedStatus)
}
if normalizedType := strings.ToUpper(strings.TrimSpace(orderType)); normalizedType != "" {
query = query.Where("order_type = ?", normalizedType)
}
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, err
}
records := make([]VipOrderPayload, 0)
if total > 0 {
var rows []model.VipOrderRecord
if err := query.
Order("create_time desc").
Order("id desc").
Offset((page - 1) * size).
Limit(size).
Find(&rows).Error; err != nil {
return nil, err
}
records = make([]VipOrderPayload, 0, len(rows))
for _, row := range rows {
records = append(records, orderPayloadFromModel(row))
}
}
return &OrderPageResponse{Records: records, Total: total}, nil
}
// PageUserStates returns the current VIP state rows for the admin page.
func (s *Service) PageUserStates(
ctx context.Context,
sysOrigin string,
userID int64,
status string,
cursor int,
limit int,
) (*UserStatePageResponse, error) {
sysOrigin = normalizeSysOrigin(sysOrigin)
if sysOrigin == "" {
return nil, NewAppError(http.StatusBadRequest, "bad_request", "sysOrigin is required")
}
now := time.Now()
if err := s.expireDueStates(ctx, sysOrigin, now); err != nil {
return nil, err
}
page, size := normalizePage(cursor, limit)
query := s.db.WithContext(ctx).Model(&model.UserVipState{}).Where("sys_origin = ?", sysOrigin)
if userID > 0 {
query = query.Where("user_id = ?", userID)
}
if normalizedStatus := strings.ToUpper(strings.TrimSpace(status)); normalizedStatus != "" {
query = query.Where("status = ?", normalizedStatus)
}
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, err
}
records := make([]UserVipStatePayload, 0)
if total > 0 {
var rows []model.UserVipState
if err := query.
Order("update_time desc").
Order("id desc").
Offset((page - 1) * size).
Limit(size).
Find(&rows).Error; err != nil {
return nil, err
}
records = make([]UserVipStatePayload, 0, len(rows))
for idx := range rows {
records = append(records, statePayloadFromModel(&rows[idx], now))
}
}
return &UserStatePageResponse{Records: records, Total: total}, nil
}
// PageUserOrders returns the current user's VIP order records.
func (s *Service) PageUserOrders(ctx context.Context, user AuthUser, cursor int, limit int) (*OrderPageResponse, error) {
sysOrigin, err := normalizeUser(user)
if err != nil {
return nil, err
}
return s.PageOrders(ctx, sysOrigin, user.UserID, "", "", cursor, limit)
}
func (s *Service) expireDueStates(ctx context.Context, sysOrigin string, now time.Time) error {
updates := map[string]any{
"level": 0,
"level_code": "",
"display_name": "",
"status": statusExpired,
"badge_resource_id": 0,
"badge_name": "",
"badge_url": "",
"avatar_frame_resource_id": 0,
"avatar_frame_name": "",
"avatar_frame_url": "",
"entry_effect_resource_id": 0,
"entry_effect_name": "",
"entry_effect_url": "",
"chat_bubble_resource_id": 0,
"chat_bubble_name": "",
"chat_bubble_url": "",
"float_picture_resource_id": 0,
"float_picture_name": "",
"float_picture_url": "",
"update_time": now,
}
return s.db.WithContext(ctx).
Model(&model.UserVipState{}).
Where("sys_origin = ? AND status = ? AND expire_at <= ?", sysOrigin, statusActive, now).
Updates(updates).Error
}
// ParseUserID parses optional userId filters from query strings.
func ParseUserID(raw string) int64 {
value := strings.TrimSpace(raw)
if value == "" {
return 0
}
parsed, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return 0
}
return parsed
}