package service import ( "dianshang/internal/model" "dianshang/internal/repository" "dianshang/pkg/utils" "errors" "fmt" "strconv" "time" ) // ProductService 产品服务 type ProductService struct { productRepo *repository.ProductRepository userRepo *repository.UserRepository } // NewProductService 创建产品服务 func NewProductService(productRepo *repository.ProductRepository, userRepo *repository.UserRepository) *ProductService { return &ProductService{ productRepo: productRepo, userRepo: userRepo, } } // GetProductList 获取产品列表(前端用户) func (s *ProductService) GetProductList(page, pageSize int, categoryID uint, keyword string, minPrice, maxPrice float64, sort, sortType string) ([]model.Product, *utils.Pagination, error) { if page <= 0 { page = 1 } if pageSize <= 0 || pageSize > 100 { pageSize = 20 } offset := (page - 1) * pageSize conditions := make(map[string]interface{}) if categoryID > 0 { conditions["category_id"] = categoryID } if keyword != "" { conditions["keyword"] = keyword } if minPrice > 0 { conditions["min_price"] = minPrice } if maxPrice > 0 { conditions["max_price"] = maxPrice } if sort != "" { conditions["sort"] = sort } if sortType != "" { conditions["sort_type"] = sortType } products, total, err := s.productRepo.GetList(offset, pageSize, conditions) if err != nil { return nil, nil, err } pagination := utils.NewPagination(page, pageSize) pagination.Total = total return products, pagination, nil } // GetProductListForAdmin 获取产品列表(管理系统) func (s *ProductService) GetProductListForAdmin(page, pageSize int, categoryID uint, keyword string, minPrice, maxPrice float64, sort, sortType, status, isHot, isNew, isRecommend string) ([]model.Product, *utils.Pagination, error) { if page <= 0 { page = 1 } if pageSize <= 0 || pageSize > 100 { pageSize = 20 } offset := (page - 1) * pageSize conditions := make(map[string]interface{}) if categoryID > 0 { conditions["category_id"] = categoryID } if keyword != "" { conditions["keyword"] = keyword } if minPrice > 0 { conditions["min_price"] = minPrice } if maxPrice > 0 { conditions["max_price"] = maxPrice } if sort != "" { conditions["sort"] = sort } if sortType != "" { conditions["sort_type"] = sortType } // 添加状态条件,支持获取所有状态的商品 if status != "" { conditions["status"] = status } // 添加热门、新品、推荐筛选条件 if isHot != "" { conditions["is_hot"] = isHot } if isNew != "" { conditions["is_new"] = isNew } if isRecommend != "" { conditions["is_recommend"] = isRecommend } products, total, err := s.productRepo.GetList(offset, pageSize, conditions) if err != nil { return nil, nil, err } pagination := utils.NewPagination(page, pageSize) pagination.Total = total return products, pagination, nil } // GetProductDetail 获取产品详情 func (s *ProductService) GetProductDetail(id uint) (*model.Product, error) { return s.productRepo.GetByID(id) } // CreateProduct 创建产品 func (s *ProductService) CreateProduct(product *model.Product) error { // 验证分类是否存在 if product.CategoryID > 0 { _, err := s.productRepo.GetCategoryByID(product.CategoryID) if err != nil { return errors.New("分类不存在") } } return s.productRepo.Create(product) } // UpdateProduct 更新产品 func (s *ProductService) UpdateProduct(id uint, updates map[string]interface{}) error { // 检查产品是否存在 _, err := s.productRepo.GetByID(id) if err != nil { return errors.New("产品不存在") } // 如果更新分类,验证分类是否存在 if categoryID, ok := updates["category_id"]; ok { var catID uint switch v := categoryID.(type) { case uint: catID = v case float64: catID = uint(v) case int: catID = uint(v) default: return errors.New("分类ID格式错误") } if catID > 0 { _, err := s.productRepo.GetCategoryByID(catID) if err != nil { return errors.New("分类不存在") } } } // 处理 detail_images 字段 - 确保正确转换为 JSONSlice 类型 if detailImages, ok := updates["detail_images"]; ok { switch v := detailImages.(type) { case []interface{}: // 将 []interface{} 转换为 []string var stringSlice []string for _, item := range v { if str, ok := item.(string); ok { stringSlice = append(stringSlice, str) } } updates["detail_images"] = model.JSONSlice(stringSlice) case []string: updates["detail_images"] = model.JSONSlice(v) } } // 处理 images 字段 - 确保正确转换为 JSONSlice 类型 if images, ok := updates["images"]; ok { switch v := images.(type) { case []interface{}: // 将 []interface{} 转换为 []string var stringSlice []string for _, item := range v { if str, ok := item.(string); ok { stringSlice = append(stringSlice, str) } } updates["images"] = model.JSONSlice(stringSlice) case []string: updates["images"] = model.JSONSlice(v) } } // 处理SKU数据 var skusData []interface{} if skus, ok := updates["skus"]; ok { skusData, _ = skus.([]interface{}) // 从updates中移除skus,避免直接更新到Product表 delete(updates, "skus") } // 更新商品基本信息 if err := s.productRepo.Update(id, updates); err != nil { return err } // 处理SKU数据 if len(skusData) > 0 { if err := s.handleProductSKUs(id, skusData); err != nil { return err } } return nil } // handleProductSKUs 处理商品SKU数据 func (s *ProductService) handleProductSKUs(productID uint, skusData []interface{}) error { // 获取当前商品的所有现有SKU existingSKUs, err := s.productRepo.GetProductSKUs(productID) if err != nil { return err } // 收集前端发送的SKU ID列表 var submittedSKUIDs []uint // 处理前端发送的SKU数据 for _, skuData := range skusData { skuMap, ok := skuData.(map[string]interface{}) if !ok { continue } // 创建SKU对象 sku := &model.ProductSKU{ ProductID: productID, } // 处理SKU字段 if skuCode, ok := skuMap["sku_code"].(string); ok { sku.SKUCode = skuCode } if price, ok := skuMap["price"].(float64); ok { sku.Price = price } if stock, ok := skuMap["stock"]; ok { switch v := stock.(type) { case float64: sku.Stock = int(v) case int: sku.Stock = v case string: if stockInt, err := strconv.Atoi(v); err == nil { sku.Stock = stockInt } } } // 处理spec_values if specValues, ok := skuMap["spec_values"]; ok { if specMap, ok := specValues.(map[string]interface{}); ok { sku.SpecValues = model.JSONMap(specMap) } } // 处理image字段 if image, ok := skuMap["image"].(string); ok { sku.Image = image } // 检查是否是更新还是创建 var isUpdate bool var skuIDValue uint if skuID, ok := skuMap["id"]; ok && skuID != nil { switch v := skuID.(type) { case float64: if v > 0 { isUpdate = true skuIDValue = uint(v) submittedSKUIDs = append(submittedSKUIDs, skuIDValue) } case int: if v > 0 { isUpdate = true skuIDValue = uint(v) submittedSKUIDs = append(submittedSKUIDs, skuIDValue) } } } if isUpdate { // 更新现有SKU updates := make(map[string]interface{}) if sku.SKUCode != "" { updates["sku_code"] = sku.SKUCode } updates["price"] = sku.Price updates["stock"] = sku.Stock // 直接传递JSONMap类型,让GORM处理序列化 updates["spec_values"] = sku.SpecValues // 添加image字段的更新 if sku.Image != "" { updates["image"] = sku.Image } if err := s.productRepo.UpdateSKU(skuIDValue, updates); err != nil { return err } } else { // 创建新SKU - 确保不设置ID字段 sku.ID = 0 // 明确设置为0,让数据库自动生成 if sku.SKUCode == "" { // 生成默认SKU代码 sku.SKUCode = fmt.Sprintf("SKU-%d-%d", productID, time.Now().Unix()) } if err := s.productRepo.CreateSKU(sku); err != nil { return err } } } // 删除不在前端提交列表中的现有SKU for _, existingSKU := range existingSKUs { shouldDelete := true for _, submittedID := range submittedSKUIDs { if existingSKU.ID == submittedID { shouldDelete = false break } } if shouldDelete { if err := s.productRepo.DeleteSKU(existingSKU.ID); err != nil { return fmt.Errorf("删除SKU失败 - SKU ID: %d, 错误: %v", existingSKU.ID, err) } } } // 处理完所有SKU后,同步商品库存 if err := s.productRepo.SyncProductStockFromSKUs(productID); err != nil { // 记录错误但不阻止操作 fmt.Printf("同步商品库存失败 - 商品ID: %d, 错误: %v\n", productID, err) } return nil } // DeleteProduct 删除产品 func (s *ProductService) DeleteProduct(id uint) error { // 检查产品是否存在 _, err := s.productRepo.GetByID(id) if err != nil { return errors.New("产品不存在") } return s.productRepo.Delete(id) } // GetCategories 获取分类列表 func (s *ProductService) GetCategories() ([]model.Category, error) { return s.productRepo.GetCategories() } // CreateCategory 创建分类 func (s *ProductService) CreateCategory(category *model.Category) error { return s.productRepo.CreateCategory(category) } // UpdateCategory 更新分类 func (s *ProductService) UpdateCategory(id uint, updates map[string]interface{}) error { // 检查分类是否存在 _, err := s.productRepo.GetCategoryByID(id) if err != nil { return errors.New("分类不存在") } return s.productRepo.UpdateCategory(id, updates) } // DeleteCategory 删除分类 func (s *ProductService) DeleteCategory(id uint) error { // 检查分类是否存在 _, err := s.productRepo.GetCategoryByID(id) if err != nil { return errors.New("分类不存在") } // 检查分类下是否有商品 productCount, err := s.productRepo.CountProductsByCategory(id) if err != nil { return errors.New("检查分类商品数量失败") } if productCount > 0 { return errors.New("该分类下还有商品,无法删除") } // 检查是否有子分类 var childCategories []model.Category err = s.productRepo.GetDB().Where("parent_id = ?", id).Find(&childCategories).Error if err != nil { return errors.New("检查子分类失败") } if len(childCategories) > 0 { return errors.New("该分类下还有子分类,请先删除子分类") } return s.productRepo.DeleteCategory(id) } // GetProductReviews 获取产品评价列表 func (s *ProductService) GetProductReviews(productID uint, page, pageSize int) ([]model.ProductReview, *utils.Pagination, error) { if page <= 0 { page = 1 } if pageSize <= 0 || pageSize > 100 { pageSize = 20 } offset := (page - 1) * pageSize reviews, total, err := s.productRepo.GetReviews(productID, offset, pageSize) if err != nil { return nil, nil, err } pagination := utils.NewPagination(page, pageSize) pagination.Total = total return reviews, pagination, nil } // CreateReview 创建评价 func (s *ProductService) CreateReview(userID uint, review *model.ProductReview) error { // 检查用户是否存在 _, err := s.userRepo.GetByID(userID) if err != nil { return errors.New("用户不存在") } // 检查产品是否存在 _, err = s.productRepo.GetByID(review.ProductID) if err != nil { return errors.New("产品不存在") } // 检查是否已经评价过 if review.OrderID != nil { existingReview, _ := s.productRepo.GetReviewByOrderID(userID, *review.OrderID) if existingReview != nil { return errors.New("已经评价过该商品") } } review.UserID = userID return s.productRepo.CreateReview(review) } // GetHotProducts 获取热门产品 func (s *ProductService) GetHotProducts(limit int) ([]model.Product, error) { if limit <= 0 || limit > 50 { limit = 10 } return s.productRepo.GetHotProducts(limit) } // GetRecommendProducts 获取推荐产品 func (s *ProductService) GetRecommendProducts(limit int) ([]model.Product, error) { if limit <= 0 || limit > 50 { limit = 10 } return s.productRepo.GetRecommendProducts(limit) } // SearchProducts 搜索产品(支持价格与排序) func (s *ProductService) SearchProducts(keyword string, page, pageSize int, minPrice, maxPrice float64, sort, sortType string) ([]model.Product, *utils.Pagination, error) { if keyword == "" { return []model.Product{}, utils.NewPagination(page, pageSize), nil } return s.GetProductList(page, pageSize, 0, keyword, minPrice, maxPrice, sort, sortType) } // UpdateStock 更新库存 func (s *ProductService) UpdateStock(id uint, quantity int) error { // 检查产品是否存在 product, err := s.productRepo.GetByID(id) if err != nil { return errors.New("产品不存在") } // 检查库存是否足够(减库存时) if quantity < 0 && product.Stock < -quantity { return errors.New("库存不足") } return s.productRepo.UpdateStock(id, quantity) } // GetProductSKUs 获取产品SKU列表 func (s *ProductService) GetProductSKUs(productID uint) ([]model.ProductSKU, error) { return s.productRepo.GetProductSKUs(productID) } // GetSKUByID 根据SKU ID获取SKU详情 func (s *ProductService) GetSKUByID(skuID uint) (*model.ProductSKU, error) { return s.productRepo.GetSKUByID(skuID) } // GetProductTags 获取产品标签列表 func (s *ProductService) GetProductTags() ([]model.ProductTag, error) { return s.productRepo.GetProductTags() } // GetStores 获取店铺列表 func (s *ProductService) GetStores() ([]model.Store, error) { return s.productRepo.GetStores() } // GetStoreByID 根据ID获取店铺信息 func (s *ProductService) GetStoreByID(id uint) (*model.Store, error) { return s.productRepo.GetStoreByID(id) } // GetProductReviewCount 获取产品评价统计 func (s *ProductService) GetProductReviewCount(productID uint) (map[string]interface{}, error) { // 检查产品是否存在 _, err := s.productRepo.GetByID(productID) if err != nil { return nil, errors.New("产品不存在") } return s.productRepo.GetReviewCount(productID) } // GetProductStatistics 获取产品统计 func (s *ProductService) GetProductStatistics() (map[string]interface{}, error) { // 使用ProductRepository的GetProductStatistics方法 return s.productRepo.GetProductStatistics() } // GetProductSalesRanking 获取产品销售排行 func (s *ProductService) GetProductSalesRanking(startDate, endDate, limit string) ([]map[string]interface{}, error) { // 简化实现,返回基础排行数据 var results []map[string]interface{} // 这里应该根据订单数据统计产品销量,暂时返回模拟数据 products, _, err := s.productRepo.GetList(0, 10, map[string]interface{}{"status": 1}) if err != nil { return nil, err } for i, product := range products { if i >= 10 { // 限制返回数量 break } results = append(results, map[string]interface{}{ "product_id": product.ID, "product_name": product.Name, "sales_count": 100 - i*5, // 模拟销量数据 "sales_amount": float64(1000 - i*50), }) } return results, nil } // GetCategorySalesRanking 获取分类销售排行 func (s *ProductService) GetCategorySalesRanking(startDate, endDate, limit string) ([]map[string]interface{}, error) { // 解析limit参数 limitInt := 10 // 默认值 if limit != "" { if parsedLimit, err := strconv.Atoi(limit); err == nil && parsedLimit > 0 { limitInt = parsedLimit } } // 如果没有提供日期范围,使用最近30天 if startDate == "" || endDate == "" { now := time.Now() endDate = now.Format("2006-01-02") startDate = now.AddDate(0, 0, -30).Format("2006-01-02") } // 使用真实的数据库查询 return s.productRepo.GetCategorySalesStatistics(startDate, endDate, limitInt) } // BatchUpdateProductStatus 批量更新商品状态 func (s *ProductService) BatchUpdateProductStatus(ids []uint, status int) error { if len(ids) == 0 { return errors.New("商品ID列表不能为空") } return s.productRepo.BatchUpdateStatus(ids, status) } // BatchUpdateProductPrice 批量更新商品价格 func (s *ProductService) BatchUpdateProductPrice(updates []map[string]interface{}) error { if len(updates) == 0 { return errors.New("更新数据不能为空") } return s.productRepo.BatchUpdatePrice(updates) } // BatchDeleteProducts 批量删除商品 func (s *ProductService) BatchDeleteProducts(ids []uint) error { if len(ids) == 0 { return errors.New("商品ID列表不能为空") } return s.productRepo.BatchDelete(ids) } // CreateProductSKU 创建商品SKU func (s *ProductService) CreateProductSKU(sku *model.ProductSKU) error { // 验证商品是否存在 _, err := s.productRepo.GetByID(sku.ProductID) if err != nil { return errors.New("商品不存在") } return s.productRepo.CreateSKU(sku) } // UpdateProductSKU 更新商品SKU func (s *ProductService) UpdateProductSKU(id uint, updates map[string]interface{}) error { // 检查SKU是否存在 _, err := s.productRepo.GetSKUByID(id) if err != nil { return errors.New("SKU不存在") } return s.productRepo.UpdateSKU(id, updates) } // DeleteProductSKU 删除商品SKU func (s *ProductService) DeleteProductSKU(id uint) error { // 检查SKU是否存在(包括已软删除的) var sku model.ProductSKU err := s.productRepo.GetDB().Where("id = ?", id).First(&sku).Error if err != nil { return errors.New("SKU不存在") } // 如果SKU已经被软删除,直接返回成功 if sku.Status == 0 { fmt.Printf("SKU ID %d 已经被软删除,无需重复操作\n", id) return nil } // 检查SKU是否被订单引用 var count int64 err = s.productRepo.GetDB().Table("order_items").Where("sk_uid = ?", id).Count(&count).Error if err != nil { return fmt.Errorf("检查SKU引用关系失败: %v", err) } if count > 0 { // 如果被订单引用,执行软删除 err = s.productRepo.DeleteSKU(id) if err != nil { return fmt.Errorf("删除SKU失败: %v", err) } // 软删除成功,记录日志但不返回错误 fmt.Printf("SKU ID %d 已被 %d 个订单引用,已执行软删除(设置为不可用状态)\n", id, count) return nil } // 如果没有被引用,执行硬删除 err = s.productRepo.DeleteSKU(id) if err != nil { return fmt.Errorf("删除SKU失败: %v", err) } // 同步更新商品库存 if err := s.productRepo.SyncProductStockFromSKUs(sku.ProductID); err != nil { // 记录错误但不阻止删除操作 fmt.Printf("同步商品库存失败 - 商品ID: %d, 错误: %v\n", sku.ProductID, err) } return nil } // GetProductImages 获取商品图片列表 func (s *ProductService) GetProductImages(productID uint) ([]model.ProductImage, error) { return s.productRepo.GetProductImages(productID) } // CreateProductImage 创建商品图片 func (s *ProductService) CreateProductImage(image *model.ProductImage) error { // 验证商品是否存在 _, err := s.productRepo.GetByID(image.ProductID) if err != nil { return errors.New("商品不存在") } return s.productRepo.CreateProductImage(image) } // UpdateProductImageSort 更新商品图片排序 func (s *ProductService) UpdateProductImageSort(id uint, sort int) error { return s.productRepo.UpdateProductImageSort(id, sort) } // DeleteProductImage 删除商品图片 func (s *ProductService) DeleteProductImage(id uint) error { return s.productRepo.DeleteProductImage(id) } // CreateProductSpec 创建商品规格 func (s *ProductService) CreateProductSpec(spec *model.ProductSpec) error { // 验证商品是否存在 _, err := s.productRepo.GetByID(spec.ProductID) if err != nil { return errors.New("商品不存在") } return s.productRepo.CreateProductSpec(spec) } // UpdateProductSpec 更新商品规格 func (s *ProductService) UpdateProductSpec(id uint, updates map[string]interface{}) error { return s.productRepo.UpdateProductSpec(id, updates) } // DeleteProductSpec 删除商品规格 func (s *ProductService) DeleteProductSpec(id uint) error { return s.productRepo.DeleteProductSpec(id) } // GetProductSpecs 获取商品规格列表 func (s *ProductService) GetProductSpecs(productID uint) ([]model.ProductSpec, error) { return s.productRepo.GetProductSpecs(productID) } // CreateProductTag 创建商品标签 func (s *ProductService) CreateProductTag(tag *model.ProductTag) error { return s.productRepo.CreateProductTag(tag) } // UpdateProductTag 更新商品标签 func (s *ProductService) UpdateProductTag(id uint, updates map[string]interface{}) error { return s.productRepo.UpdateProductTag(id, updates) } // DeleteProductTag 删除商品标签 func (s *ProductService) DeleteProductTag(id uint) error { return s.productRepo.DeleteProductTag(id) } // AssignTagsToProduct 为商品分配标签 func (s *ProductService) AssignTagsToProduct(productID uint, tagIDs []uint) error { // 验证商品是否存在 _, err := s.productRepo.GetByID(productID) if err != nil { return errors.New("商品不存在") } return s.productRepo.AssignTagsToProduct(productID, tagIDs) } // GetLowStockProducts 获取低库存商品 func (s *ProductService) GetLowStockProducts(threshold int) ([]model.Product, error) { if threshold <= 0 { threshold = 10 // 默认阈值 } return s.productRepo.GetLowStockProducts(threshold) } // GetInventoryStatistics 获取库存统计 func (s *ProductService) GetInventoryStatistics() (map[string]interface{}, error) { return s.productRepo.GetInventoryStatistics() } // ExportProducts 导出商品数据 func (s *ProductService) ExportProducts(conditions map[string]interface{}) ([]model.Product, error) { return s.productRepo.GetProductsForExport(conditions) } // ImportProducts 导入商品数据 func (s *ProductService) ImportProducts(products []model.Product) (map[string]interface{}, error) { successCount := 0 failCount := 0 var errors []string for _, product := range products { // 验证商品数据 if product.Name == "" { errors = append(errors, "商品名称不能为空") failCount++ continue } if product.Price <= 0 { errors = append(errors, "商品价格必须大于0") failCount++ continue } // 创建商品 err := s.productRepo.Create(&product) if err != nil { errors = append(errors, err.Error()) failCount++ } else { successCount++ } } return map[string]interface{}{ "success_count": successCount, "fail_count": failCount, "errors": errors, }, nil } // SyncProductStock 同步商品库存(根据SKU库存计算) func (s *ProductService) SyncProductStock(productID uint) error { return s.productRepo.SyncProductStockFromSKUs(productID) } // SyncAllProductsStock 同步所有商品库存 func (s *ProductService) SyncAllProductsStock() error { // 获取所有有SKU的商品 products, _, err := s.productRepo.GetList(0, 0, map[string]interface{}{}) if err != nil { return err } var syncErrors []string for _, product := range products { // 检查商品是否有SKU skus, err := s.productRepo.GetProductSKUs(product.ID) if err != nil { continue } if len(skus) > 0 { // 如果有SKU,同步库存 err = s.productRepo.SyncProductStockFromSKUs(product.ID) if err != nil { syncErrors = append(syncErrors, fmt.Sprintf("商品ID %d 同步失败: %v", product.ID, err)) } } } if len(syncErrors) > 0 { return fmt.Errorf("部分商品同步失败: %v", syncErrors) } return nil }