Initial commit: 商品售卖网站
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"sale/internal/models"
|
||||
"sale/internal/schemas"
|
||||
"sale/internal/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type LotteryHandler struct{}
|
||||
|
||||
func NewLotteryHandler() *LotteryHandler {
|
||||
return &LotteryHandler{}
|
||||
}
|
||||
|
||||
func (h *LotteryHandler) List(c *gin.Context) {
|
||||
var lotteries []models.Lottery
|
||||
utils.DB.Where("is_active = ?", true).Preload("Prizes").Order("created_at DESC").Find(&lotteries)
|
||||
c.JSON(http.StatusOK, gin.H{"data": lotteries})
|
||||
}
|
||||
|
||||
func (h *LotteryHandler) GetByID(c *gin.Context) {
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
var lottery models.Lottery
|
||||
if err := utils.DB.Preload("Prizes").First(&lottery, id).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Lottery not found"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"data": lottery})
|
||||
}
|
||||
|
||||
func (h *LotteryHandler) Register(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
|
||||
var lottery models.Lottery
|
||||
if err := utils.DB.First(&lottery, id).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Lottery not found"})
|
||||
return
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
if now.Before(lottery.StartTime) || now.After(lottery.EndTime) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Lottery is not in registration period"})
|
||||
return
|
||||
}
|
||||
|
||||
var existing models.LotteryParticipant
|
||||
if err := utils.DB.Where("lottery_id = ? AND user_id = ?", id, userID).First(&existing).Error; err == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Already registered"})
|
||||
return
|
||||
}
|
||||
|
||||
var totalSpent float64
|
||||
utils.DB.Model(&models.Order{}).
|
||||
Where("user_id = ? AND status = ?", userID, models.OrderStatusCompleted).
|
||||
Select("COALESCE(SUM(total_amount), 0)").
|
||||
Scan(&totalSpent)
|
||||
|
||||
participant := models.LotteryParticipant{
|
||||
LotteryID: lottery.ID,
|
||||
UserID: userID,
|
||||
PurchaseWeight: int(totalSpent),
|
||||
}
|
||||
|
||||
utils.DB.Create(&participant)
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Registered successfully"})
|
||||
}
|
||||
|
||||
func (h *LotteryHandler) Create(c *gin.Context) {
|
||||
var req schemas.CreateLotteryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
startTime, _ := time.Parse(time.RFC3339, req.StartTime)
|
||||
endTime, _ := time.Parse(time.RFC3339, req.EndTime)
|
||||
|
||||
lottery := models.Lottery{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
Cycle: req.Cycle,
|
||||
DailyQuota: req.DailyQuota,
|
||||
TotalQuota: req.TotalQuota,
|
||||
RegistrationValidity: req.RegistrationValidity,
|
||||
IsActive: true,
|
||||
}
|
||||
|
||||
utils.DB.Create(&lottery)
|
||||
c.JSON(http.StatusCreated, gin.H{"data": lottery})
|
||||
}
|
||||
|
||||
func (h *LotteryHandler) Update(c *gin.Context) {
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
var lottery models.Lottery
|
||||
if err := utils.DB.First(&lottery, id).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Lottery not found"})
|
||||
return
|
||||
}
|
||||
|
||||
var req schemas.UpdateLotteryRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
updates := make(map[string]interface{})
|
||||
if req.Name != nil {
|
||||
updates["name"] = *req.Name
|
||||
}
|
||||
if req.Description != nil {
|
||||
updates["description"] = *req.Description
|
||||
}
|
||||
if req.StartTime != nil {
|
||||
t, _ := time.Parse(time.RFC3339, *req.StartTime)
|
||||
updates["start_time"] = t
|
||||
}
|
||||
if req.EndTime != nil {
|
||||
t, _ := time.Parse(time.RFC3339, *req.EndTime)
|
||||
updates["end_time"] = t
|
||||
}
|
||||
if req.Cycle != nil {
|
||||
updates["cycle"] = *req.Cycle
|
||||
}
|
||||
if req.DailyQuota != nil {
|
||||
updates["daily_quota"] = *req.DailyQuota
|
||||
}
|
||||
if req.TotalQuota != nil {
|
||||
updates["total_quota"] = *req.TotalQuota
|
||||
}
|
||||
if req.RegistrationValidity != nil {
|
||||
updates["registration_validity"] = *req.RegistrationValidity
|
||||
}
|
||||
if req.IsActive != nil {
|
||||
updates["is_active"] = *req.IsActive
|
||||
}
|
||||
|
||||
utils.DB.Model(&lottery).Updates(updates)
|
||||
c.JSON(http.StatusOK, gin.H{"data": lottery})
|
||||
}
|
||||
|
||||
func (h *LotteryHandler) Delete(c *gin.Context) {
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
utils.DB.Delete(&models.Lottery{}, id)
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Lottery deleted successfully"})
|
||||
}
|
||||
|
||||
func (h *LotteryHandler) AddPrize(c *gin.Context) {
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
var req schemas.AddLotteryPrizeRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
prize := models.LotteryPrize{
|
||||
LotteryID: uint(id),
|
||||
Name: req.Name,
|
||||
Type: req.Type,
|
||||
Quantity: req.Quantity,
|
||||
Weight: req.Weight,
|
||||
CreditReward: req.CreditReward,
|
||||
DrawMode: req.DrawMode,
|
||||
}
|
||||
|
||||
utils.DB.Create(&prize)
|
||||
c.JSON(http.StatusCreated, gin.H{"data": prize})
|
||||
}
|
||||
|
||||
func (h *LotteryHandler) Draw(c *gin.Context) {
|
||||
id, _ := strconv.Atoi(c.Param("id"))
|
||||
var lottery models.Lottery
|
||||
if err := utils.DB.Preload("Prizes").First(&lottery, id).Error; err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Lottery not found"})
|
||||
return
|
||||
}
|
||||
|
||||
var participants []models.LotteryParticipant
|
||||
utils.DB.Where("lottery_id = ?", id).Find(&participants)
|
||||
|
||||
if len(participants) == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "No participants"})
|
||||
return
|
||||
}
|
||||
|
||||
var winners []models.LotteryWinner
|
||||
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
for _, prize := range lottery.Prizes {
|
||||
remaining := prize.Quantity
|
||||
|
||||
var weightParticipants []models.LotteryParticipant
|
||||
var randomParticipants []models.LotteryParticipant
|
||||
|
||||
if prize.DrawMode == models.DrawModeWeight {
|
||||
weightParticipants = participants
|
||||
} else {
|
||||
randomParticipants = participants
|
||||
}
|
||||
|
||||
selectedParticipants := weightParticipants
|
||||
if len(selectedParticipants) == 0 {
|
||||
selectedParticipants = randomParticipants
|
||||
}
|
||||
|
||||
totalWeight := 0
|
||||
for _, p := range selectedParticipants {
|
||||
w := p.PurchaseWeight
|
||||
if w < 1 {
|
||||
w = 1
|
||||
}
|
||||
totalWeight += w
|
||||
}
|
||||
|
||||
selected := make(map[uint]bool)
|
||||
for remaining > 0 && len(selected) < len(selectedParticipants) {
|
||||
r := rng.Intn(totalWeight)
|
||||
cumWeight := 0
|
||||
for _, p := range selectedParticipants {
|
||||
if selected[p.UserID] {
|
||||
continue
|
||||
}
|
||||
w := p.PurchaseWeight
|
||||
if w < 1 {
|
||||
w = 1
|
||||
}
|
||||
cumWeight += w
|
||||
if cumWeight > r {
|
||||
winner := models.LotteryWinner{
|
||||
LotteryID: lottery.ID,
|
||||
PrizeID: prize.ID,
|
||||
UserID: p.UserID,
|
||||
DrawnAt: time.Now(),
|
||||
}
|
||||
winners = append(winners, winner)
|
||||
selected[p.UserID] = true
|
||||
remaining--
|
||||
|
||||
if prize.Type == models.PrizeTypeCredit && prize.CreditReward != nil {
|
||||
utils.DB.Model(&models.User{}).Where("id = ?", p.UserID).
|
||||
UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits + ?", *prize.CreditReward))
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(winners) > 0 {
|
||||
utils.DB.Create(&winners)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": winners, "message": "Draw completed successfully"})
|
||||
}
|
||||
Reference in New Issue
Block a user