重构配方类服务层
This commit is contained in:
@@ -1,618 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/recipe"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
|
||||
)
|
||||
|
||||
// 定义服务层特定的错误
|
||||
var (
|
||||
ErrNutrientNameConflict = errors.New("营养种类名称已存在")
|
||||
ErrNutrientNotFound = errors.New("营养种类不存在")
|
||||
ErrRawMaterialNameConflict = errors.New("原料名称已存在")
|
||||
ErrRawMaterialNotFound = errors.New("原料不存在")
|
||||
ErrPigBreedInUse = errors.New("猪品种正在被猪类型使用,无法删除")
|
||||
ErrPigBreedNotFound = errors.New("猪品种不存在")
|
||||
ErrPigAgeStageInUse = errors.New("猪年龄阶段正在被猪类型使用,无法删除")
|
||||
ErrPigAgeStageNotFound = errors.New("猪年龄阶段不存在")
|
||||
ErrPigTypeNotFound = errors.New("猪类型不存在")
|
||||
)
|
||||
|
||||
// FeedManagementService 定义了饲料管理的应用服务接口
|
||||
type FeedManagementService interface {
|
||||
// 营养种类相关
|
||||
CreateNutrient(ctx context.Context, req *dto.CreateNutrientRequest) (*dto.NutrientResponse, error)
|
||||
UpdateNutrient(ctx context.Context, id uint32, req *dto.UpdateNutrientRequest) (*dto.NutrientResponse, error)
|
||||
DeleteNutrient(ctx context.Context, id uint32) error
|
||||
GetNutrient(ctx context.Context, id uint32) (*dto.NutrientResponse, error)
|
||||
ListNutrients(ctx context.Context, req *dto.ListNutrientRequest) (*dto.ListNutrientResponse, error)
|
||||
|
||||
// 原料相关
|
||||
CreateRawMaterial(ctx context.Context, req *dto.CreateRawMaterialRequest) (*dto.RawMaterialResponse, error)
|
||||
UpdateRawMaterial(ctx context.Context, id uint32, req *dto.UpdateRawMaterialRequest) (*dto.RawMaterialResponse, error)
|
||||
DeleteRawMaterial(ctx context.Context, id uint32) error
|
||||
GetRawMaterial(ctx context.Context, id uint32) (*dto.RawMaterialResponse, error)
|
||||
ListRawMaterials(ctx context.Context, req *dto.ListRawMaterialRequest) (*dto.ListRawMaterialResponse, error)
|
||||
UpdateRawMaterialNutrients(ctx context.Context, id uint32, req *dto.UpdateRawMaterialNutrientsRequest) (*dto.RawMaterialResponse, error) // 新增
|
||||
|
||||
// 猪品种相关
|
||||
CreatePigBreed(ctx context.Context, req *dto.CreatePigBreedRequest) (*dto.PigBreedResponse, error)
|
||||
UpdatePigBreed(ctx context.Context, id uint32, req *dto.UpdatePigBreedRequest) (*dto.PigBreedResponse, error)
|
||||
DeletePigBreed(ctx context.Context, id uint32) error
|
||||
GetPigBreed(ctx context.Context, id uint32) (*dto.PigBreedResponse, error)
|
||||
ListPigBreeds(ctx context.Context, req *dto.ListPigBreedRequest) (*dto.ListPigBreedResponse, error)
|
||||
|
||||
// 猪年龄阶段相关
|
||||
CreatePigAgeStage(ctx context.Context, req *dto.CreatePigAgeStageRequest) (*dto.PigAgeStageResponse, error)
|
||||
UpdatePigAgeStage(ctx context.Context, id uint32, req *dto.UpdatePigAgeStageRequest) (*dto.PigAgeStageResponse, error)
|
||||
DeletePigAgeStage(ctx context.Context, id uint32) error
|
||||
GetPigAgeStage(ctx context.Context, id uint32) (*dto.PigAgeStageResponse, error)
|
||||
ListPigAgeStages(ctx context.Context, req *dto.ListPigAgeStageRequest) (*dto.ListPigAgeStageResponse, error)
|
||||
|
||||
// 猪类型相关
|
||||
CreatePigType(ctx context.Context, req *dto.CreatePigTypeRequest) (*dto.PigTypeResponse, error)
|
||||
UpdatePigType(ctx context.Context, id uint32, req *dto.UpdatePigTypeRequest) (*dto.PigTypeResponse, error)
|
||||
DeletePigType(ctx context.Context, id uint32) error
|
||||
GetPigType(ctx context.Context, id uint32) (*dto.PigTypeResponse, error)
|
||||
ListPigTypes(ctx context.Context, req *dto.ListPigTypeRequest) (*dto.ListPigTypeResponse, error)
|
||||
UpdatePigTypeNutrientRequirements(ctx context.Context, id uint32, req *dto.UpdatePigTypeNutrientRequirementsRequest) (*dto.PigTypeResponse, error) // 新增
|
||||
}
|
||||
|
||||
// feedManagementServiceImpl 是 FeedManagementService 接口的实现
|
||||
type feedManagementServiceImpl struct {
|
||||
ctx context.Context
|
||||
recipeSvc recipe.Service
|
||||
}
|
||||
|
||||
// NewFeedManagementService 创建一个新的 FeedManagementService 实例
|
||||
func NewFeedManagementService(ctx context.Context, recipeSvc recipe.Service) FeedManagementService {
|
||||
return &feedManagementServiceImpl{
|
||||
ctx: ctx,
|
||||
recipeSvc: recipeSvc,
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// 营养种类 (Nutrient) 实现
|
||||
// =====================================================================================================================
|
||||
|
||||
// CreateNutrient 创建营养种类
|
||||
func (s *feedManagementServiceImpl) CreateNutrient(ctx context.Context, req *dto.CreateNutrientRequest) (*dto.NutrientResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreateNutrient")
|
||||
|
||||
nutrient, err := s.recipeSvc.CreateNutrient(serviceCtx, req.Name, req.Description)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrNutrientNameConflict) {
|
||||
return nil, ErrNutrientNameConflict
|
||||
}
|
||||
return nil, fmt.Errorf("创建营养种类失败: %w", err)
|
||||
}
|
||||
return dto.ConvertNutrientToDTO(nutrient), nil
|
||||
}
|
||||
|
||||
// UpdateNutrient 更新营养种类
|
||||
func (s *feedManagementServiceImpl) UpdateNutrient(ctx context.Context, id uint32, req *dto.UpdateNutrientRequest) (*dto.NutrientResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateNutrient")
|
||||
|
||||
nutrient, err := s.recipeSvc.UpdateNutrient(serviceCtx, id, req.Name, req.Description)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrNutrientNotFound) {
|
||||
return nil, ErrNutrientNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrNutrientNameConflict) {
|
||||
return nil, ErrNutrientNameConflict
|
||||
}
|
||||
return nil, fmt.Errorf("更新营养种类失败: %w", err)
|
||||
}
|
||||
return dto.ConvertNutrientToDTO(nutrient), nil
|
||||
}
|
||||
|
||||
// DeleteNutrient 删除营养种类
|
||||
func (s *feedManagementServiceImpl) DeleteNutrient(ctx context.Context, id uint32) error {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeleteNutrient")
|
||||
err := s.recipeSvc.DeleteNutrient(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrNutrientNotFound) {
|
||||
return ErrNutrientNotFound
|
||||
}
|
||||
return fmt.Errorf("删除营养种类失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNutrient 获取单个营养种类
|
||||
func (s *feedManagementServiceImpl) GetNutrient(ctx context.Context, id uint32) (*dto.NutrientResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetNutrient")
|
||||
|
||||
nutrient, err := s.recipeSvc.GetNutrient(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrNutrientNotFound) {
|
||||
return nil, ErrNutrientNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("获取营养种类失败: %w", err)
|
||||
}
|
||||
return dto.ConvertNutrientToDTO(nutrient), nil
|
||||
}
|
||||
|
||||
// ListNutrients 列出营养种类
|
||||
func (s *feedManagementServiceImpl) ListNutrients(ctx context.Context, req *dto.ListNutrientRequest) (*dto.ListNutrientResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListNutrients")
|
||||
|
||||
opts := repository.NutrientListOptions{
|
||||
Name: req.Name,
|
||||
RawMaterialName: req.RawMaterialName,
|
||||
OrderBy: req.OrderBy,
|
||||
}
|
||||
nutrients, total, err := s.recipeSvc.ListNutrients(serviceCtx, opts, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取营养种类列表失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertNutrientListToDTO(nutrients, total, req.Page, req.PageSize), nil
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// 原料 (RawMaterial) 实现
|
||||
// =====================================================================================================================
|
||||
|
||||
// CreateRawMaterial 创建原料
|
||||
func (s *feedManagementServiceImpl) CreateRawMaterial(ctx context.Context, req *dto.CreateRawMaterialRequest) (*dto.RawMaterialResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreateRawMaterial")
|
||||
|
||||
rawMaterial, err := s.recipeSvc.CreateRawMaterial(serviceCtx, req.Name, req.Description)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNameConflict) {
|
||||
return nil, ErrRawMaterialNameConflict
|
||||
}
|
||||
return nil, fmt.Errorf("创建原料失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertRawMaterialToDTO(rawMaterial), nil
|
||||
}
|
||||
|
||||
// UpdateRawMaterial 更新原料
|
||||
func (s *feedManagementServiceImpl) UpdateRawMaterial(ctx context.Context, id uint32, req *dto.UpdateRawMaterialRequest) (*dto.RawMaterialResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateRawMaterial")
|
||||
|
||||
rawMaterial, err := s.recipeSvc.UpdateRawMaterial(serviceCtx, id, req.Name, req.Description)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNotFound) {
|
||||
return nil, ErrRawMaterialNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrRawMaterialNameConflict) {
|
||||
return nil, ErrRawMaterialNameConflict
|
||||
}
|
||||
return nil, fmt.Errorf("更新原料失败: %w", err)
|
||||
}
|
||||
return dto.ConvertRawMaterialToDTO(rawMaterial), nil
|
||||
}
|
||||
|
||||
// DeleteRawMaterial 删除原料
|
||||
func (s *feedManagementServiceImpl) DeleteRawMaterial(ctx context.Context, id uint32) error {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeleteRawMaterial")
|
||||
err := s.recipeSvc.DeleteRawMaterial(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNotFound) {
|
||||
return ErrRawMaterialNotFound
|
||||
}
|
||||
return fmt.Errorf("删除原料失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRawMaterial 获取单个原料
|
||||
func (s *feedManagementServiceImpl) GetRawMaterial(ctx context.Context, id uint32) (*dto.RawMaterialResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetRawMaterial")
|
||||
|
||||
rawMaterial, err := s.recipeSvc.GetRawMaterial(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNotFound) {
|
||||
return nil, ErrRawMaterialNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("获取原料失败: %w", err)
|
||||
}
|
||||
return dto.ConvertRawMaterialToDTO(rawMaterial), nil
|
||||
}
|
||||
|
||||
// ListRawMaterials 列出原料
|
||||
func (s *feedManagementServiceImpl) ListRawMaterials(ctx context.Context, req *dto.ListRawMaterialRequest) (*dto.ListRawMaterialResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListRawMaterials")
|
||||
|
||||
opts := repository.RawMaterialListOptions{
|
||||
Name: req.Name,
|
||||
NutrientName: req.NutrientName,
|
||||
OrderBy: req.OrderBy,
|
||||
}
|
||||
rawMaterials, total, err := s.recipeSvc.ListRawMaterials(serviceCtx, opts, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取原料列表失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertRawMaterialListToDTO(rawMaterials, total, req.Page, req.PageSize), nil
|
||||
}
|
||||
|
||||
// UpdateRawMaterialNutrients 全量更新原料的营养成分
|
||||
func (s *feedManagementServiceImpl) UpdateRawMaterialNutrients(ctx context.Context, id uint32, req *dto.UpdateRawMaterialNutrientsRequest) (*dto.RawMaterialResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateRawMaterialNutrients")
|
||||
|
||||
// 1. 将 DTO 转换为领域模型
|
||||
nutrients := make([]models.RawMaterialNutrient, len(req.Nutrients))
|
||||
for i, item := range req.Nutrients {
|
||||
nutrients[i] = models.RawMaterialNutrient{
|
||||
RawMaterialID: id,
|
||||
NutrientID: item.NutrientID,
|
||||
Value: item.Value,
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 调用领域服务执行更新命令
|
||||
err := s.recipeSvc.UpdateRawMaterialNutrients(serviceCtx, id, nutrients)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNotFound) {
|
||||
return nil, ErrRawMaterialNotFound
|
||||
}
|
||||
// 此处可以根据领域层可能返回的其他特定错误进行转换
|
||||
return nil, fmt.Errorf("更新原料营养成分失败: %w", err)
|
||||
}
|
||||
|
||||
// 3. 更新成功后,调用查询服务获取最新的原料信息
|
||||
updatedRawMaterial, err := s.recipeSvc.GetRawMaterial(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNotFound) {
|
||||
// 理论上不应该发生,因为刚更新成功
|
||||
return nil, ErrRawMaterialNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新后获取原料信息失败: %w", err)
|
||||
}
|
||||
|
||||
// 4. 将领域模型转换为 DTO 并返回
|
||||
return dto.ConvertRawMaterialToDTO(updatedRawMaterial), nil
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// 猪品种 (PigBreed) 实现
|
||||
// =====================================================================================================================
|
||||
|
||||
// CreatePigBreed 创建猪品种
|
||||
func (s *feedManagementServiceImpl) CreatePigBreed(ctx context.Context, req *dto.CreatePigBreedRequest) (*dto.PigBreedResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigBreed")
|
||||
|
||||
breed := &models.PigBreed{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
ParentInfo: req.ParentInfo,
|
||||
AppearanceFeatures: req.AppearanceFeatures,
|
||||
BreedAdvantages: req.BreedAdvantages,
|
||||
BreedDisadvantages: req.BreedDisadvantages,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.CreatePigBreed(serviceCtx, breed); err != nil {
|
||||
return nil, fmt.Errorf("创建猪品种失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigBreedToDTO(breed), nil
|
||||
}
|
||||
|
||||
// UpdatePigBreed 更新猪品种
|
||||
func (s *feedManagementServiceImpl) UpdatePigBreed(ctx context.Context, id uint32, req *dto.UpdatePigBreedRequest) (*dto.PigBreedResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigBreed")
|
||||
|
||||
breed := &models.PigBreed{
|
||||
Model: models.Model{ID: id},
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
ParentInfo: req.ParentInfo,
|
||||
AppearanceFeatures: req.AppearanceFeatures,
|
||||
BreedAdvantages: req.BreedAdvantages,
|
||||
BreedDisadvantages: req.BreedDisadvantages,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.UpdatePigBreed(serviceCtx, breed); err != nil {
|
||||
if errors.Is(err, recipe.ErrPigBreedNotFound) {
|
||||
return nil, ErrPigBreedNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新猪品种失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigBreedToDTO(breed), nil
|
||||
}
|
||||
|
||||
// DeletePigBreed 删除猪品种
|
||||
func (s *feedManagementServiceImpl) DeletePigBreed(ctx context.Context, id uint32) error {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigBreed")
|
||||
err := s.recipeSvc.DeletePigBreed(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigBreedNotFound) {
|
||||
return ErrPigBreedNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrPigBreedInUse) {
|
||||
return ErrPigBreedInUse
|
||||
}
|
||||
return fmt.Errorf("删除猪品种失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPigBreed 获取单个猪品种
|
||||
func (s *feedManagementServiceImpl) GetPigBreed(ctx context.Context, id uint32) (*dto.PigBreedResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigBreed")
|
||||
|
||||
breed, err := s.recipeSvc.GetPigBreedByID(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigBreedNotFound) {
|
||||
return nil, ErrPigBreedNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("获取猪品种失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigBreedToDTO(breed), nil
|
||||
}
|
||||
|
||||
// ListPigBreeds 列出猪品种
|
||||
func (s *feedManagementServiceImpl) ListPigBreeds(ctx context.Context, req *dto.ListPigBreedRequest) (*dto.ListPigBreedResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigBreeds")
|
||||
|
||||
opts := repository.PigBreedListOptions{
|
||||
Name: req.Name,
|
||||
OrderBy: req.OrderBy,
|
||||
}
|
||||
breeds, total, err := s.recipeSvc.ListPigBreeds(serviceCtx, opts, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取猪品种列表失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertPigBreedListToDTO(breeds, total, req.Page, req.PageSize), nil
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// 猪年龄阶段 (PigAgeStage) 实现
|
||||
// =====================================================================================================================
|
||||
|
||||
// CreatePigAgeStage 创建猪年龄阶段
|
||||
func (s *feedManagementServiceImpl) CreatePigAgeStage(ctx context.Context, req *dto.CreatePigAgeStageRequest) (*dto.PigAgeStageResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigAgeStage")
|
||||
|
||||
ageStage := &models.PigAgeStage{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.CreatePigAgeStage(serviceCtx, ageStage); err != nil {
|
||||
return nil, fmt.Errorf("创建猪年龄阶段失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigAgeStageToDTO(ageStage), nil
|
||||
}
|
||||
|
||||
// UpdatePigAgeStage 更新猪年龄阶段
|
||||
func (s *feedManagementServiceImpl) UpdatePigAgeStage(ctx context.Context, id uint32, req *dto.UpdatePigAgeStageRequest) (*dto.PigAgeStageResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigAgeStage")
|
||||
|
||||
ageStage := &models.PigAgeStage{
|
||||
Model: models.Model{ID: id},
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.UpdatePigAgeStage(serviceCtx, ageStage); err != nil {
|
||||
if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
|
||||
return nil, ErrPigAgeStageNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新猪年龄阶段失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigAgeStageToDTO(ageStage), nil
|
||||
}
|
||||
|
||||
// DeletePigAgeStage 删除猪年龄阶段
|
||||
func (s *feedManagementServiceImpl) DeletePigAgeStage(ctx context.Context, id uint32) error {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigAgeStage")
|
||||
err := s.recipeSvc.DeletePigAgeStage(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
|
||||
return ErrPigAgeStageNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrPigAgeStageInUse) {
|
||||
return ErrPigAgeStageInUse
|
||||
}
|
||||
return fmt.Errorf("删除猪年龄阶段失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPigAgeStage 获取单个猪年龄阶段
|
||||
func (s *feedManagementServiceImpl) GetPigAgeStage(ctx context.Context, id uint32) (*dto.PigAgeStageResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigAgeStage")
|
||||
|
||||
ageStage, err := s.recipeSvc.GetPigAgeStageByID(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
|
||||
return nil, ErrPigAgeStageNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("获取猪年龄阶段失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigAgeStageToDTO(ageStage), nil
|
||||
}
|
||||
|
||||
// ListPigAgeStages 列出猪年龄阶段
|
||||
func (s *feedManagementServiceImpl) ListPigAgeStages(ctx context.Context, req *dto.ListPigAgeStageRequest) (*dto.ListPigAgeStageResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigAgeStages")
|
||||
|
||||
opts := repository.PigAgeStageListOptions{
|
||||
Name: req.Name,
|
||||
OrderBy: req.OrderBy,
|
||||
}
|
||||
ageStages, total, err := s.recipeSvc.ListPigAgeStages(serviceCtx, opts, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取猪年龄阶段列表失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertPigAgeStageListToDTO(ageStages, total, req.Page, req.PageSize), nil
|
||||
}
|
||||
|
||||
// =====================================================================================================================
|
||||
// 猪类型 (PigType) 实现
|
||||
// =====================================================================================================================
|
||||
|
||||
// CreatePigType 创建猪类型
|
||||
func (s *feedManagementServiceImpl) CreatePigType(ctx context.Context, req *dto.CreatePigTypeRequest) (*dto.PigTypeResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigType")
|
||||
|
||||
pigType := &models.PigType{
|
||||
BreedID: req.BreedID,
|
||||
AgeStageID: req.AgeStageID,
|
||||
Description: req.Description,
|
||||
DailyFeedIntake: req.DailyFeedIntake,
|
||||
DailyGainWeight: req.DailyGainWeight,
|
||||
MinDays: req.MinDays,
|
||||
MaxDays: req.MaxDays,
|
||||
MinWeight: req.MinWeight,
|
||||
MaxWeight: req.MaxWeight,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.CreatePigType(serviceCtx, pigType); err != nil {
|
||||
if errors.Is(err, recipe.ErrPigBreedNotFound) {
|
||||
return nil, ErrPigBreedNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
|
||||
return nil, ErrPigAgeStageNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("创建猪类型失败: %w", err)
|
||||
}
|
||||
// 创建后需要重新获取,以包含关联数据
|
||||
createdPigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, pigType.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) { // 理论上不应该发生,因为刚创建
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("创建猪类型后获取详情失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigTypeToDTO(createdPigType), nil
|
||||
}
|
||||
|
||||
// UpdatePigType 更新猪类型
|
||||
func (s *feedManagementServiceImpl) UpdatePigType(ctx context.Context, id uint32, req *dto.UpdatePigTypeRequest) (*dto.PigTypeResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigType")
|
||||
|
||||
pigType := &models.PigType{
|
||||
Model: models.Model{ID: id},
|
||||
BreedID: req.BreedID,
|
||||
AgeStageID: req.AgeStageID,
|
||||
Description: req.Description,
|
||||
DailyFeedIntake: req.DailyFeedIntake,
|
||||
DailyGainWeight: req.DailyGainWeight,
|
||||
MinDays: req.MinDays,
|
||||
MaxDays: req.MaxDays,
|
||||
MinWeight: req.MinWeight,
|
||||
MaxWeight: req.MaxWeight,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.UpdatePigType(serviceCtx, pigType); err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) {
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrPigBreedNotFound) {
|
||||
return nil, ErrPigBreedNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
|
||||
return nil, ErrPigAgeStageNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新猪类型失败: %w", err)
|
||||
}
|
||||
// 更新后需要重新获取,以包含关联数据
|
||||
updatedPigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) { // 理论上不应该发生,因为刚更新成功
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新猪类型后获取详情失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigTypeToDTO(updatedPigType), nil
|
||||
}
|
||||
|
||||
// DeletePigType 删除猪类型
|
||||
func (s *feedManagementServiceImpl) DeletePigType(ctx context.Context, id uint32) error {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigType")
|
||||
err := s.recipeSvc.DeletePigType(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) {
|
||||
return ErrPigTypeNotFound
|
||||
}
|
||||
return fmt.Errorf("删除猪类型失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPigType 获取单个猪类型
|
||||
func (s *feedManagementServiceImpl) GetPigType(ctx context.Context, id uint32) (*dto.PigTypeResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigType")
|
||||
|
||||
pigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) {
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("获取猪类型失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigTypeToDTO(pigType), nil
|
||||
}
|
||||
|
||||
// ListPigTypes 列出猪类型
|
||||
func (s *feedManagementServiceImpl) ListPigTypes(ctx context.Context, req *dto.ListPigTypeRequest) (*dto.ListPigTypeResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigTypes")
|
||||
|
||||
opts := repository.PigTypeListOptions{
|
||||
BreedID: req.BreedID,
|
||||
AgeStageID: req.AgeStageID,
|
||||
BreedName: req.BreedName,
|
||||
AgeStageName: req.AgeStageName,
|
||||
OrderBy: req.OrderBy,
|
||||
}
|
||||
pigTypes, total, err := s.recipeSvc.ListPigTypes(serviceCtx, opts, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取猪类型列表失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertPigTypeListToDTO(pigTypes, total, req.Page, req.PageSize), nil
|
||||
}
|
||||
|
||||
// UpdatePigTypeNutrientRequirements 全量更新猪类型的营养需求
|
||||
func (s *feedManagementServiceImpl) UpdatePigTypeNutrientRequirements(ctx context.Context, id uint32, req *dto.UpdatePigTypeNutrientRequirementsRequest) (*dto.PigTypeResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigTypeNutrientRequirements")
|
||||
|
||||
// 1. 将 DTO 转换为领域模型
|
||||
requirements := make([]models.PigNutrientRequirement, len(req.NutrientRequirements))
|
||||
for i, item := range req.NutrientRequirements {
|
||||
requirements[i] = models.PigNutrientRequirement{
|
||||
PigTypeID: id, // 设置所属的 PigTypeID
|
||||
NutrientID: item.NutrientID,
|
||||
MinRequirement: item.MinRequirement,
|
||||
MaxRequirement: item.MaxRequirement,
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 调用领域服务执行更新命令
|
||||
err := s.recipeSvc.UpdatePigTypeNutrientRequirements(serviceCtx, id, requirements)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) {
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
// 此处可以根据领域层可能返回的其他特定错误进行转换
|
||||
return nil, fmt.Errorf("更新猪类型营养需求失败: %w", err)
|
||||
}
|
||||
|
||||
// 3. 更新成功后,调用查询服务获取最新的猪类型信息
|
||||
updatedPigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) {
|
||||
// 理论上不应该发生,因为刚更新成功
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新后获取猪类型信息失败: %w", err)
|
||||
}
|
||||
|
||||
// 4. 将领域模型转换为 DTO 并返回
|
||||
return dto.ConvertPigTypeToDTO(updatedPigType), nil
|
||||
}
|
||||
116
internal/app/service/nutrient_service.go
Normal file
116
internal/app/service/nutrient_service.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/recipe"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
|
||||
)
|
||||
|
||||
// 定义营养种类服务特定的错误
|
||||
var (
|
||||
ErrNutrientNameConflict = errors.New("营养种类名称已存在")
|
||||
ErrNutrientNotFound = errors.New("营养种类不存在")
|
||||
)
|
||||
|
||||
// NutrientService 定义了营养种类相关的应用服务接口
|
||||
type NutrientService interface {
|
||||
CreateNutrient(ctx context.Context, req *dto.CreateNutrientRequest) (*dto.NutrientResponse, error)
|
||||
UpdateNutrient(ctx context.Context, id uint32, req *dto.UpdateNutrientRequest) (*dto.NutrientResponse, error)
|
||||
DeleteNutrient(ctx context.Context, id uint32) error
|
||||
GetNutrient(ctx context.Context, id uint32) (*dto.NutrientResponse, error)
|
||||
ListNutrients(ctx context.Context, req *dto.ListNutrientRequest) (*dto.ListNutrientResponse, error)
|
||||
}
|
||||
|
||||
// nutrientServiceImpl 是 NutrientService 接口的实现
|
||||
type nutrientServiceImpl struct {
|
||||
ctx context.Context
|
||||
recipeSvc recipe.Service
|
||||
}
|
||||
|
||||
// NewNutrientService 创建一个新的 NutrientService 实例
|
||||
func NewNutrientService(ctx context.Context, recipeSvc recipe.Service) NutrientService {
|
||||
return &nutrientServiceImpl{
|
||||
ctx: ctx,
|
||||
recipeSvc: recipeSvc,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateNutrient 创建营养种类
|
||||
func (s *nutrientServiceImpl) CreateNutrient(ctx context.Context, req *dto.CreateNutrientRequest) (*dto.NutrientResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreateNutrient")
|
||||
|
||||
nutrient, err := s.recipeSvc.CreateNutrient(serviceCtx, req.Name, req.Description)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrNutrientNameConflict) {
|
||||
return nil, ErrNutrientNameConflict
|
||||
}
|
||||
return nil, fmt.Errorf("创建营养种类失败: %w", err)
|
||||
}
|
||||
return dto.ConvertNutrientToDTO(nutrient), nil
|
||||
}
|
||||
|
||||
// UpdateNutrient 更新营养种类
|
||||
func (s *nutrientServiceImpl) UpdateNutrient(ctx context.Context, id uint32, req *dto.UpdateNutrientRequest) (*dto.NutrientResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateNutrient")
|
||||
|
||||
nutrient, err := s.recipeSvc.UpdateNutrient(serviceCtx, id, req.Name, req.Description)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrNutrientNotFound) {
|
||||
return nil, ErrNutrientNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrNutrientNameConflict) {
|
||||
return nil, ErrNutrientNameConflict
|
||||
}
|
||||
return nil, fmt.Errorf("更新营养种类失败: %w", err)
|
||||
}
|
||||
return dto.ConvertNutrientToDTO(nutrient), nil
|
||||
}
|
||||
|
||||
// DeleteNutrient 删除营养种类
|
||||
func (s *nutrientServiceImpl) DeleteNutrient(ctx context.Context, id uint32) error {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeleteNutrient")
|
||||
err := s.recipeSvc.DeleteNutrient(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrNutrientNotFound) {
|
||||
return ErrNutrientNotFound
|
||||
}
|
||||
return fmt.Errorf("删除营养种类失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNutrient 获取单个营养种类
|
||||
func (s *nutrientServiceImpl) GetNutrient(ctx context.Context, id uint32) (*dto.NutrientResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetNutrient")
|
||||
|
||||
nutrient, err := s.recipeSvc.GetNutrient(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrNutrientNotFound) {
|
||||
return nil, ErrNutrientNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("获取营养种类失败: %w", err)
|
||||
}
|
||||
return dto.ConvertNutrientToDTO(nutrient), nil
|
||||
}
|
||||
|
||||
// ListNutrients 列出营养种类
|
||||
func (s *nutrientServiceImpl) ListNutrients(ctx context.Context, req *dto.ListNutrientRequest) (*dto.ListNutrientResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListNutrients")
|
||||
|
||||
opts := repository.NutrientListOptions{
|
||||
Name: req.Name,
|
||||
RawMaterialName: req.RawMaterialName,
|
||||
OrderBy: req.OrderBy,
|
||||
}
|
||||
nutrients, total, err := s.recipeSvc.ListNutrients(serviceCtx, opts, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取营养种类列表失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertNutrientListToDTO(nutrients, total, req.Page, req.PageSize), nil
|
||||
}
|
||||
122
internal/app/service/pig_age_stage_service.go
Normal file
122
internal/app/service/pig_age_stage_service.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/recipe"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
|
||||
)
|
||||
|
||||
// 定义猪年龄阶段服务特定的错误
|
||||
var (
|
||||
ErrPigAgeStageInUse = errors.New("猪年龄阶段正在被猪类型使用,无法删除")
|
||||
ErrPigAgeStageNotFound = errors.New("猪年龄阶段不存在")
|
||||
)
|
||||
|
||||
// PigAgeStageService 定义了猪年龄阶段相关的应用服务接口
|
||||
type PigAgeStageService interface {
|
||||
CreatePigAgeStage(ctx context.Context, req *dto.CreatePigAgeStageRequest) (*dto.PigAgeStageResponse, error)
|
||||
UpdatePigAgeStage(ctx context.Context, id uint32, req *dto.UpdatePigAgeStageRequest) (*dto.PigAgeStageResponse, error)
|
||||
DeletePigAgeStage(ctx context.Context, id uint32) error
|
||||
GetPigAgeStage(ctx context.Context, id uint32) (*dto.PigAgeStageResponse, error)
|
||||
ListPigAgeStages(ctx context.Context, req *dto.ListPigAgeStageRequest) (*dto.ListPigAgeStageResponse, error)
|
||||
}
|
||||
|
||||
// pigAgeStageServiceImpl 是 PigAgeStageService 接口的实现
|
||||
type pigAgeStageServiceImpl struct {
|
||||
ctx context.Context
|
||||
recipeSvc recipe.Service
|
||||
}
|
||||
|
||||
// NewPigAgeStageService 创建一个新的 PigAgeStageService 实例
|
||||
func NewPigAgeStageService(ctx context.Context, recipeSvc recipe.Service) PigAgeStageService {
|
||||
return &pigAgeStageServiceImpl{
|
||||
ctx: ctx,
|
||||
recipeSvc: recipeSvc,
|
||||
}
|
||||
}
|
||||
|
||||
// CreatePigAgeStage 创建猪年龄阶段
|
||||
func (s *pigAgeStageServiceImpl) CreatePigAgeStage(ctx context.Context, req *dto.CreatePigAgeStageRequest) (*dto.PigAgeStageResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigAgeStage")
|
||||
|
||||
ageStage := &models.PigAgeStage{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.CreatePigAgeStage(serviceCtx, ageStage); err != nil {
|
||||
return nil, fmt.Errorf("创建猪年龄阶段失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigAgeStageToDTO(ageStage), nil
|
||||
}
|
||||
|
||||
// UpdatePigAgeStage 更新猪年龄阶段
|
||||
func (s *pigAgeStageServiceImpl) UpdatePigAgeStage(ctx context.Context, id uint32, req *dto.UpdatePigAgeStageRequest) (*dto.PigAgeStageResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigAgeStage")
|
||||
|
||||
ageStage := &models.PigAgeStage{
|
||||
Model: models.Model{ID: id},
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.UpdatePigAgeStage(serviceCtx, ageStage); err != nil {
|
||||
if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
|
||||
return nil, ErrPigAgeStageNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新猪年龄阶段失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigAgeStageToDTO(ageStage), nil
|
||||
}
|
||||
|
||||
// DeletePigAgeStage 删除猪年龄阶段
|
||||
func (s *pigAgeStageServiceImpl) DeletePigAgeStage(ctx context.Context, id uint32) error {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigAgeStage")
|
||||
err := s.recipeSvc.DeletePigAgeStage(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
|
||||
return ErrPigAgeStageNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrPigAgeStageInUse) {
|
||||
return ErrPigAgeStageInUse
|
||||
}
|
||||
return fmt.Errorf("删除猪年龄阶段失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPigAgeStage 获取单个猪年龄阶段
|
||||
func (s *pigAgeStageServiceImpl) GetPigAgeStage(ctx context.Context, id uint32) (*dto.PigAgeStageResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigAgeStage")
|
||||
|
||||
ageStage, err := s.recipeSvc.GetPigAgeStageByID(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
|
||||
return nil, ErrPigAgeStageNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("获取猪年龄阶段失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigAgeStageToDTO(ageStage), nil
|
||||
}
|
||||
|
||||
// ListPigAgeStages 列出猪年龄阶段
|
||||
func (s *pigAgeStageServiceImpl) ListPigAgeStages(ctx context.Context, req *dto.ListPigAgeStageRequest) (*dto.ListPigAgeStageResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigAgeStages")
|
||||
|
||||
opts := repository.PigAgeStageListOptions{
|
||||
Name: req.Name,
|
||||
OrderBy: req.OrderBy,
|
||||
}
|
||||
ageStages, total, err := s.recipeSvc.ListPigAgeStages(serviceCtx, opts, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取猪年龄阶段列表失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertPigAgeStageListToDTO(ageStages, total, req.Page, req.PageSize), nil
|
||||
}
|
||||
130
internal/app/service/pig_breed_service.go
Normal file
130
internal/app/service/pig_breed_service.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/recipe"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
|
||||
)
|
||||
|
||||
// 定义猪品种服务特定的错误
|
||||
var (
|
||||
ErrPigBreedInUse = errors.New("猪品种正在被猪类型使用,无法删除")
|
||||
ErrPigBreedNotFound = errors.New("猪品种不存在")
|
||||
)
|
||||
|
||||
// PigBreedService 定义了猪品种相关的应用服务接口
|
||||
type PigBreedService interface {
|
||||
CreatePigBreed(ctx context.Context, req *dto.CreatePigBreedRequest) (*dto.PigBreedResponse, error)
|
||||
UpdatePigBreed(ctx context.Context, id uint32, req *dto.UpdatePigBreedRequest) (*dto.PigBreedResponse, error)
|
||||
DeletePigBreed(ctx context.Context, id uint32) error
|
||||
GetPigBreed(ctx context.Context, id uint32) (*dto.PigBreedResponse, error)
|
||||
ListPigBreeds(ctx context.Context, req *dto.ListPigBreedRequest) (*dto.ListPigBreedResponse, error)
|
||||
}
|
||||
|
||||
// pigBreedServiceImpl 是 PigBreedService 接口的实现
|
||||
type pigBreedServiceImpl struct {
|
||||
ctx context.Context
|
||||
recipeSvc recipe.Service
|
||||
}
|
||||
|
||||
// NewPigBreedService 创建一个新的 PigBreedService 实例
|
||||
func NewPigBreedService(ctx context.Context, recipeSvc recipe.Service) PigBreedService {
|
||||
return &pigBreedServiceImpl{
|
||||
ctx: ctx,
|
||||
recipeSvc: recipeSvc,
|
||||
}
|
||||
}
|
||||
|
||||
// CreatePigBreed 创建猪品种
|
||||
func (s *pigBreedServiceImpl) CreatePigBreed(ctx context.Context, req *dto.CreatePigBreedRequest) (*dto.PigBreedResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigBreed")
|
||||
|
||||
breed := &models.PigBreed{
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
ParentInfo: req.ParentInfo,
|
||||
AppearanceFeatures: req.AppearanceFeatures,
|
||||
BreedAdvantages: req.BreedAdvantages,
|
||||
BreedDisadvantages: req.BreedDisadvantages,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.CreatePigBreed(serviceCtx, breed); err != nil {
|
||||
return nil, fmt.Errorf("创建猪品种失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigBreedToDTO(breed), nil
|
||||
}
|
||||
|
||||
// UpdatePigBreed 更新猪品种
|
||||
func (s *pigBreedServiceImpl) UpdatePigBreed(ctx context.Context, id uint32, req *dto.UpdatePigBreedRequest) (*dto.PigBreedResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigBreed")
|
||||
|
||||
breed := &models.PigBreed{
|
||||
Model: models.Model{ID: id},
|
||||
Name: req.Name,
|
||||
Description: req.Description,
|
||||
ParentInfo: req.ParentInfo,
|
||||
AppearanceFeatures: req.AppearanceFeatures,
|
||||
BreedAdvantages: req.BreedAdvantages,
|
||||
BreedDisadvantages: req.BreedDisadvantages,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.UpdatePigBreed(serviceCtx, breed); err != nil {
|
||||
if errors.Is(err, recipe.ErrPigBreedNotFound) {
|
||||
return nil, ErrPigBreedNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新猪品种失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigBreedToDTO(breed), nil
|
||||
}
|
||||
|
||||
// DeletePigBreed 删除猪品种
|
||||
func (s *pigBreedServiceImpl) DeletePigBreed(ctx context.Context, id uint32) error {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigBreed")
|
||||
err := s.recipeSvc.DeletePigBreed(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigBreedNotFound) {
|
||||
return ErrPigBreedNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrPigBreedInUse) {
|
||||
return ErrPigBreedInUse
|
||||
}
|
||||
return fmt.Errorf("删除猪品种失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPigBreed 获取单个猪品种
|
||||
func (s *pigBreedServiceImpl) GetPigBreed(ctx context.Context, id uint32) (*dto.PigBreedResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigBreed")
|
||||
|
||||
breed, err := s.recipeSvc.GetPigBreedByID(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigBreedNotFound) {
|
||||
return nil, ErrPigBreedNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("获取猪品种失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigBreedToDTO(breed), nil
|
||||
}
|
||||
|
||||
// ListPigBreeds 列出猪品种
|
||||
func (s *pigBreedServiceImpl) ListPigBreeds(ctx context.Context, req *dto.ListPigBreedRequest) (*dto.ListPigBreedResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigBreeds")
|
||||
|
||||
opts := repository.PigBreedListOptions{
|
||||
Name: req.Name,
|
||||
OrderBy: req.OrderBy,
|
||||
}
|
||||
breeds, total, err := s.recipeSvc.ListPigBreeds(serviceCtx, opts, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取猪品种列表失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertPigBreedListToDTO(breeds, total, req.Page, req.PageSize), nil
|
||||
}
|
||||
203
internal/app/service/pig_type_service.go
Normal file
203
internal/app/service/pig_type_service.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/recipe"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
|
||||
)
|
||||
|
||||
// 定义猪类型服务特定的错误
|
||||
var (
|
||||
ErrPigTypeNotFound = errors.New("猪类型不存在")
|
||||
)
|
||||
|
||||
// PigTypeService 定义了猪类型相关的应用服务接口
|
||||
type PigTypeService interface {
|
||||
CreatePigType(ctx context.Context, req *dto.CreatePigTypeRequest) (*dto.PigTypeResponse, error)
|
||||
UpdatePigType(ctx context.Context, id uint32, req *dto.UpdatePigTypeRequest) (*dto.PigTypeResponse, error)
|
||||
DeletePigType(ctx context.Context, id uint32) error
|
||||
GetPigType(ctx context.Context, id uint32) (*dto.PigTypeResponse, error)
|
||||
ListPigTypes(ctx context.Context, req *dto.ListPigTypeRequest) (*dto.ListPigTypeResponse, error)
|
||||
UpdatePigTypeNutrientRequirements(ctx context.Context, id uint32, req *dto.UpdatePigTypeNutrientRequirementsRequest) (*dto.PigTypeResponse, error)
|
||||
}
|
||||
|
||||
// pigTypeServiceImpl 是 PigTypeService 接口的实现
|
||||
type pigTypeServiceImpl struct {
|
||||
ctx context.Context
|
||||
recipeSvc recipe.Service
|
||||
}
|
||||
|
||||
// NewPigTypeService 创建一个新的 PigTypeService 实例
|
||||
func NewPigTypeService(ctx context.Context, recipeSvc recipe.Service) PigTypeService {
|
||||
return &pigTypeServiceImpl{
|
||||
ctx: ctx,
|
||||
recipeSvc: recipeSvc,
|
||||
}
|
||||
}
|
||||
|
||||
// CreatePigType 创建猪类型
|
||||
func (s *pigTypeServiceImpl) CreatePigType(ctx context.Context, req *dto.CreatePigTypeRequest) (*dto.PigTypeResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigType")
|
||||
|
||||
pigType := &models.PigType{
|
||||
BreedID: req.BreedID,
|
||||
AgeStageID: req.AgeStageID,
|
||||
Description: req.Description,
|
||||
DailyFeedIntake: req.DailyFeedIntake,
|
||||
DailyGainWeight: req.DailyGainWeight,
|
||||
MinDays: req.MinDays,
|
||||
MaxDays: req.MaxDays,
|
||||
MinWeight: req.MinWeight,
|
||||
MaxWeight: req.MaxWeight,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.CreatePigType(serviceCtx, pigType); err != nil {
|
||||
if errors.Is(err, recipe.ErrPigBreedNotFound) {
|
||||
return nil, ErrPigBreedNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
|
||||
return nil, ErrPigAgeStageNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("创建猪类型失败: %w", err)
|
||||
}
|
||||
// 创建后需要重新获取,以包含关联数据
|
||||
createdPigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, pigType.ID)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) { // 理论上不应该发生,因为刚创建
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("创建猪类型后获取详情失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigTypeToDTO(createdPigType), nil
|
||||
}
|
||||
|
||||
// UpdatePigType 更新猪类型
|
||||
func (s *pigTypeServiceImpl) UpdatePigType(ctx context.Context, id uint32, req *dto.UpdatePigTypeRequest) (*dto.PigTypeResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigType")
|
||||
|
||||
pigType := &models.PigType{
|
||||
Model: models.Model{ID: id},
|
||||
BreedID: req.BreedID,
|
||||
AgeStageID: req.AgeStageID,
|
||||
Description: req.Description,
|
||||
DailyFeedIntake: req.DailyFeedIntake,
|
||||
DailyGainWeight: req.DailyGainWeight,
|
||||
MinDays: req.MinDays,
|
||||
MaxDays: req.MaxDays,
|
||||
MinWeight: req.MinWeight,
|
||||
MaxWeight: req.MaxWeight,
|
||||
}
|
||||
|
||||
if err := s.recipeSvc.UpdatePigType(serviceCtx, pigType); err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) {
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrPigBreedNotFound) {
|
||||
return nil, ErrPigBreedNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
|
||||
return nil, ErrPigAgeStageNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新猪类型失败: %w", err)
|
||||
}
|
||||
// 更新后需要重新获取,以包含关联数据
|
||||
updatedPigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) { // 理论上不应该发生,因为刚更新成功
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新猪类型后获取详情失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigTypeToDTO(updatedPigType), nil
|
||||
}
|
||||
|
||||
// DeletePigType 删除猪类型
|
||||
func (s *pigTypeServiceImpl) DeletePigType(ctx context.Context, id uint32) error {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigType")
|
||||
err := s.recipeSvc.DeletePigType(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) {
|
||||
return ErrPigTypeNotFound
|
||||
}
|
||||
return fmt.Errorf("删除猪类型失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPigType 获取单个猪类型
|
||||
func (s *pigTypeServiceImpl) GetPigType(ctx context.Context, id uint32) (*dto.PigTypeResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigType")
|
||||
|
||||
pigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) {
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("获取猪类型失败: %w", err)
|
||||
}
|
||||
return dto.ConvertPigTypeToDTO(pigType), nil
|
||||
}
|
||||
|
||||
// ListPigTypes 列出猪类型
|
||||
func (s *pigTypeServiceImpl) ListPigTypes(ctx context.Context, req *dto.ListPigTypeRequest) (*dto.ListPigTypeResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigTypes")
|
||||
|
||||
opts := repository.PigTypeListOptions{
|
||||
BreedID: req.BreedID,
|
||||
AgeStageID: req.AgeStageID,
|
||||
BreedName: req.BreedName,
|
||||
AgeStageName: req.AgeStageName,
|
||||
OrderBy: req.OrderBy,
|
||||
}
|
||||
pigTypes, total, err := s.recipeSvc.ListPigTypes(serviceCtx, opts, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取猪类型列表失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertPigTypeListToDTO(pigTypes, total, req.Page, req.PageSize), nil
|
||||
}
|
||||
|
||||
// UpdatePigTypeNutrientRequirements 全量更新猪类型的营养需求
|
||||
func (s *pigTypeServiceImpl) UpdatePigTypeNutrientRequirements(ctx context.Context, id uint32, req *dto.UpdatePigTypeNutrientRequirementsRequest) (*dto.PigTypeResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigTypeNutrientRequirements")
|
||||
|
||||
// 1. 将 DTO 转换为领域模型
|
||||
requirements := make([]models.PigNutrientRequirement, len(req.NutrientRequirements))
|
||||
for i, item := range req.NutrientRequirements {
|
||||
requirements[i] = models.PigNutrientRequirement{
|
||||
PigTypeID: id, // 设置所属的 PigTypeID
|
||||
NutrientID: item.NutrientID,
|
||||
MinRequirement: item.MinRequirement,
|
||||
MaxRequirement: item.MaxRequirement,
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 调用领域服务执行更新命令
|
||||
err := s.recipeSvc.UpdatePigTypeNutrientRequirements(serviceCtx, id, requirements)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) {
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
// 此处可以根据领域层可能返回的其他特定错误进行转换
|
||||
return nil, fmt.Errorf("更新猪类型营养需求失败: %w", err)
|
||||
}
|
||||
|
||||
// 3. 更新成功后,调用查询服务获取最新的猪类型信息
|
||||
updatedPigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrPigTypeNotFound) {
|
||||
// 理论上不应该发生,因为刚更新成功
|
||||
return nil, ErrPigTypeNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新后获取猪类型信息失败: %w", err)
|
||||
}
|
||||
|
||||
// 4. 将领域模型转换为 DTO 并返回
|
||||
return dto.ConvertPigTypeToDTO(updatedPigType), nil
|
||||
}
|
||||
157
internal/app/service/raw_material_service.go
Normal file
157
internal/app/service/raw_material_service.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/recipe"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
|
||||
)
|
||||
|
||||
// 定义原料服务特定的错误
|
||||
var (
|
||||
ErrRawMaterialNameConflict = errors.New("原料名称已存在")
|
||||
ErrRawMaterialNotFound = errors.New("原料不存在")
|
||||
)
|
||||
|
||||
// RawMaterialService 定义了原料相关的应用服务接口
|
||||
type RawMaterialService interface {
|
||||
CreateRawMaterial(ctx context.Context, req *dto.CreateRawMaterialRequest) (*dto.RawMaterialResponse, error)
|
||||
UpdateRawMaterial(ctx context.Context, id uint32, req *dto.UpdateRawMaterialRequest) (*dto.RawMaterialResponse, error)
|
||||
DeleteRawMaterial(ctx context.Context, id uint32) error
|
||||
GetRawMaterial(ctx context.Context, id uint32) (*dto.RawMaterialResponse, error)
|
||||
ListRawMaterials(ctx context.Context, req *dto.ListRawMaterialRequest) (*dto.ListRawMaterialResponse, error)
|
||||
UpdateRawMaterialNutrients(ctx context.Context, id uint32, req *dto.UpdateRawMaterialNutrientsRequest) (*dto.RawMaterialResponse, error)
|
||||
}
|
||||
|
||||
// rawMaterialServiceImpl 是 RawMaterialService 接口的实现
|
||||
type rawMaterialServiceImpl struct {
|
||||
ctx context.Context
|
||||
recipeSvc recipe.Service
|
||||
}
|
||||
|
||||
// NewRawMaterialService 创建一个新的 RawMaterialService 实例
|
||||
func NewRawMaterialService(ctx context.Context, recipeSvc recipe.Service) RawMaterialService {
|
||||
return &rawMaterialServiceImpl{
|
||||
ctx: ctx,
|
||||
recipeSvc: recipeSvc,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateRawMaterial 创建原料
|
||||
func (s *rawMaterialServiceImpl) CreateRawMaterial(ctx context.Context, req *dto.CreateRawMaterialRequest) (*dto.RawMaterialResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreateRawMaterial")
|
||||
|
||||
rawMaterial, err := s.recipeSvc.CreateRawMaterial(serviceCtx, req.Name, req.Description)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNameConflict) {
|
||||
return nil, ErrRawMaterialNameConflict
|
||||
}
|
||||
return nil, fmt.Errorf("创建原料失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertRawMaterialToDTO(rawMaterial), nil
|
||||
}
|
||||
|
||||
// UpdateRawMaterial 更新原料
|
||||
func (s *rawMaterialServiceImpl) UpdateRawMaterial(ctx context.Context, id uint32, req *dto.UpdateRawMaterialRequest) (*dto.RawMaterialResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateRawMaterial")
|
||||
|
||||
rawMaterial, err := s.recipeSvc.UpdateRawMaterial(serviceCtx, id, req.Name, req.Description)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNotFound) {
|
||||
return nil, ErrRawMaterialNotFound
|
||||
}
|
||||
if errors.Is(err, recipe.ErrRawMaterialNameConflict) {
|
||||
return nil, ErrRawMaterialNameConflict
|
||||
}
|
||||
return nil, fmt.Errorf("更新原料失败: %w", err)
|
||||
}
|
||||
return dto.ConvertRawMaterialToDTO(rawMaterial), nil
|
||||
}
|
||||
|
||||
// DeleteRawMaterial 删除原料
|
||||
func (s *rawMaterialServiceImpl) DeleteRawMaterial(ctx context.Context, id uint32) error {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeleteRawMaterial")
|
||||
err := s.recipeSvc.DeleteRawMaterial(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNotFound) {
|
||||
return ErrRawMaterialNotFound
|
||||
}
|
||||
return fmt.Errorf("删除原料失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetRawMaterial 获取单个原料
|
||||
func (s *rawMaterialServiceImpl) GetRawMaterial(ctx context.Context, id uint32) (*dto.RawMaterialResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetRawMaterial")
|
||||
|
||||
rawMaterial, err := s.recipeSvc.GetRawMaterial(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNotFound) {
|
||||
return nil, ErrRawMaterialNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("获取原料失败: %w", err)
|
||||
}
|
||||
return dto.ConvertRawMaterialToDTO(rawMaterial), nil
|
||||
}
|
||||
|
||||
// ListRawMaterials 列出原料
|
||||
func (s *rawMaterialServiceImpl) ListRawMaterials(ctx context.Context, req *dto.ListRawMaterialRequest) (*dto.ListRawMaterialResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListRawMaterials")
|
||||
|
||||
opts := repository.RawMaterialListOptions{
|
||||
Name: req.Name,
|
||||
NutrientName: req.NutrientName,
|
||||
OrderBy: req.OrderBy,
|
||||
}
|
||||
rawMaterials, total, err := s.recipeSvc.ListRawMaterials(serviceCtx, opts, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取原料列表失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertRawMaterialListToDTO(rawMaterials, total, req.Page, req.PageSize), nil
|
||||
}
|
||||
|
||||
// UpdateRawMaterialNutrients 全量更新原料的营养成分
|
||||
func (s *rawMaterialServiceImpl) UpdateRawMaterialNutrients(ctx context.Context, id uint32, req *dto.UpdateRawMaterialNutrientsRequest) (*dto.RawMaterialResponse, error) {
|
||||
serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdateRawMaterialNutrients")
|
||||
|
||||
// 1. 将 DTO 转换为领域模型
|
||||
nutrients := make([]models.RawMaterialNutrient, len(req.Nutrients))
|
||||
for i, item := range req.Nutrients {
|
||||
nutrients[i] = models.RawMaterialNutrient{
|
||||
RawMaterialID: id,
|
||||
NutrientID: item.NutrientID,
|
||||
Value: item.Value,
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 调用领域服务执行更新命令
|
||||
err := s.recipeSvc.UpdateRawMaterialNutrients(serviceCtx, id, nutrients)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNotFound) {
|
||||
return nil, ErrRawMaterialNotFound
|
||||
}
|
||||
// 此处可以根据领域层可能返回的其他特定错误进行转换
|
||||
return nil, fmt.Errorf("更新原料营养成分失败: %w", err)
|
||||
}
|
||||
|
||||
// 3. 更新成功后,调用查询服务获取最新的原料信息
|
||||
updatedRawMaterial, err := s.recipeSvc.GetRawMaterial(serviceCtx, id)
|
||||
if err != nil {
|
||||
if errors.Is(err, recipe.ErrRawMaterialNotFound) {
|
||||
// 理论上不应该发生,因为刚更新成功
|
||||
return nil, ErrRawMaterialNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("更新后获取原料信息失败: %w", err)
|
||||
}
|
||||
|
||||
// 4. 将领域模型转换为 DTO 并返回
|
||||
return dto.ConvertRawMaterialToDTO(updatedRawMaterial), nil
|
||||
}
|
||||
Reference in New Issue
Block a user