94 lines
3.2 KiB
Go
94 lines
3.2 KiB
Go
package welfare_activity
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
func (s *service) Join(ctx context.Context, activityID int64, userID int64) error {
|
|
if activityID <= 0 || userID <= 0 {
|
|
return errors.New("活动或用户无效")
|
|
}
|
|
var activity Activity
|
|
if err := s.repo.GetDbR().WithContext(ctx).Where("id = ? AND deleted_at IS NULL", activityID).First(&activity).Error; err != nil {
|
|
return err
|
|
}
|
|
now := time.Now()
|
|
if !isJoinWindowOpen(activity, now) {
|
|
if now.Before(activity.StartTime) {
|
|
return errors.New("活动未开始")
|
|
}
|
|
return errors.New("当前不在活动参与时间内")
|
|
}
|
|
start, end, period := periodRange(activity.Type, now)
|
|
paid, err := s.sumPaidAmount(ctx, userID, start, end)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if paid < activity.ThresholdAmount {
|
|
return fmt.Errorf("未达到参与门槛,还差%d分", activity.ThresholdAmount-paid)
|
|
}
|
|
participant := &Participant{ActivityID: activityID, UserID: userID, PeriodKey: period, PaidAmountSnapshot: paid}
|
|
return s.repo.GetDbW().WithContext(ctx).Create(participant).Error
|
|
}
|
|
|
|
func (s *service) ListParticipants(ctx context.Context, activityID int64, page int, pageSize int) (*ParticipantResponse, error) {
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
if pageSize <= 0 {
|
|
pageSize = 20
|
|
}
|
|
if pageSize > 100 {
|
|
pageSize = 100
|
|
}
|
|
var total int64
|
|
db := s.repo.GetDbR().WithContext(ctx).Table("welfare_activity_participants").Where("activity_id = ?", activityID)
|
|
if err := db.Count(&total).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
var list []ParticipantAvatar
|
|
err := s.repo.GetDbR().WithContext(ctx).Table("welfare_activity_participants p").
|
|
Select("p.user_id, COALESCE(u.nickname, '') AS nickname, COALESCE(u.avatar, '') AS avatar").
|
|
Joins("LEFT JOIN users u ON u.id = p.user_id").
|
|
Where("p.activity_id = ?", activityID).
|
|
Order("p.id DESC").
|
|
Offset((page - 1) * pageSize).
|
|
Limit(pageSize).
|
|
Scan(&list).Error
|
|
return &ParticipantResponse{Page: page, PageSize: pageSize, Total: total, List: list}, err
|
|
}
|
|
|
|
func (s *service) sumPaidAmount(ctx context.Context, userID int64, start time.Time, end time.Time) (int64, error) {
|
|
var total int64
|
|
err := s.repo.GetDbR().WithContext(ctx).Table("orders").
|
|
Select("COALESCE(SUM(actual_amount), 0)").
|
|
Where("user_id = ? AND status = 2 AND actual_amount > 0", userID).
|
|
Where("COALESCE(NULLIF(paid_at, '1970-01-01 00:00:00'), created_at) >= ?", start).
|
|
Where("COALESCE(NULLIF(paid_at, '1970-01-01 00:00:00'), created_at) < ?", end).
|
|
Scan(&total).Error
|
|
return total, err
|
|
}
|
|
|
|
func periodRange(activityType string, now time.Time) (time.Time, time.Time, string) {
|
|
loc := now.Location()
|
|
switch activityType {
|
|
case TypeWeekly:
|
|
dayOffset := (int(now.Weekday()) + 6) % 7
|
|
start := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc).AddDate(0, 0, -dayOffset)
|
|
end := start.AddDate(0, 0, 7)
|
|
y, w := start.ISOWeek()
|
|
return start, end, fmt.Sprintf("%04d-W%02d", y, w)
|
|
case TypeMonthly:
|
|
start := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, loc)
|
|
end := start.AddDate(0, 1, 0)
|
|
return start, end, start.Format("2006-01")
|
|
default:
|
|
start := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
|
|
end := start.AddDate(0, 0, 1)
|
|
return start, end, start.Format("2006-01-02")
|
|
}
|
|
}
|