feat: 实现套餐管理模块,包含套餐系列、双状态管理、废弃模型清理
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m24s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m24s
- 新增套餐系列管理 (CRUD + 状态切换) - 新增套餐管理 (CRUD + 启用/禁用 + 上架/下架双状态) - 清理 8 个废弃分佣模型及对应数据库表 - Package 模型新增建议成本价、建议售价、上架状态字段 - 完整的 Store/Service/Handler 三层实现 - 包含单元测试和集成测试 - 归档 add-package-module change - 新增多个 OpenSpec changes (订单支付、店铺套餐分配、一次性分佣、卡设备系列绑定)
This commit is contained in:
177
internal/service/package_series/service.go
Normal file
177
internal/service/package_series/service.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package package_series
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
packageSeriesStore *postgres.PackageSeriesStore
|
||||
}
|
||||
|
||||
func New(packageSeriesStore *postgres.PackageSeriesStore) *Service {
|
||||
return &Service{packageSeriesStore: packageSeriesStore}
|
||||
}
|
||||
|
||||
func (s *Service) Create(ctx context.Context, req *dto.CreatePackageSeriesRequest) (*dto.PackageSeriesResponse, error) {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
}
|
||||
|
||||
existing, _ := s.packageSeriesStore.GetByCode(ctx, req.SeriesCode)
|
||||
if existing != nil {
|
||||
return nil, errors.New(errors.CodeConflict, "系列编码已存在")
|
||||
}
|
||||
|
||||
series := &model.PackageSeries{
|
||||
SeriesCode: req.SeriesCode,
|
||||
SeriesName: req.SeriesName,
|
||||
Description: req.Description,
|
||||
Status: constants.StatusEnabled,
|
||||
}
|
||||
series.Creator = currentUserID
|
||||
|
||||
if err := s.packageSeriesStore.Create(ctx, series); err != nil {
|
||||
return nil, fmt.Errorf("创建套餐系列失败: %w", err)
|
||||
}
|
||||
|
||||
return s.toResponse(series), nil
|
||||
}
|
||||
|
||||
func (s *Service) Get(ctx context.Context, id uint) (*dto.PackageSeriesResponse, error) {
|
||||
series, err := s.packageSeriesStore.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, errors.New(errors.CodeNotFound, "套餐系列不存在")
|
||||
}
|
||||
return nil, fmt.Errorf("获取套餐系列失败: %w", err)
|
||||
}
|
||||
return s.toResponse(series), nil
|
||||
}
|
||||
|
||||
func (s *Service) Update(ctx context.Context, id uint, req *dto.UpdatePackageSeriesRequest) (*dto.PackageSeriesResponse, error) {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
}
|
||||
|
||||
series, err := s.packageSeriesStore.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, errors.New(errors.CodeNotFound, "套餐系列不存在")
|
||||
}
|
||||
return nil, fmt.Errorf("获取套餐系列失败: %w", err)
|
||||
}
|
||||
|
||||
if req.SeriesName != nil {
|
||||
series.SeriesName = *req.SeriesName
|
||||
}
|
||||
if req.Description != nil {
|
||||
series.Description = *req.Description
|
||||
}
|
||||
series.Updater = currentUserID
|
||||
|
||||
if err := s.packageSeriesStore.Update(ctx, series); err != nil {
|
||||
return nil, fmt.Errorf("更新套餐系列失败: %w", err)
|
||||
}
|
||||
|
||||
return s.toResponse(series), nil
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, id uint) error {
|
||||
_, err := s.packageSeriesStore.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return errors.New(errors.CodeNotFound, "套餐系列不存在")
|
||||
}
|
||||
return fmt.Errorf("获取套餐系列失败: %w", err)
|
||||
}
|
||||
|
||||
if err := s.packageSeriesStore.Delete(ctx, id); err != nil {
|
||||
return fmt.Errorf("删除套餐系列失败: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) List(ctx context.Context, req *dto.PackageSeriesListRequest) ([]*dto.PackageSeriesResponse, int64, error) {
|
||||
opts := &store.QueryOptions{
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
OrderBy: "id DESC",
|
||||
}
|
||||
if opts.Page == 0 {
|
||||
opts.Page = 1
|
||||
}
|
||||
if opts.PageSize == 0 {
|
||||
opts.PageSize = constants.DefaultPageSize
|
||||
}
|
||||
|
||||
filters := make(map[string]interface{})
|
||||
if req.SeriesName != nil {
|
||||
filters["series_name"] = *req.SeriesName
|
||||
}
|
||||
if req.Status != nil {
|
||||
filters["status"] = *req.Status
|
||||
}
|
||||
|
||||
seriesList, total, err := s.packageSeriesStore.List(ctx, opts, filters)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("查询套餐系列列表失败: %w", err)
|
||||
}
|
||||
|
||||
responses := make([]*dto.PackageSeriesResponse, len(seriesList))
|
||||
for i, series := range seriesList {
|
||||
responses[i] = s.toResponse(series)
|
||||
}
|
||||
|
||||
return responses, total, nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error {
|
||||
currentUserID := middleware.GetUserIDFromContext(ctx)
|
||||
if currentUserID == 0 {
|
||||
return errors.New(errors.CodeUnauthorized, "未授权访问")
|
||||
}
|
||||
|
||||
series, err := s.packageSeriesStore.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return errors.New(errors.CodeNotFound, "套餐系列不存在")
|
||||
}
|
||||
return fmt.Errorf("获取套餐系列失败: %w", err)
|
||||
}
|
||||
|
||||
series.Status = status
|
||||
series.Updater = currentUserID
|
||||
|
||||
if err := s.packageSeriesStore.Update(ctx, series); err != nil {
|
||||
return fmt.Errorf("更新套餐系列状态失败: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) toResponse(series *model.PackageSeries) *dto.PackageSeriesResponse {
|
||||
return &dto.PackageSeriesResponse{
|
||||
ID: series.ID,
|
||||
SeriesCode: series.SeriesCode,
|
||||
SeriesName: series.SeriesName,
|
||||
Description: series.Description,
|
||||
Status: series.Status,
|
||||
CreatedAt: series.CreatedAt.Format(time.RFC3339),
|
||||
UpdatedAt: series.UpdatedAt.Format(time.RFC3339),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user