package recipe import ( "context" "fmt" "git.huangwc.com/pig/pig-farm-controller/internal/infra/models" "git.huangwc.com/pig/pig-farm-controller/internal/infra/repository" ) // Service 定义了配方与原料领域的核心业务服务接口 // 该接口聚合了所有子领域的服务接口 type Service interface { NutrientService RawMaterialService PigBreedService PigAgeStageService PigTypeService RecipeCoreService RecipeGenerateManager GenerateRecipeWithAllRawMaterials(ctx context.Context, pigTypeID uint32) (*models.Recipe, error) } // recipeServiceImpl 是 Service 的实现,通过组合各个子服务来实现 type recipeServiceImpl struct { ctx context.Context NutrientService RawMaterialService PigBreedService PigAgeStageService PigTypeService RecipeCoreService RecipeGenerateManager } // NewRecipeService 创建一个新的 Service 实例 func NewRecipeService( ctx context.Context, nutrientService NutrientService, rawMaterialService RawMaterialService, pigBreedService PigBreedService, pigAgeStageService PigAgeStageService, pigTypeService PigTypeService, recipeCoreService RecipeCoreService, recipeGenerateManager RecipeGenerateManager, ) Service { return &recipeServiceImpl{ ctx: ctx, NutrientService: nutrientService, RawMaterialService: rawMaterialService, PigBreedService: pigBreedService, PigAgeStageService: pigAgeStageService, PigTypeService: pigTypeService, RecipeCoreService: recipeCoreService, RecipeGenerateManager: recipeGenerateManager, } } // GenerateRecipeWithAllRawMaterials 使用所有已知原料为特定猪类型生成一个新配方。 // pigTypeID: 目标猪类型的ID。 // 返回: 生成的配方对象指针和可能的错误。 func (r *recipeServiceImpl) GenerateRecipeWithAllRawMaterials(ctx context.Context, pigTypeID uint32) (*models.Recipe, error) { // 1. 获取猪只类型信息,确保包含了营养需求 pigType, err := r.GetPigTypeByID(ctx, pigTypeID) if err != nil { return nil, fmt.Errorf("获取猪类型信息失败: %w", err) } // 2. 获取所有原料 // 我们通过传递一个非常大的 pageSize 来获取所有原料,这在大多数情况下是可行的。 // 对于超大规模系统,可能需要考虑分页迭代,但目前这是一个简单有效的策略。 materials, _, err := r.ListRawMaterials(ctx, repository.RawMaterialListOptions{}, 1, 9999) if err != nil { return nil, fmt.Errorf("获取所有原料列表失败: %w", err) } // 3. 调用生成器生成配方 recipe, err := r.GenerateRecipe(ctx, *pigType, materials) if err != nil { return nil, fmt.Errorf("生成配方失败: %w", err) } // 4. 保存新生成的配方到数据库 // CreateRecipe 会处理配方及其成分的保存 if recipe, err = r.CreateRecipe(ctx, recipe); err != nil { return nil, fmt.Errorf("保存生成的配方失败: %w", err) } // 5. 返回创建的配方 (现在它应该已经有了ID) return recipe, nil }