Files
ai_dianshang/server/internal/service/cart.go
2025-11-28 15:18:10 +08:00

656 lines
16 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"dianshang/internal/model"
"dianshang/internal/repository"
"errors"
"fmt"
"time"
"gorm.io/gorm"
)
// CartService 购物车服务
type CartService struct {
orderRepo *repository.OrderRepository
productRepo *repository.ProductRepository
userRepo *repository.UserRepository
}
// NewCartService 创建购物车服务
func NewCartService(orderRepo *repository.OrderRepository, productRepo *repository.ProductRepository, userRepo *repository.UserRepository) *CartService {
return &CartService{
orderRepo: orderRepo,
productRepo: productRepo,
userRepo: userRepo,
}
}
// GetCart 获取购物车
// 优化: 移除用户存在性检查,因为中间件已经验证过token和用户
func (s *CartService) GetCart(userID uint) ([]model.Cart, error) {
return s.orderRepo.GetCart(userID)
}
// AddToCart 添加到购物车
func (s *CartService) AddToCart(userID, productID uint, skuID uint, quantity int) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
// 检查产品是否存在
product, err := s.productRepo.GetByID(productID)
if err != nil {
return errors.New("产品不存在")
}
// 检查产品状态
if product.Status != 1 {
return errors.New("产品已下架")
}
// 检查库存
if product.Stock < quantity {
return errors.New("库存不足")
}
// 检查购物车中是否已存在该商品包括SKU
existingCart, err := s.orderRepo.GetCartItemBySKU(userID, productID, skuID)
if err == nil && existingCart != nil {
// 已存在,更新数量
newQuantity := existingCart.Quantity + quantity
if product.Stock < newQuantity {
return errors.New("库存不足")
}
return s.orderRepo.UpdateCartItem(existingCart.ID, newQuantity)
}
// 如果不是记录不存在的错误,返回错误
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
// 不存在,添加新项
var skuPtr *uint
if skuID != 0 {
skuPtr = &skuID
}
cart := &model.Cart{
UserID: userID,
ProductID: productID,
SKUID: skuPtr,
Quantity: quantity,
Selected: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
return s.orderRepo.AddToCart(cart)
}
// UpdateCartItem 更新购物车项
func (s *CartService) UpdateCartItem(userID, productID uint, quantity int) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
// 获取该用户该产品的所有购物车项
cartItems, err := s.orderRepo.GetCart(userID)
if err != nil {
return errors.New("获取购物车失败")
}
// 查找匹配的购物车项
var targetCartItem *model.Cart
for _, item := range cartItems {
if item.ProductID == productID {
targetCartItem = &item
break
}
}
if targetCartItem == nil {
return errors.New("购物车项不存在")
}
if quantity == 0 {
// 数量为0删除该项
return s.orderRepo.RemoveFromCart(userID, productID)
}
// 检查产品库存
product, err := s.productRepo.GetByID(productID)
if err != nil {
return errors.New("产品不存在")
}
if product.Stock < quantity {
return errors.New("库存不足")
}
return s.orderRepo.UpdateCartItem(targetCartItem.ID, quantity)
}
// UpdateCartItemBySKU 基于SKU更新购物车项
func (s *CartService) UpdateCartItemBySKU(userID, productID, skuID uint, quantity int) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
// 使用SKU查找购物车项
cartItem, err := s.orderRepo.GetCartItemBySKU(userID, productID, skuID)
if err != nil {
return errors.New("购物车项不存在")
}
if quantity == 0 {
// 数量为0删除该项
return s.orderRepo.RemoveFromCartBySKU(userID, productID, skuID)
}
// 检查产品库存
product, err := s.productRepo.GetByID(productID)
if err != nil {
return errors.New("产品不存在")
}
if product.Stock < quantity {
return errors.New("库存不足")
}
return s.orderRepo.UpdateCartItem(cartItem.ID, quantity)
}
// RemoveFromCart 从购物车移除
func (s *CartService) RemoveFromCart(userID, productID uint) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
// 获取该用户该产品的所有购物车项
cartItems, err := s.orderRepo.GetCart(userID)
if err != nil {
return errors.New("获取购物车失败")
}
// 查找匹配的购物车项
var found bool
for _, item := range cartItems {
if item.ProductID == productID {
found = true
break
}
}
if !found {
return errors.New("购物车项不存在")
}
return s.orderRepo.RemoveFromCart(userID, productID)
}
// RemoveFromCartBySKU 基于SKU从购物车移除
func (s *CartService) RemoveFromCartBySKU(userID, productID, skuID uint) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
// 使用SKU查找购物车项
_, err = s.orderRepo.GetCartItemBySKU(userID, productID, skuID)
if err != nil {
return errors.New("购物车项不存在")
}
return s.orderRepo.RemoveFromCartBySKU(userID, productID, skuID)
}
// ClearCart 清空购物车
func (s *CartService) ClearCart(userID uint) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
return s.orderRepo.ClearCart(userID)
}
// GetCartCount 获取购物车商品数量
func (s *CartService) GetCartCount(userID uint) (int, error) {
cart, err := s.GetCart(userID)
if err != nil {
return 0, err
}
var count int
for _, item := range cart {
count += int(item.Quantity)
}
return count, nil
}
// GetCartTotal 获取购物车总金额
func (s *CartService) GetCartTotal(userID uint) (float64, error) {
cart, err := s.GetCart(userID)
if err != nil {
return 0, err
}
var total float64
for _, item := range cart {
if item.Product.ID != 0 {
// 将价格从分转换为元
total += (float64(item.Product.Price) / 100) * float64(item.Quantity)
}
}
return total, nil
}
// SelectCartItem 选择/取消选择购物车项
func (s *CartService) SelectCartItem(userID, cartID uint, selected bool) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
return s.orderRepo.SelectCartItem(userID, cartID, selected)
}
// SelectAllCartItems 全选/取消全选购物车
func (s *CartService) SelectAllCartItems(userID uint, selected bool) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
return s.orderRepo.SelectAllCartItems(userID, selected)
}
// BatchAddToCart 批量添加到购物车
func (s *CartService) BatchAddToCart(userID uint, items []struct {
ProductID uint `json:"product_id"`
SKUID uint `json:"sku_id"`
Quantity int `json:"quantity"`
}) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
// 验证所有商品
for _, item := range items {
product, err := s.productRepo.GetByID(item.ProductID)
if err != nil {
return errors.New("商品不存在: " + err.Error())
}
if product.Status != 1 {
return errors.New("商品已下架")
}
if product.Stock < item.Quantity {
return errors.New("商品库存不足")
}
}
// 批量添加
for _, item := range items {
err := s.AddToCart(userID, item.ProductID, item.SKUID, item.Quantity)
if err != nil {
return err
}
}
return nil
}
// BatchRemoveFromCart 批量从购物车移除
func (s *CartService) BatchRemoveFromCart(userID uint, cartIDs []uint) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
return s.orderRepo.BatchRemoveFromCart(userID, cartIDs)
}
// BatchUpdateCartItems 批量更新购物车项
func (s *CartService) BatchUpdateCartItems(userID uint, updates []struct {
CartID uint `json:"cart_id"`
Quantity int `json:"quantity"`
}) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
// 获取购物车项并验证
for _, update := range updates {
cartItem, err := s.orderRepo.GetCartItem(userID, update.CartID)
if err != nil {
return errors.New("购物车项不存在")
}
// 检查库存
product, err := s.productRepo.GetByID(cartItem.ProductID)
if err != nil {
return errors.New("商品不存在")
}
if product.Stock < update.Quantity {
return errors.New("商品库存不足")
}
// 更新数量
if update.Quantity == 0 {
err = s.orderRepo.RemoveCartItem(update.CartID)
} else {
err = s.orderRepo.UpdateCartItem(update.CartID, update.Quantity)
}
if err != nil {
return err
}
}
return nil
}
// GetCartWithDetails 获取购物车详细信息(包含商品详情)
func (s *CartService) GetCartWithDetails(userID uint) (map[string]interface{}, error) {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return nil, errors.New("用户不存在")
}
cart, err := s.orderRepo.GetCart(userID)
if err != nil {
return nil, err
}
var validItems []model.Cart
var invalidItems []model.Cart
var totalAmount float64
var totalQuantity int
var selectedAmount float64
var selectedQuantity int
for _, item := range cart {
// 检查商品是否有效
product, err := s.productRepo.GetByID(item.ProductID)
if err != nil || product.Status != 1 {
invalidItems = append(invalidItems, item)
continue
}
// 检查库存
if product.Stock < item.Quantity {
item.Product = *product
invalidItems = append(invalidItems, item)
continue
}
// 计算价格
item.Product = *product
itemPrice := float64(product.Price) / 100 * float64(item.Quantity)
totalAmount += itemPrice
totalQuantity += item.Quantity
if item.Selected {
selectedAmount += itemPrice
selectedQuantity += item.Quantity
}
validItems = append(validItems, item)
}
return map[string]interface{}{
"valid_items": validItems,
"invalid_items": invalidItems,
"total_amount": totalAmount,
"total_quantity": totalQuantity,
"selected_amount": selectedAmount,
"selected_quantity": selectedQuantity,
"valid_count": len(validItems),
"invalid_count": len(invalidItems),
}, nil
}
// ValidateCartItems 验证购物车商品有效性
func (s *CartService) ValidateCartItems(userID uint) (map[string]interface{}, error) {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return nil, errors.New("用户不存在")
}
cart, err := s.orderRepo.GetCart(userID)
if err != nil {
return nil, err
}
var validItems []uint
var invalidItems []struct {
CartID uint `json:"cart_id"`
Reason string `json:"reason"`
}
for _, item := range cart {
// 检查商品是否存在
product, err := s.productRepo.GetByID(item.ProductID)
if err != nil {
invalidItems = append(invalidItems, struct {
CartID uint `json:"cart_id"`
Reason string `json:"reason"`
}{
CartID: item.ID,
Reason: "商品不存在",
})
continue
}
// 检查商品状态
if product.Status != 1 {
invalidItems = append(invalidItems, struct {
CartID uint `json:"cart_id"`
Reason string `json:"reason"`
}{
CartID: item.ID,
Reason: "商品已下架",
})
continue
}
// 检查库存
if product.Stock < item.Quantity {
invalidItems = append(invalidItems, struct {
CartID uint `json:"cart_id"`
Reason string `json:"reason"`
}{
CartID: item.ID,
Reason: "库存不足",
})
continue
}
validItems = append(validItems, item.ID)
}
return map[string]interface{}{
"valid_items": validItems,
"invalid_items": invalidItems,
"valid_count": len(validItems),
"invalid_count": len(invalidItems),
}, nil
}
// CleanInvalidCartItems 清理无效的购物车项
func (s *CartService) CleanInvalidCartItems(userID uint) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
validation, err := s.ValidateCartItems(userID)
if err != nil {
return err
}
invalidItems := validation["invalid_items"].([]struct {
CartID uint `json:"cart_id"`
Reason string `json:"reason"`
})
if len(invalidItems) == 0 {
return nil
}
var cartIDs []uint
for _, item := range invalidItems {
cartIDs = append(cartIDs, item.CartID)
}
return s.orderRepo.BatchRemoveFromCart(userID, cartIDs)
}
// GetCartSummary 获取购物车摘要信息
func (s *CartService) GetCartSummary(userID uint) (map[string]interface{}, error) {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return nil, errors.New("用户不存在")
}
details, err := s.GetCartWithDetails(userID)
if err != nil {
return nil, err
}
return map[string]interface{}{
"total_items": details["valid_count"].(int) + details["invalid_count"].(int),
"valid_items": details["valid_count"],
"invalid_items": details["invalid_count"],
"total_amount": details["total_amount"],
"selected_amount": details["selected_amount"],
"total_quantity": details["total_quantity"],
"selected_quantity": details["selected_quantity"],
}, nil
}
// MergeCart 合并购物车(用于登录后合并游客购物车)
func (s *CartService) MergeCart(userID uint, guestCartItems []struct {
ProductID uint `json:"product_id"`
SKUID uint `json:"sku_id"`
Quantity int `json:"quantity"`
}) error {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return errors.New("用户不存在")
}
// 获取用户现有购物车
existingCart, err := s.orderRepo.GetCart(userID)
if err != nil {
return err
}
// 创建现有购物车的映射
existingMap := make(map[string]*model.Cart)
for i, item := range existingCart {
key := fmt.Sprintf("%d_%d", item.ProductID, item.SKUID)
if item.SKUID == nil {
key = fmt.Sprintf("%d_0", item.ProductID)
}
existingMap[key] = &existingCart[i]
}
// 合并游客购物车项
for _, guestItem := range guestCartItems {
key := fmt.Sprintf("%d_%d", guestItem.ProductID, guestItem.SKUID)
if guestItem.SKUID == 0 {
key = fmt.Sprintf("%d_0", guestItem.ProductID)
}
if existingItem, exists := existingMap[key]; exists {
// 已存在,更新数量
newQuantity := existingItem.Quantity + guestItem.Quantity
err = s.orderRepo.UpdateCartItem(existingItem.ID, newQuantity)
if err != nil {
return err
}
} else {
// 不存在,添加新项
err = s.AddToCart(userID, guestItem.ProductID, guestItem.SKUID, guestItem.Quantity)
if err != nil {
return err
}
}
}
return nil
}
// GetSelectedCartItems 获取选中的购物车项
func (s *CartService) GetSelectedCartItems(userID uint) ([]model.Cart, error) {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return nil, errors.New("用户不存在")
}
return s.orderRepo.GetSelectedCartItems(userID)
}
// CalculateCartDiscount 计算购物车优惠(预留接口)
func (s *CartService) CalculateCartDiscount(userID uint, couponID uint) (map[string]interface{}, error) {
// 检查用户是否存在
_, err := s.userRepo.GetByID(userID)
if err != nil {
return nil, errors.New("用户不存在")
}
selectedItems, err := s.GetSelectedCartItems(userID)
if err != nil {
return nil, err
}
var originalAmount float64
for _, item := range selectedItems {
product, err := s.productRepo.GetByID(item.ProductID)
if err != nil {
continue
}
originalAmount += float64(product.Price) / 100 * float64(item.Quantity)
}
// 这里可以添加优惠券计算逻辑
discountAmount := 0.0
finalAmount := originalAmount - discountAmount
return map[string]interface{}{
"original_amount": originalAmount,
"discount_amount": discountAmount,
"final_amount": finalAmount,
"coupon_id": couponID,
}, nil
}