package logic import ( "context" "errors" "healthapi/internal/model" "healthapi/internal/svc" "healthapi/internal/types" "healthapi/pkg/errorx" "github.com/zeromicro/go-zero/core/logx" "gorm.io/gorm" ) type AddCartLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewAddCartLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddCartLogic { return &AddCartLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *AddCartLogic) AddCart(req *types.AddCartReq) (resp *types.CartItem, err error) { userID, err := GetUserIDFromCtx(l.ctx) if err != nil { return nil, errorx.ErrUnauthorized } // 验证商品存在且上架 var product model.Product if err := l.svcCtx.DB.First(&product, req.ProductID).Error; err != nil { return nil, errorx.NewCodeError(404, "商品不存在") } if !product.IsActive { return nil, errorx.NewCodeError(400, "商品已下架") } price := product.Price stock := product.Stock skuName := "" image := product.MainImage // 如果有 SKU,验证 SKU if req.SkuID > 0 { var sku model.ProductSku if err := l.svcCtx.DB.First(&sku, req.SkuID).Error; err != nil { return nil, errorx.NewCodeError(404, "商品规格不存在") } if sku.ProductID != req.ProductID { return nil, errorx.NewCodeError(400, "商品规格不匹配") } if !sku.IsActive { return nil, errorx.NewCodeError(400, "该规格已下架") } price = sku.Price stock = sku.Stock skuName = sku.Name if sku.Image != "" { image = sku.Image } } // 检查库存 if stock < req.Quantity { return nil, errorx.NewCodeError(400, "库存不足") } // 检查是否已在购物车中 var existingItem model.CartItem query := l.svcCtx.DB.Where("user_id = ? AND product_id = ?", userID, req.ProductID) if req.SkuID > 0 { query = query.Where("sku_id = ?", req.SkuID) } else { query = query.Where("sku_id = 0 OR sku_id IS NULL") } if err := query.First(&existingItem).Error; err == nil { // 已存在,更新数量 newQty := existingItem.Quantity + req.Quantity if newQty > stock { return nil, errorx.NewCodeError(400, "库存不足") } existingItem.Quantity = newQty l.svcCtx.DB.Save(&existingItem) resp = &types.CartItem{ ID: uint(existingItem.ID), ProductID: existingItem.ProductID, SkuID: existingItem.SkuID, ProductName: product.Name, SkuName: skuName, Image: image, Price: price, Quantity: existingItem.Quantity, Selected: existingItem.Selected, Stock: stock, } return resp, nil } else if !errors.Is(err, gorm.ErrRecordNotFound) { return nil, err } // 新增购物车项 cartItem := model.CartItem{ UserID: userID, ProductID: req.ProductID, SkuID: req.SkuID, Quantity: req.Quantity, Selected: true, } if err := l.svcCtx.DB.Create(&cartItem).Error; err != nil { return nil, err } resp = &types.CartItem{ ID: uint(cartItem.ID), ProductID: cartItem.ProductID, SkuID: cartItem.SkuID, ProductName: product.Name, SkuName: skuName, Image: image, Price: price, Quantity: cartItem.Quantity, Selected: cartItem.Selected, Stock: stock, } return resp, nil }