Files
2025-11-17 13:32:54 +08:00

227 lines
6.3 KiB
Go

package service
import (
"dianshang/internal/model"
"dianshang/internal/repository"
"errors"
"fmt"
"time"
)
// CouponService 优惠券服务
type CouponService struct {
couponRepo *repository.CouponRepository
}
// NewCouponService 创建优惠券服务
func NewCouponService(couponRepo *repository.CouponRepository) *CouponService {
return &CouponService{
couponRepo: couponRepo,
}
}
// GetAvailableCoupons 获取可用优惠券列表
func (s *CouponService) GetAvailableCoupons() ([]model.Coupon, error) {
return s.couponRepo.GetAvailableCoupons()
}
// GetAvailableCouponsWithUserStatus 获取可用优惠券列表(包含用户已领取状态)
func (s *CouponService) GetAvailableCouponsWithUserStatus(userID uint) ([]map[string]interface{}, error) {
// 获取所有可用优惠券
coupons, err := s.couponRepo.GetAvailableCoupons()
if err != nil {
return nil, err
}
var result []map[string]interface{}
// 如果用户已登录,检查每个优惠券的领取状态
for _, coupon := range coupons {
couponData := map[string]interface{}{
"id": coupon.ID,
"name": coupon.Name,
"type": coupon.Type,
"value": coupon.Value,
"min_amount": coupon.MinAmount,
"description": coupon.Description,
"start_time": coupon.StartTime,
"end_time": coupon.EndTime,
"total_count": coupon.TotalCount,
"used_count": coupon.UsedCount,
"is_received": false, // 默认未领取
}
// 如果用户已登录,检查是否已领取
if userID > 0 {
exists, err := s.couponRepo.CheckUserCouponExists(userID, coupon.ID)
if err == nil {
couponData["is_received"] = exists
}
}
result = append(result, couponData)
}
return result, nil
}
// GetUserCoupons 获取用户优惠券
func (s *CouponService) GetUserCoupons(userID uint, status int) ([]model.UserCoupon, error) {
return s.couponRepo.GetUserCoupons(userID, status)
}
// ReceiveCoupon 领取优惠券
func (s *CouponService) ReceiveCoupon(userID, couponID uint) error {
// 检查优惠券是否存在且有效
coupon, err := s.couponRepo.GetByID(couponID)
if err != nil {
return errors.New("优惠券不存在")
}
// 检查是否在有效期内
now := time.Now()
if now.Before(coupon.StartTime) || now.After(coupon.EndTime) {
return errors.New("优惠券不在有效期内")
}
// 检查是否还有库存
if coupon.TotalCount > 0 && coupon.UsedCount >= coupon.TotalCount {
return errors.New("优惠券已被领完")
}
// 检查用户是否已经领取过
exists, err := s.couponRepo.CheckUserCouponExists(userID, couponID)
if err != nil {
return err
}
if exists {
return errors.New("您已经领取过该优惠券")
}
// 创建用户优惠券记录
userCoupon := &model.UserCoupon{
UserID: userID,
CouponID: couponID,
Status: 0, // 未使用
}
return s.couponRepo.CreateUserCoupon(userCoupon)
}
// UseCoupon 使用优惠券
func (s *CouponService) UseCoupon(userID, userCouponID, orderID uint) error {
// 获取用户优惠券
userCoupon, err := s.couponRepo.GetUserCouponByID(userCouponID)
if err != nil {
return errors.New("优惠券不存在")
}
// 检查是否属于该用户
if userCoupon.UserID != userID {
return errors.New("无权使用该优惠券")
}
// 检查是否已使用
if userCoupon.Status != 0 {
return errors.New("优惠券已使用或已过期")
}
// 检查优惠券是否在有效期内
now := time.Now()
if now.Before(userCoupon.Coupon.StartTime) || now.After(userCoupon.Coupon.EndTime) {
return errors.New("优惠券不在有效期内")
}
// 更新优惠券状态为已使用
return s.couponRepo.UseCoupon(userCouponID, orderID)
}
// ValidateCoupon 验证优惠券是否可用
func (s *CouponService) ValidateCoupon(userID, userCouponID uint, orderAmount float64) (*model.UserCoupon, float64, error) {
// 获取用户优惠券
userCoupon, err := s.couponRepo.GetUserCouponByID(userCouponID)
if err != nil {
return nil, 0, errors.New("优惠券不存在")
}
// 检查是否属于该用户
if userCoupon.UserID != userID {
return nil, 0, errors.New("无权使用该优惠券")
}
// 检查是否已使用
if userCoupon.Status != 0 {
return nil, 0, errors.New("优惠券已使用或已过期")
}
// 检查优惠券是否在有效期内
now := time.Now()
if now.Before(userCoupon.Coupon.StartTime) || now.After(userCoupon.Coupon.EndTime) {
return nil, 0, errors.New("优惠券不在有效期内")
}
// 检查最低消费金额
minAmount := float64(userCoupon.Coupon.MinAmount) / 100 // 分转元
if orderAmount < minAmount {
return nil, 0, errors.New(fmt.Sprintf("订单金额不满足优惠券使用条件,最低需要%.2f元", minAmount))
}
// 计算优惠金额
var discountAmount float64
switch userCoupon.Coupon.Type {
case 1: // 满减券
discountAmount = float64(userCoupon.Coupon.Value) / 100 // 分转元
case 2: // 折扣券
discountRate := float64(userCoupon.Coupon.Value) / 100 // 85 -> 0.85
discountAmount = orderAmount * (1 - discountRate)
case 3: // 免邮券
discountAmount = 0 // 免邮券的优惠金额在运费中体现
default:
return nil, 0, errors.New("不支持的优惠券类型")
}
// 确保优惠金额不超过订单金额
if discountAmount > orderAmount {
discountAmount = orderAmount
}
return userCoupon, discountAmount, nil
}
// GetAvailableCouponsForOrder 获取订单可用的优惠券
func (s *CouponService) GetAvailableCouponsForOrder(userID uint, orderAmount float64) ([]model.UserCoupon, error) {
// 获取用户未使用的优惠券
userCoupons, err := s.couponRepo.GetUserCoupons(userID, 1) // 1表示未使用(API状态值)
if err != nil {
return nil, err
}
var availableCoupons []model.UserCoupon
now := time.Now()
for _, userCoupon := range userCoupons {
// 严格检查优惠券状态:必须是未使用状态(0)且没有关联订单
if userCoupon.Status != 0 || userCoupon.OrderID != nil {
continue
}
// 检查是否在有效期内
if now.Before(userCoupon.Coupon.StartTime) || now.After(userCoupon.Coupon.EndTime) {
continue
}
// 检查优惠券模板是否可用
if userCoupon.Coupon.Status != 1 {
continue
}
// 检查最低消费金额
minAmount := float64(userCoupon.Coupon.MinAmount) / 100 // 分转元
if orderAmount >= minAmount {
availableCoupons = append(availableCoupons, userCoupon)
}
}
return availableCoupons, nil
}