You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
3.9 KiB
143 lines
3.9 KiB
package service
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
|
|
"health-ai/internal/model"
|
|
"health-ai/internal/repository/impl"
|
|
)
|
|
|
|
type ProductService struct {
|
|
productRepo *impl.ProductRepository
|
|
constitutionRepo *impl.ConstitutionRepository
|
|
}
|
|
|
|
func NewProductService() *ProductService {
|
|
return &ProductService{
|
|
productRepo: impl.NewProductRepository(),
|
|
constitutionRepo: impl.NewConstitutionRepository(),
|
|
}
|
|
}
|
|
|
|
// ================= 请求/响应结构体 =================
|
|
|
|
// ProductListResponse 产品列表响应
|
|
type ProductListResponse struct {
|
|
Products []model.Product `json:"products"`
|
|
Total int64 `json:"total"`
|
|
Page int `json:"page"`
|
|
PageSize int `json:"page_size"`
|
|
}
|
|
|
|
// ProductRecommendResponse 产品推荐响应
|
|
type ProductRecommendResponse struct {
|
|
ConstitutionType string `json:"constitution_type"`
|
|
ConstitutionName string `json:"constitution_name"`
|
|
Products []model.Product `json:"products"`
|
|
}
|
|
|
|
// PurchaseSyncRequest 购买同步请求
|
|
type PurchaseSyncRequest struct {
|
|
UserID uint `json:"user_id" binding:"required"`
|
|
OrderNo string `json:"order_no" binding:"required"`
|
|
Products []struct {
|
|
ID uint `json:"id" binding:"required"`
|
|
Name string `json:"name" binding:"required"`
|
|
} `json:"products" binding:"required"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
// ================= Service 方法 =================
|
|
|
|
// GetProducts 获取产品列表
|
|
func (s *ProductService) GetProducts(page, pageSize int) (*ProductListResponse, error) {
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
if pageSize <= 0 {
|
|
pageSize = 20
|
|
}
|
|
|
|
products, total, err := s.productRepo.GetAll(page, pageSize)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &ProductListResponse{
|
|
Products: products,
|
|
Total: total,
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
}, nil
|
|
}
|
|
|
|
// GetProductByID 获取产品详情
|
|
func (s *ProductService) GetProductByID(id uint) (*model.Product, error) {
|
|
product, err := s.productRepo.GetByID(id)
|
|
if err != nil {
|
|
return nil, errors.New("产品不存在")
|
|
}
|
|
return product, nil
|
|
}
|
|
|
|
// GetProductsByCategory 按分类获取产品
|
|
func (s *ProductService) GetProductsByCategory(category string) ([]model.Product, error) {
|
|
return s.productRepo.GetByCategory(category)
|
|
}
|
|
|
|
// GetRecommendedProducts 根据用户体质获取推荐产品
|
|
func (s *ProductService) GetRecommendedProducts(userID uint) (*ProductRecommendResponse, error) {
|
|
// 获取用户最新体质
|
|
assessment, err := s.constitutionRepo.GetLatestAssessment(userID)
|
|
if err != nil {
|
|
return nil, errors.New("请先完成体质测评")
|
|
}
|
|
|
|
// 获取该体质的推荐产品
|
|
products, err := s.productRepo.GetByConstitution(assessment.PrimaryConstitution)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &ProductRecommendResponse{
|
|
ConstitutionType: assessment.PrimaryConstitution,
|
|
ConstitutionName: model.ConstitutionNames[assessment.PrimaryConstitution],
|
|
Products: products,
|
|
}, nil
|
|
}
|
|
|
|
// SearchProducts 根据关键词搜索产品
|
|
func (s *ProductService) SearchProducts(keyword string) ([]model.Product, error) {
|
|
if keyword == "" {
|
|
return nil, errors.New("请输入搜索关键词")
|
|
}
|
|
return s.productRepo.SearchByKeyword(keyword)
|
|
}
|
|
|
|
// SyncPurchase 同步商城购买记录
|
|
func (s *ProductService) SyncPurchase(req *PurchaseSyncRequest) error {
|
|
purchasedAt := req.CreatedAt
|
|
if purchasedAt.IsZero() {
|
|
purchasedAt = time.Now()
|
|
}
|
|
|
|
histories := make([]model.PurchaseHistory, len(req.Products))
|
|
for i, p := range req.Products {
|
|
histories[i] = model.PurchaseHistory{
|
|
UserID: req.UserID,
|
|
OrderNo: req.OrderNo,
|
|
ProductID: p.ID,
|
|
ProductName: p.Name,
|
|
PurchasedAt: purchasedAt,
|
|
Source: "mall",
|
|
}
|
|
}
|
|
|
|
return s.productRepo.BatchCreatePurchaseHistory(histories)
|
|
}
|
|
|
|
// GetPurchaseHistory 获取用户购买历史
|
|
func (s *ProductService) GetPurchaseHistory(userID uint) ([]model.PurchaseHistory, error) {
|
|
return s.productRepo.GetPurchaseHistory(userID)
|
|
}
|
|
|