feat(points): 增加积分兑换联系信息

This commit is contained in:
yml2213
2026-11-04 19:51:17 +08:00
parent 95aeee7eb3
commit f439e23eb8
9 changed files with 425 additions and 25 deletions
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"regexp"
"strings"
"time"
@@ -18,6 +19,8 @@ type Repository struct {
db *gorm.DB
}
var mobilePhonePattern = regexp.MustCompile(`^1[3-9]\d{9}$`)
func NewRepository(db *gorm.DB) *Repository {
return &Repository{db: db}
}
@@ -115,8 +118,18 @@ func (r *Repository) findProduct(ctx context.Context, id uint64) (*ProductDTO, e
return &dto, nil
}
func (r *Repository) Redeem(ctx context.Context, userID, productID uint64, quantity int) (*RedemptionDTO, error) {
if userID == 0 || productID == 0 || quantity <= 0 || quantity > 10 {
func (r *Repository) Redeem(ctx context.Context, userID, productID uint64, req RedeemRequest) (*RedemptionDTO, error) {
contactName := strings.TrimSpace(req.ContactName)
contactPhone := strings.TrimSpace(req.ContactPhone)
customerRemark := strings.TrimSpace(req.CustomerRemark)
if userID == 0 ||
productID == 0 ||
req.Quantity <= 0 ||
req.Quantity > 10 ||
contactName == "" ||
len([]rune(contactName)) > 32 ||
!mobilePhonePattern.MatchString(contactPhone) ||
len([]rune(customerRemark)) > 500 {
return nil, ErrInvalidInput
}
var result model.PointsMallRedemption
@@ -125,7 +138,7 @@ func (r *Repository) Redeem(ctx context.Context, userID, productID uint64, quant
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&product, productID).Error; err != nil {
return err
}
if product.Status != "online" || product.Stock < int64(quantity) {
if product.Status != "online" || product.Stock < int64(req.Quantity) {
return ErrProductUnavailable
}
var redeemed int64
@@ -135,14 +148,14 @@ func (r *Repository) Redeem(ctx context.Context, userID, productID uint64, quant
Scan(&redeemed).Error; err != nil {
return err
}
if redeemed+int64(quantity) > int64(product.PerUserLimit) {
if redeemed+int64(req.Quantity) > int64(product.PerUserLimit) {
return ErrRedeemLimitExceeded
}
var user model.User
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&user, userID).Error; err != nil {
return err
}
totalPoints := product.PointsPrice * int64(quantity)
totalPoints := product.PointsPrice * int64(req.Quantity)
if totalPoints <= 0 || user.PointsAvailable < totalPoints {
return ErrInsufficientPoints
}
@@ -154,8 +167,11 @@ func (r *Repository) Redeem(ctx context.Context, userID, productID uint64, quant
ProductTitle: product.Title,
ProductCoverURL: product.CoverURL,
RedemptionInstructions: product.RedemptionInstructions,
ContactName: contactName,
ContactPhone: contactPhone,
CustomerRemark: customerRemark,
PointsPrice: product.PointsPrice,
Quantity: quantity,
Quantity: req.Quantity,
TotalPoints: totalPoints,
Status: "pending",
CreatedAt: now,
@@ -170,8 +186,8 @@ func (r *Repository) Redeem(ctx context.Context, userID, productID uint64, quant
return err
}
if err := tx.Model(&product).Updates(map[string]any{
"stock": gorm.Expr("stock - ?", quantity),
"redeemed_count": gorm.Expr("redeemed_count + ?", quantity),
"stock": gorm.Expr("stock - ?", req.Quantity),
"redeemed_count": gorm.Expr("redeemed_count + ?", req.Quantity),
}).Error; err != nil {
return err
}