Compare commits
3 Commits
1b5f715dec
...
bc4355cad5
| Author | SHA1 | Date | |
|---|---|---|---|
| bc4355cad5 | |||
| 968d996a9b | |||
| d6e5d89768 |
@@ -260,7 +260,7 @@ func (a *API) setupRoutes() {
|
|||||||
feedGroup.GET("/recipes/:id", a.recipeController.GetRecipe)
|
feedGroup.GET("/recipes/:id", a.recipeController.GetRecipe)
|
||||||
feedGroup.GET("/recipes", a.recipeController.ListRecipes)
|
feedGroup.GET("/recipes", a.recipeController.ListRecipes)
|
||||||
feedGroup.POST("/recipes/generate-from-all-materials/:pig_type_id", a.recipeController.GenerateFromAllMaterials)
|
feedGroup.POST("/recipes/generate-from-all-materials/:pig_type_id", a.recipeController.GenerateFromAllMaterials)
|
||||||
feedGroup.POST("/recipes/generate-prioritized-stock/:pig_type_id", a.recipeController.GenerateFromAllMaterials)
|
feedGroup.POST("/recipes/generate-prioritized-stock/:pig_type_id", a.recipeController.GenerateRecipeWithPrioritizedStockRawMaterials)
|
||||||
}
|
}
|
||||||
logger.Debug("饲料管理相关接口注册成功 (需要认证和审计)")
|
logger.Debug("饲料管理相关接口注册成功 (需要认证和审计)")
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ func (r *recipeServiceImpl) GenerateRecipeWithAllRawMaterials(ctx context.Contex
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4. 丰富配方描述:计算并添加参考价格信息
|
// 4. 丰富配方描述:计算并添加参考价格信息
|
||||||
|
recipe.Name = fmt.Sprintf("%s - 使用所有已知原料", recipe.Name)
|
||||||
|
|
||||||
// 填充 RecipeIngredients 中的 RawMaterial 字段,以便后续计算成本
|
// 填充 RecipeIngredients 中的 RawMaterial 字段,以便后续计算成本
|
||||||
rawMaterialMap := make(map[uint32]models.RawMaterial)
|
rawMaterialMap := make(map[uint32]models.RawMaterial)
|
||||||
@@ -120,7 +121,7 @@ func (r *recipeServiceImpl) GenerateRecipeWithAllRawMaterials(ctx context.Contex
|
|||||||
if recipe, err = r.CreateRecipe(serviceCtx, recipe); err != nil {
|
if recipe, err = r.CreateRecipe(serviceCtx, recipe); err != nil {
|
||||||
return nil, fmt.Errorf("保存生成的配方失败: %w", err)
|
return nil, fmt.Errorf("保存生成的配方失败: %w", err)
|
||||||
}
|
}
|
||||||
logger.Infof("成功生成配方: %+v", recipe)
|
logger.Infof("成功生成配方: 配方名称: %v | 配方简介: %v", recipe.Name, recipe.Description)
|
||||||
|
|
||||||
// 6. 返回创建的配方 (现在它应该已经有了ID)
|
// 6. 返回创建的配方 (现在它应该已经有了ID)
|
||||||
return recipe, nil
|
return recipe, nil
|
||||||
@@ -184,6 +185,8 @@ func (r *recipeServiceImpl) GenerateRecipeWithPrioritizedStockRawMaterials(ctx c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 5. 丰富配方描述:计算并添加参考价格信息
|
// 5. 丰富配方描述:计算并添加参考价格信息
|
||||||
|
recipe.Name = fmt.Sprintf("%s - 优先使用库存已有原料", recipe.Name)
|
||||||
|
|
||||||
// 注意:这里需要使用原始的、未调整价格的原料信息来计算最终的参考价格
|
// 注意:这里需要使用原始的、未调整价格的原料信息来计算最终的参考价格
|
||||||
// rawMaterialMap 从 allOriginalMaterials 构建,确保使用原始价格
|
// rawMaterialMap 从 allOriginalMaterials 构建,确保使用原始价格
|
||||||
rawMaterialMap := make(map[uint32]models.RawMaterial)
|
rawMaterialMap := make(map[uint32]models.RawMaterial)
|
||||||
@@ -201,7 +204,7 @@ func (r *recipeServiceImpl) GenerateRecipeWithPrioritizedStockRawMaterials(ctx c
|
|||||||
}
|
}
|
||||||
|
|
||||||
referencePrice := recipe.CalculateReferencePricePerKilogram() / 100
|
referencePrice := recipe.CalculateReferencePricePerKilogram() / 100
|
||||||
recipe.Description = fmt.Sprintf("%s 计算时预估成本: %.2f元/kg。", recipe.Description, referencePrice)
|
recipe.Description = fmt.Sprintf("使用 %v 种有库存原料和 %v 种无库存原料计算的库存原料优先使用的配方。 计算时预估成本: %.2f元/kg。", len(stockMaterials), len(noStockMaterials), referencePrice)
|
||||||
|
|
||||||
// 如果 totalPercentage 小于 100%,说明填充料被使用,这是符合预期的。
|
// 如果 totalPercentage 小于 100%,说明填充料被使用,这是符合预期的。
|
||||||
// 此时需要在描述中说明需要添加的廉价填充料的百分比。
|
// 此时需要在描述中说明需要添加的廉价填充料的百分比。
|
||||||
@@ -216,7 +219,7 @@ func (r *recipeServiceImpl) GenerateRecipeWithPrioritizedStockRawMaterials(ctx c
|
|||||||
|
|
||||||
return nil, fmt.Errorf("保存生成的配方失败: %w", err)
|
return nil, fmt.Errorf("保存生成的配方失败: %w", err)
|
||||||
}
|
}
|
||||||
logger.Infof("成功生成优先使用库存原料的配方: %+v", recipe)
|
logger.Infof("成功生成优先使用库存原料的配方: 配方名称: %v | 配方简介: %v", recipe.Name, recipe.Description)
|
||||||
|
|
||||||
// 7. 返回创建的配方
|
// 7. 返回创建的配方
|
||||||
return recipe, nil
|
return recipe, nil
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ type RawMaterialListOptions struct {
|
|||||||
NutrientName *string
|
NutrientName *string
|
||||||
MinReferencePrice *float32 // 参考价格最小值
|
MinReferencePrice *float32 // 参考价格最小值
|
||||||
MaxReferencePrice *float32 // 参考价格最大值
|
MaxReferencePrice *float32 // 参考价格最大值
|
||||||
HasStock *bool // 是否只查询有库存的原料
|
HasStock *bool
|
||||||
OrderBy string
|
OrderBy string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,20 +123,27 @@ func (r *gormRawMaterialRepository) ListRawMaterials(ctx context.Context, opts R
|
|||||||
db = db.Where("reference_price <= ?", *opts.MaxReferencePrice)
|
db = db.Where("reference_price <= ?", *opts.MaxReferencePrice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 筛选有库存的原料
|
// 筛选有/无库存的原料
|
||||||
if opts.HasStock != nil && *opts.HasStock {
|
if opts.HasStock != nil {
|
||||||
// 内部子查询:生成带有 rn 的结果集,GORM 会自动为 models.RawMaterialStockLog 添加 deleted_at IS NULL
|
// 内部子查询:生成带有 rn 的结果集,GORM 会自动为 models.RawMaterialStockLog 添加 deleted_at IS NULL
|
||||||
rankedLogsQuery := r.db.Model(&models.RawMaterialStockLog{}).
|
rankedLogsQuery := r.db.Model(&models.RawMaterialStockLog{}).
|
||||||
Select("raw_material_id, after_quantity, ROW_NUMBER() OVER(PARTITION BY raw_material_id ORDER BY happened_at DESC, id DESC) as rn")
|
Select("raw_material_id, after_quantity, ROW_NUMBER() OVER(PARTITION BY raw_material_id ORDER BY happened_at DESC, id DESC) as rn")
|
||||||
|
|
||||||
// 外部子查询:从 ranked_logs 中筛选 rn=1 且 after_quantity > 0 的 raw_material_id
|
// 外部子查询:从 ranked_logs 中筛选 rn=1 的 raw_material_id
|
||||||
// GORM 会将 rankedLogsQuery 作为一个子查询嵌入到 FROM 子句中
|
|
||||||
latestStockLogSubQuery := r.db.Table("(?) as ranked_logs", rankedLogsQuery).
|
latestStockLogSubQuery := r.db.Table("(?) as ranked_logs", rankedLogsQuery).
|
||||||
Select("raw_material_id").
|
Select("raw_material_id").
|
||||||
Where("rn = 1 AND after_quantity > 0")
|
Where("rn = 1").
|
||||||
|
Where("after_quantity > 0")
|
||||||
|
|
||||||
|
if *opts.HasStock {
|
||||||
|
// 筛选有库存的原料 (ID 在有正库存的集合中)
|
||||||
|
db = db.Where("id IN (?)", latestStockLogSubQuery)
|
||||||
|
} else {
|
||||||
|
// 筛选无库存的原料 (ID 不在有正库存的集合中)
|
||||||
|
// 包含了最新库存为0 和 没有库存日志的原料。
|
||||||
|
db = db.Where("id NOT IN (?)", latestStockLogSubQuery)
|
||||||
|
}
|
||||||
|
|
||||||
// 将这个子查询直接应用到主查询的 WHERE id IN (?) 条件中
|
|
||||||
db = db.Where("id IN (?)", latestStockLogSubQuery)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 首先计算总数
|
// 首先计算总数
|
||||||
|
|||||||
Reference in New Issue
Block a user