issue_66 #70
@@ -54,4 +54,5 @@ http://git.huangwc.com/pig/pig-farm-controller/issues/66
|
||||
4. 实现原材料的增删改查和仓库层的原料库存记录表增查
|
||||
5. 定义猪的模型和营养需求模型
|
||||
6. 实现从json读取猪营养需求并写入数据库
|
||||
7. 实现配方领域关于猪模型和营养需求的增删改查
|
||||
7. 实现配方领域关于猪模型和营养需求的增删改查
|
||||
8. 实现配方领域的web接口
|
||||
1793
docs/docs.go
1793
docs/docs.go
File diff suppressed because it is too large
Load Diff
1793
docs/swagger.json
1793
docs/swagger.json
File diff suppressed because it is too large
Load Diff
1111
docs/swagger.yaml
1111
docs/swagger.yaml
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@ import (
|
||||
_ "git.huangwc.com/pig/pig-farm-controller/docs" // 引入 swag 生成的 docs
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/alarm"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/device"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/feed"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/health"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/management"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/monitor"
|
||||
@@ -55,6 +56,7 @@ type API struct {
|
||||
monitorController *monitor.Controller // 数据监控控制器实例
|
||||
healthController *health.Controller // 健康检查控制器实例
|
||||
alarmController *alarm.ThresholdAlarmController // 阈值告警控制器
|
||||
feedController *feed.Controller // 饲料管理控制器实例
|
||||
listenHandler webhook.ListenHandler // 设备上行事件监听器
|
||||
analysisTaskManager *domain_plan.AnalysisPlanTaskManager // 计划触发器管理器实例
|
||||
}
|
||||
@@ -72,6 +74,7 @@ func NewAPI(cfg config.ServerConfig,
|
||||
userService service.UserService,
|
||||
auditService service.AuditService,
|
||||
alarmService service.ThresholdAlarmService,
|
||||
feedManagementService service.FeedManagementService,
|
||||
tokenGenerator token.Generator,
|
||||
listenHandler webhook.ListenHandler,
|
||||
) *API {
|
||||
@@ -111,6 +114,8 @@ func NewAPI(cfg config.ServerConfig,
|
||||
healthController: health.NewController(logs.AddCompName(baseCtx, "HealthController")),
|
||||
// 在 NewAPI 中初始化阈
|
||||
alarmController: alarm.NewThresholdAlarmController(logs.AddCompName(baseCtx, "ThresholdAlarmController"), alarmService),
|
||||
// 在 NewAPI 中初始化饲料管理控制器
|
||||
feedController: feed.NewController(logs.AddCompName(baseCtx, "FeedController"), feedManagementService),
|
||||
}
|
||||
|
||||
api.setupRoutes() // 设置所有路由
|
||||
|
||||
@@ -212,6 +212,46 @@ func (a *API) setupRoutes() {
|
||||
}
|
||||
}
|
||||
logger.Debug("告警相关接口注册成功 (需要认证和审计)")
|
||||
|
||||
// 饲料管理相关路由组
|
||||
feedGroup := authGroup.Group("/feed")
|
||||
{
|
||||
// 营养种类 (Nutrient) 路由
|
||||
feedGroup.POST("/nutrients", a.feedController.CreateNutrient)
|
||||
feedGroup.PUT("/nutrients/:id", a.feedController.UpdateNutrient)
|
||||
feedGroup.DELETE("/nutrients/:id", a.feedController.DeleteNutrient)
|
||||
feedGroup.GET("/nutrients/:id", a.feedController.GetNutrient)
|
||||
feedGroup.GET("/nutrients", a.feedController.ListNutrients)
|
||||
|
||||
// 原料 (RawMaterial) 路由
|
||||
feedGroup.POST("/raw-materials", a.feedController.CreateRawMaterial)
|
||||
feedGroup.PUT("/raw-materials/:id", a.feedController.UpdateRawMaterial)
|
||||
feedGroup.DELETE("/raw-materials/:id", a.feedController.DeleteRawMaterial)
|
||||
feedGroup.GET("/raw-materials/:id", a.feedController.GetRawMaterial)
|
||||
feedGroup.GET("/raw-materials", a.feedController.ListRawMaterials)
|
||||
|
||||
// 猪品种 (PigBreed) 路由
|
||||
feedGroup.POST("/pig-breeds", a.feedController.CreatePigBreed)
|
||||
feedGroup.PUT("/pig-breeds/:id", a.feedController.UpdatePigBreed)
|
||||
feedGroup.DELETE("/pig-breeds/:id", a.feedController.DeletePigBreed)
|
||||
feedGroup.GET("/pig-breeds/:id", a.feedController.GetPigBreed)
|
||||
feedGroup.GET("/pig-breeds", a.feedController.ListPigBreeds)
|
||||
|
||||
// 猪年龄阶段 (PigAgeStage) 路由
|
||||
feedGroup.POST("/pig-age-stages", a.feedController.CreatePigAgeStage)
|
||||
feedGroup.PUT("/pig-age-stages/:id", a.feedController.UpdatePigAgeStage)
|
||||
feedGroup.DELETE("/pig-age-stages/:id", a.feedController.DeletePigAgeStage)
|
||||
feedGroup.GET("/pig-age-stages/:id", a.feedController.GetPigAgeStage)
|
||||
feedGroup.GET("/pig-age-stages", a.feedController.ListPigAgeStages)
|
||||
|
||||
// 猪类型 (PigType) 路由
|
||||
feedGroup.POST("/pig-types", a.feedController.CreatePigType)
|
||||
feedGroup.PUT("/pig-types/:id", a.feedController.UpdatePigType)
|
||||
feedGroup.DELETE("/pig-types/:id", a.feedController.DeletePigType)
|
||||
feedGroup.GET("/pig-types/:id", a.feedController.GetPigType)
|
||||
feedGroup.GET("/pig-types", a.feedController.ListPigTypes)
|
||||
}
|
||||
logger.Debug("饲料管理相关接口注册成功 (需要认证和审计)")
|
||||
}
|
||||
|
||||
logger.Debug("所有接口注册成功")
|
||||
|
||||
875
internal/app/controller/feed/feed_controller.go
Normal file
875
internal/app/controller/feed/feed_controller.go
Normal file
@@ -0,0 +1,875 @@
|
||||
package feed
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// Controller 定义了饲料管理相关的控制器
|
||||
type Controller struct {
|
||||
ctx context.Context
|
||||
feedManagementService service.FeedManagementService
|
||||
}
|
||||
|
||||
// NewController 创建一个新的 Controller 实例
|
||||
func NewController(ctx context.Context, feedManagementService service.FeedManagementService) *Controller {
|
||||
return &Controller{
|
||||
ctx: ctx,
|
||||
feedManagementService: feedManagementService,
|
||||
}
|
||||
}
|
||||
|
||||
// --- 营养种类 (Nutrient) 接口方法实现 ---
|
||||
|
||||
// CreateNutrient godoc
|
||||
// @Summary 创建营养种类
|
||||
// @Description 创建一个新的营养种类。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param nutrient body dto.CreateNutrientRequest true "营养种类信息"
|
||||
// @Success 200 {object} controller.Response{data=dto.NutrientResponse} "业务码为201代表创建成功"
|
||||
// @Router /api/v1/feed/nutrients [post]
|
||||
func (c *Controller) CreateNutrient(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "CreateNutrient")
|
||||
var req dto.CreateNutrientRequest
|
||||
const actionType = "创建营养种类"
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.CreateNutrient(reqCtx, &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层创建营养种类失败: %v", actionType, err)
|
||||
if errors.Is(err, service.ErrNutrientNameConflict) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), actionType, "营养种类名称已存在", req)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建营养种类失败: "+err.Error(), actionType, "服务层创建营养种类失败", req)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 营养种类创建成功, ID: %d", actionType, resp.ID)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "营养种类创建成功", resp, actionType, "营养种类创建成功", resp)
|
||||
}
|
||||
|
||||
// UpdateNutrient godoc
|
||||
// @Summary 更新营养种类
|
||||
// @Description 根据ID更新营养种类信息。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "营养种类ID"
|
||||
// @Param nutrient body dto.UpdateNutrientRequest true "更新后的营养种类信息"
|
||||
// @Success 200 {object} controller.Response{data=dto.NutrientResponse} "业务码为200代表更新成功"
|
||||
// @Router /api/v1/feed/nutrients/{id} [put]
|
||||
func (c *Controller) UpdateNutrient(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "UpdateNutrient")
|
||||
const actionType = "更新营养种类"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 营养种类ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的营养种类ID格式", actionType, "营养种类ID格式错误", idStr)
|
||||
}
|
||||
|
||||
var req dto.UpdateNutrientRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.UpdateNutrient(reqCtx, uint32(id), &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层更新营养种类失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrNutrientNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "营养种类不存在", id)
|
||||
}
|
||||
if errors.Is(err, service.ErrNutrientNameConflict) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), actionType, "营养种类名称已存在", req)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新营养种类失败: "+err.Error(), actionType, "服务层更新营养种类失败", req)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 营养种类更新成功, ID: %d", actionType, resp.ID)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "营养种类更新成功", resp, actionType, "营养种类更新成功", resp)
|
||||
}
|
||||
|
||||
// DeleteNutrient godoc
|
||||
// @Summary 删除营养种类
|
||||
// @Description 根据ID删除营养种类。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "营养种类ID"
|
||||
// @Success 200 {object} controller.Response "业务码为200代表删除成功"
|
||||
// @Router /api/v1/feed/nutrients/{id} [delete]
|
||||
func (c *Controller) DeleteNutrient(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "DeleteNutrient")
|
||||
const actionType = "删除营养种类"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 营养种类ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的营养种类ID格式", actionType, "营养种类ID格式错误", idStr)
|
||||
}
|
||||
|
||||
err = c.feedManagementService.DeleteNutrient(reqCtx, uint32(id))
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层删除营养种类失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrNutrientNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "营养种类不存在", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除营养种类失败: "+err.Error(), actionType, "服务层删除营养种类失败", id)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 营养种类删除成功, ID: %d", actionType, id)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "营养种类删除成功", nil, actionType, "营养种类删除成功", id)
|
||||
}
|
||||
|
||||
// GetNutrient godoc
|
||||
// @Summary 获取营养种类详情
|
||||
// @Description 根据ID获取单个营养种类的详细信息。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "营养种类ID"
|
||||
// @Success 200 {object} controller.Response{data=dto.NutrientResponse} "业务码为200代表成功获取"
|
||||
// @Router /api/v1/feed/nutrients/{id} [get]
|
||||
func (c *Controller) GetNutrient(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "GetNutrient")
|
||||
const actionType = "获取营养种类详情"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 营养种类ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的营养种类ID格式", actionType, "营养种类ID格式错误", idStr)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.GetNutrient(reqCtx, uint32(id))
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层获取营养种类详情失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrNutrientNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "营养种类不存在", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取营养种类详情失败: "+err.Error(), actionType, "服务层获取营养种类详情失败", id)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 获取营养种类详情成功, ID: %d", actionType, id)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取营养种类详情成功", resp, actionType, "获取营养种类详情成功", resp)
|
||||
}
|
||||
|
||||
// ListNutrients godoc
|
||||
// @Summary 获取营养种类列表
|
||||
// @Description 获取所有营养种类的列表,支持分页和过滤。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param query query dto.ListNutrientRequest false "查询参数"
|
||||
// @Success 200 {object} controller.Response{data=dto.ListNutrientResponse} "业务码为200代表成功获取列表"
|
||||
// @Router /api/v1/feed/nutrients [get]
|
||||
func (c *Controller) ListNutrients(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "ListNutrients")
|
||||
const actionType = "获取营养种类列表"
|
||||
var req dto.ListNutrientRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 查询参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的查询参数: "+err.Error(), actionType, "查询参数绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.ListNutrients(reqCtx, &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层获取营养种类列表失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取营养种类列表失败: "+err.Error(), actionType, "服务层获取营养种类列表失败", nil)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 获取营养种类列表成功, 数量: %d", actionType, len(resp.List))
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取营养种类列表成功", resp, actionType, "获取营养种类列表成功", resp)
|
||||
}
|
||||
|
||||
// --- 原料 (RawMaterial) 接口方法实现 ---
|
||||
|
||||
// CreateRawMaterial godoc
|
||||
// @Summary 创建原料
|
||||
// @Description 创建一个新的原料。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param rawMaterial body dto.CreateRawMaterialRequest true "原料信息"
|
||||
// @Success 200 {object} controller.Response{data=dto.RawMaterialResponse} "业务码为201代表创建成功"
|
||||
// @Router /api/v1/feed/raw-materials [post]
|
||||
func (c *Controller) CreateRawMaterial(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "CreateRawMaterial")
|
||||
var req dto.CreateRawMaterialRequest
|
||||
const actionType = "创建原料"
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.CreateRawMaterial(reqCtx, &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层创建原料失败: %v", actionType, err)
|
||||
if errors.Is(err, service.ErrRawMaterialNameConflict) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), actionType, "原料名称已存在", req)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建原料失败: "+err.Error(), actionType, "服务层创建原料失败", req)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 原料创建成功, ID: %d", actionType, resp.ID)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "原料创建成功", resp, actionType, "原料创建成功", resp)
|
||||
}
|
||||
|
||||
// UpdateRawMaterial godoc
|
||||
// @Summary 更新原料
|
||||
// @Description 根据ID更新原料信息。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "原料ID"
|
||||
// @Param rawMaterial body dto.UpdateRawMaterialRequest true "更新后的原料信息"
|
||||
// @Success 200 {object} controller.Response{data=dto.RawMaterialResponse} "业务码为200代表更新成功"
|
||||
// @Router /api/v1/feed/raw-materials/{id} [put]
|
||||
func (c *Controller) UpdateRawMaterial(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "UpdateRawMaterial")
|
||||
const actionType = "更新原料"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 原料ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的原料ID格式", actionType, "原料ID格式错误", idStr)
|
||||
}
|
||||
|
||||
var req dto.UpdateRawMaterialRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.UpdateRawMaterial(reqCtx, uint32(id), &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层更新原料失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrRawMaterialNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "原料不存在", id)
|
||||
}
|
||||
if errors.Is(err, service.ErrRawMaterialNameConflict) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), actionType, "原料名称已存在", req)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新原料失败: "+err.Error(), actionType, "服务层更新原料失败", req)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 原料更新成功, ID: %d", actionType, resp.ID)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "原料更新成功", resp, actionType, "原料更新成功", resp)
|
||||
}
|
||||
|
||||
// DeleteRawMaterial godoc
|
||||
// @Summary 删除原料
|
||||
// @Description 根据ID删除原料。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "原料ID"
|
||||
// @Success 200 {object} controller.Response "业务码为200代表删除成功"
|
||||
// @Router /api/v1/feed/raw-materials/{id} [delete]
|
||||
func (c *Controller) DeleteRawMaterial(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "DeleteRawMaterial")
|
||||
const actionType = "删除原料"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 原料ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的原料ID格式", actionType, "原料ID格式错误", idStr)
|
||||
}
|
||||
|
||||
err = c.feedManagementService.DeleteRawMaterial(reqCtx, uint32(id))
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层删除原料失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrRawMaterialNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "原料不存在", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除原料失败: "+err.Error(), actionType, "服务层删除原料失败", id)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 原料删除成功, ID: %d", actionType, id)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "原料删除成功", nil, actionType, "原料删除成功", id)
|
||||
}
|
||||
|
||||
// GetRawMaterial godoc
|
||||
// @Summary 获取原料详情
|
||||
// @Description 根据ID获取单个原料的详细信息。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "原料ID"
|
||||
// @Success 200 {object} controller.Response{data=dto.RawMaterialResponse} "业务码为200代表成功获取"
|
||||
// @Router /api/v1/feed/raw-materials/{id} [get]
|
||||
func (c *Controller) GetRawMaterial(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "GetRawMaterial")
|
||||
const actionType = "获取原料详情"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 原料ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的原料ID格式", actionType, "原料ID格式错误", idStr)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.GetRawMaterial(reqCtx, uint32(id))
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层获取原料详情失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrRawMaterialNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "原料不存在", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取原料详情失败: "+err.Error(), actionType, "服务层获取原料详情失败", id)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 获取原料详情成功, ID: %d", actionType, id)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取原料详情成功", resp, actionType, "获取原料详情成功", resp)
|
||||
}
|
||||
|
||||
// ListRawMaterials godoc
|
||||
// @Summary 获取原料列表
|
||||
// @Description 获取所有原料的列表,支持分页和过滤。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param query query dto.ListRawMaterialRequest false "查询参数"
|
||||
// @Success 200 {object} controller.Response{data=dto.ListRawMaterialResponse} "业务码为200代表成功获取列表"
|
||||
// @Router /api/v1/feed/raw-materials [get]
|
||||
func (c *Controller) ListRawMaterials(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "ListRawMaterials")
|
||||
const actionType = "获取原料列表"
|
||||
var req dto.ListRawMaterialRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 查询参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的查询参数: "+err.Error(), actionType, "查询参数绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.ListRawMaterials(reqCtx, &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层获取原料列表失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取原料列表失败: "+err.Error(), actionType, "服务层获取原料列表失败", nil)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 获取原料列表成功, 数量: %d", actionType, len(resp.List))
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取原料列表成功", resp, actionType, "获取原料列表成功", resp)
|
||||
}
|
||||
|
||||
// --- 猪品种 (PigBreed) 接口方法实现 ---
|
||||
|
||||
// CreatePigBreed godoc
|
||||
// @Summary 创建猪品种
|
||||
// @Description 创建一个新的猪品种。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param pigBreed body dto.CreatePigBreedRequest true "猪品种信息"
|
||||
// @Success 200 {object} controller.Response{data=dto.PigBreedResponse} "业务码为201代表创建成功"
|
||||
// @Router /api/v1/feed/pig-breeds [post]
|
||||
func (c *Controller) CreatePigBreed(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "CreatePigBreed")
|
||||
var req dto.CreatePigBreedRequest
|
||||
const actionType = "创建猪品种"
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.CreatePigBreed(reqCtx, &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层创建猪品种失败: %v", actionType, err)
|
||||
// 猪品种没有名称冲突的领域错误,这里直接返回内部错误
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪品种失败: "+err.Error(), actionType, "服务层创建猪品种失败", req)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 猪品种创建成功, ID: %d", actionType, resp.ID)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "猪品种创建成功", resp, actionType, "猪品种创建成功", resp)
|
||||
}
|
||||
|
||||
// UpdatePigBreed godoc
|
||||
// @Summary 更新猪品种
|
||||
// @Description 根据ID更新猪品种信息。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "猪品种ID"
|
||||
// @Param pigBreed body dto.UpdatePigBreedRequest true "更新后的猪品种信息"
|
||||
// @Success 200 {object} controller.Response{data=dto.PigBreedResponse} "业务码为200代表更新成功"
|
||||
// @Router /api/v1/feed/pig-breeds/{id} [put]
|
||||
func (c *Controller) UpdatePigBreed(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "UpdatePigBreed")
|
||||
const actionType = "更新猪品种"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 猪品种ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪品种ID格式", actionType, "猪品种ID格式错误", idStr)
|
||||
}
|
||||
|
||||
var req dto.UpdatePigBreedRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.UpdatePigBreed(reqCtx, uint32(id), &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层更新猪品种失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrPigBreedNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "猪品种不存在", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新猪品种失败: "+err.Error(), actionType, "服务层更新猪品种失败", req)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 猪品种更新成功, ID: %d", actionType, resp.ID)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "猪品种更新成功", resp, actionType, "猪品种更新成功", resp)
|
||||
}
|
||||
|
||||
// DeletePigBreed godoc
|
||||
// @Summary 删除猪品种
|
||||
// @Description 根据ID删除猪品种。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "猪品种ID"
|
||||
// @Success 200 {object} controller.Response "业务码为200代表删除成功"
|
||||
// @Router /api/v1/feed/pig-breeds/{id} [delete]
|
||||
func (c *Controller) DeletePigBreed(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "DeletePigBreed")
|
||||
const actionType = "删除猪品种"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 猪品种ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪品种ID格式", actionType, "猪品种ID格式错误", idStr)
|
||||
}
|
||||
|
||||
err = c.feedManagementService.DeletePigBreed(reqCtx, uint32(id))
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层删除猪品种失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrPigBreedNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "猪品种不存在", id)
|
||||
}
|
||||
if errors.Is(err, service.ErrPigBreedInUse) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), actionType, "猪品种正在被使用", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除猪品种失败: "+err.Error(), actionType, "服务层删除猪品种失败", id)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 猪品种删除成功, ID: %d", actionType, id)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "猪品种删除成功", nil, actionType, "猪品种删除成功", id)
|
||||
}
|
||||
|
||||
// GetPigBreed godoc
|
||||
// @Summary 获取猪品种详情
|
||||
// @Description 根据ID获取单个猪品种的详细信息。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "猪品种ID"
|
||||
// @Success 200 {object} controller.Response{data=dto.PigBreedResponse} "业务码为200代表成功获取"
|
||||
// @Router /api/v1/feed/pig-breeds/{id} [get]
|
||||
func (c *Controller) GetPigBreed(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "GetPigBreed")
|
||||
const actionType = "获取猪品种详情"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 猪品种ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪品种ID格式", actionType, "猪品种ID格式错误", idStr)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.GetPigBreed(reqCtx, uint32(id))
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层获取猪品种详情失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrPigBreedNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "猪品种不存在", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪品种详情失败: "+err.Error(), actionType, "服务层获取猪品种详情失败", id)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 获取猪品种详情成功, ID: %d", actionType, id)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取猪品种详情成功", resp, actionType, "获取猪品种详情成功", resp)
|
||||
}
|
||||
|
||||
// ListPigBreeds godoc
|
||||
// @Summary 获取猪品种列表
|
||||
// @Description 获取所有猪品种的列表,支持分页和过滤。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param query query dto.ListPigBreedRequest false "查询参数"
|
||||
// @Success 200 {object} controller.Response{data=dto.ListPigBreedResponse} "业务码为200代表成功获取列表"
|
||||
// @Router /api/v1/feed/pig-breeds [get]
|
||||
func (c *Controller) ListPigBreeds(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "ListPigBreeds")
|
||||
const actionType = "获取猪品种列表"
|
||||
var req dto.ListPigBreedRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 查询参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的查询参数: "+err.Error(), actionType, "查询参数绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.ListPigBreeds(reqCtx, &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层获取猪品种列表失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪品种列表失败: "+err.Error(), actionType, "服务层获取猪品种列表失败", nil)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 获取猪品种列表成功, 数量: %d", actionType, len(resp.List))
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取猪品种列表成功", resp, actionType, "获取猪品种列表成功", resp)
|
||||
}
|
||||
|
||||
// --- 猪年龄阶段 (PigAgeStage) 接口方法实现 ---
|
||||
|
||||
// CreatePigAgeStage godoc
|
||||
// @Summary 创建猪年龄阶段
|
||||
// @Description 创建一个新的猪年龄阶段。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param pigAgeStage body dto.CreatePigAgeStageRequest true "猪年龄阶段信息"
|
||||
// @Success 200 {object} controller.Response{data=dto.PigAgeStageResponse} "业务码为201代表创建成功"
|
||||
// @Router /api/v1/feed/pig-age-stages [post]
|
||||
func (c *Controller) CreatePigAgeStage(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "CreatePigAgeStage")
|
||||
var req dto.CreatePigAgeStageRequest
|
||||
const actionType = "创建猪年龄阶段"
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.CreatePigAgeStage(reqCtx, &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层创建猪年龄阶段失败: %v", actionType, err)
|
||||
// 猪年龄阶段没有名称冲突的领域错误,这里直接返回内部错误
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪年龄阶段失败: "+err.Error(), actionType, "服务层创建猪年龄阶段失败", req)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 猪年龄阶段创建成功, ID: %d", actionType, resp.ID)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "猪年龄阶段创建成功", resp, actionType, "猪年龄阶段创建成功", resp)
|
||||
}
|
||||
|
||||
// UpdatePigAgeStage godoc
|
||||
// @Summary 更新猪年龄阶段
|
||||
// @Description 根据ID更新猪年龄阶段信息。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "猪年龄阶段ID"
|
||||
// @Param pigAgeStage body dto.UpdatePigAgeStageRequest true "更新后的猪年龄阶段信息"
|
||||
// @Success 200 {object} controller.Response{data=dto.PigAgeStageResponse} "业务码为200代表更新成功"
|
||||
// @Router /api/v1/feed/pig-age-stages/{id} [put]
|
||||
func (c *Controller) UpdatePigAgeStage(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "UpdatePigAgeStage")
|
||||
const actionType = "更新猪年龄阶段"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 猪年龄阶段ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪年龄阶段ID格式", actionType, "猪年龄阶段ID格式错误", idStr)
|
||||
}
|
||||
|
||||
var req dto.UpdatePigAgeStageRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.UpdatePigAgeStage(reqCtx, uint32(id), &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层更新猪年龄阶段失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrPigAgeStageNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "猪年龄阶段不存在", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新猪年龄阶段失败: "+err.Error(), actionType, "服务层更新猪年龄阶段失败", req)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 猪年龄阶段更新成功, ID: %d", actionType, resp.ID)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "猪年龄阶段更新成功", resp, actionType, "猪年龄阶段更新成功", resp)
|
||||
}
|
||||
|
||||
// DeletePigAgeStage godoc
|
||||
// @Summary 删除猪年龄阶段
|
||||
// @Description 根据ID删除猪年龄阶段。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "猪年龄阶段ID"
|
||||
// @Success 200 {object} controller.Response "业务码为200代表删除成功"
|
||||
// @Router /api/v1/feed/pig-age-stages/{id} [delete]
|
||||
func (c *Controller) DeletePigAgeStage(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "DeletePigAgeStage")
|
||||
const actionType = "删除猪年龄阶段"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 猪年龄阶段ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪年龄阶段ID格式", actionType, "猪年龄阶段ID格式错误", idStr)
|
||||
}
|
||||
|
||||
err = c.feedManagementService.DeletePigAgeStage(reqCtx, uint32(id))
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层删除猪年龄阶段失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrPigAgeStageNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "猪年龄阶段不存在", id)
|
||||
}
|
||||
if errors.Is(err, service.ErrPigAgeStageInUse) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), actionType, "猪年龄阶段正在被使用", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除猪年龄阶段失败: "+err.Error(), actionType, "服务层删除猪年龄阶段失败", id)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 猪年龄阶段删除成功, ID: %d", actionType, id)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "猪年龄阶段删除成功", nil, actionType, "猪年龄阶段删除成功", id)
|
||||
}
|
||||
|
||||
// GetPigAgeStage godoc
|
||||
// @Summary 获取猪年龄阶段详情
|
||||
// @Description 根据ID获取单个猪年龄阶段的详细信息。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "猪年龄阶段ID"
|
||||
// @Success 200 {object} controller.Response{data=dto.PigAgeStageResponse} "业务码为200代表成功获取"
|
||||
// @Router /api/v1/feed/pig-age-stages/{id} [get]
|
||||
func (c *Controller) GetPigAgeStage(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "GetPigAgeStage")
|
||||
const actionType = "获取猪年龄阶段详情"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 猪年龄阶段ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪年龄阶段ID格式", actionType, "猪年龄阶段ID格式错误", idStr)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.GetPigAgeStage(reqCtx, uint32(id))
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层获取猪年龄阶段详情失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrPigAgeStageNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "猪年龄阶段不存在", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪年龄阶段详情失败: "+err.Error(), actionType, "服务层获取猪年龄阶段详情失败", id)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 获取猪年龄阶段详情成功, ID: %d", actionType, id)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取猪年龄阶段详情成功", resp, actionType, "获取猪年龄阶段详情成功", resp)
|
||||
}
|
||||
|
||||
// ListPigAgeStages godoc
|
||||
// @Summary 获取猪年龄阶段列表
|
||||
// @Description 获取所有猪年龄阶段的列表,支持分页和过滤。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param query query dto.ListPigAgeStageRequest false "查询参数"
|
||||
// @Success 200 {object} controller.Response{data=dto.ListPigAgeStageResponse} "业务码为200代表成功获取列表"
|
||||
// @Router /api/v1/feed/pig-age-stages [get]
|
||||
func (c *Controller) ListPigAgeStages(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "ListPigAgeStages")
|
||||
const actionType = "获取猪年龄阶段列表"
|
||||
var req dto.ListPigAgeStageRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 查询参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的查询参数: "+err.Error(), actionType, "查询参数绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.ListPigAgeStages(reqCtx, &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层获取猪年龄阶段列表失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪年龄阶段列表失败: "+err.Error(), actionType, "服务层获取猪年龄阶段列表失败", nil)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 获取猪年龄阶段列表成功, 数量: %d", actionType, len(resp.List))
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取猪年龄阶段列表成功", resp, actionType, "获取猪年龄阶段列表成功", resp)
|
||||
}
|
||||
|
||||
// --- 猪类型 (PigType) 接口方法实现 ---
|
||||
|
||||
// CreatePigType godoc
|
||||
// @Summary 创建猪类型
|
||||
// @Description 创建一个新的猪类型。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param pigType body dto.CreatePigTypeRequest true "猪类型信息"
|
||||
// @Success 200 {object} controller.Response{data=dto.PigTypeResponse} "业务码为201代表创建成功"
|
||||
// @Router /api/v1/feed/pig-types [post]
|
||||
func (c *Controller) CreatePigType(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "CreatePigType")
|
||||
var req dto.CreatePigTypeRequest
|
||||
const actionType = "创建猪类型"
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.CreatePigType(reqCtx, &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层创建猪类型失败: %v", actionType, err)
|
||||
if errors.Is(err, service.ErrPigBreedNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "关联猪品种不存在", req)
|
||||
}
|
||||
if errors.Is(err, service.ErrPigAgeStageNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "关联猪年龄阶段不存在", req)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪类型失败: "+err.Error(), actionType, "服务层创建猪类型失败", req)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 猪类型创建成功, ID: %d", actionType, resp.ID)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "猪类型创建成功", resp, actionType, "猪类型创建成功", resp)
|
||||
}
|
||||
|
||||
// UpdatePigType godoc
|
||||
// @Summary 更新猪类型
|
||||
// @Description 根据ID更新猪类型信息。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "猪类型ID"
|
||||
// @Param pigType body dto.UpdatePigTypeRequest true "更新后的猪类型信息"
|
||||
// @Success 200 {object} controller.Response{data=dto.PigTypeResponse} "业务码为200代表更新成功"
|
||||
// @Router /api/v1/feed/pig-types/{id} [put]
|
||||
func (c *Controller) UpdatePigType(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "UpdatePigType")
|
||||
const actionType = "更新猪类型"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 猪类型ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪类型ID格式", actionType, "猪类型ID格式错误", idStr)
|
||||
}
|
||||
|
||||
var req dto.UpdatePigTypeRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.UpdatePigType(reqCtx, uint32(id), &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层更新猪类型失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrPigTypeNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "猪类型不存在", id)
|
||||
}
|
||||
if errors.Is(err, service.ErrPigBreedNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "关联猪品种不存在", req)
|
||||
}
|
||||
if errors.Is(err, service.ErrPigAgeStageNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "关联猪年龄阶段不存在", req)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新猪类型失败: "+err.Error(), actionType, "服务层更新猪类型失败", req)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 猪类型更新成功, ID: %d", actionType, resp.ID)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "猪类型更新成功", resp, actionType, "猪类型更新成功", resp)
|
||||
}
|
||||
|
||||
// DeletePigType godoc
|
||||
// @Summary 删除猪类型
|
||||
// @Description 根据ID删除猪类型。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "猪类型ID"
|
||||
// @Success 200 {object} controller.Response "业务码为200代表删除成功"
|
||||
// @Router /api/v1/feed/pig-types/{id} [delete]
|
||||
func (c *Controller) DeletePigType(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "DeletePigType")
|
||||
const actionType = "删除猪类型"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 猪类型ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪类型ID格式", actionType, "猪类型ID格式错误", idStr)
|
||||
}
|
||||
|
||||
err = c.feedManagementService.DeletePigType(reqCtx, uint32(id))
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层删除猪类型失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrPigTypeNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "猪类型不存在", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除猪类型失败: "+err.Error(), actionType, "服务层删除猪类型失败", id)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 猪类型删除成功, ID: %d", actionType, id)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "猪类型删除成功", nil, actionType, "猪类型删除成功", id)
|
||||
}
|
||||
|
||||
// GetPigType godoc
|
||||
// @Summary 获取猪类型详情
|
||||
// @Description 根据ID获取单个猪类型的详细信息。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param id path int true "猪类型ID"
|
||||
// @Success 200 {object} controller.Response{data=dto.PigTypeResponse} "业务码为200代表成功获取"
|
||||
// @Router /api/v1/feed/pig-types/{id} [get]
|
||||
func (c *Controller) GetPigType(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "GetPigType")
|
||||
const actionType = "获取猪类型详情"
|
||||
idStr := ctx.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 猪类型ID格式错误: %v, ID: %s", actionType, err, idStr)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的猪类型ID格式", actionType, "猪类型ID格式错误", idStr)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.GetPigType(reqCtx, uint32(id))
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层获取猪类型详情失败: %v, ID: %d", actionType, err, id)
|
||||
if errors.Is(err, service.ErrPigTypeNotFound) {
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "猪类型不存在", id)
|
||||
}
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪类型详情失败: "+err.Error(), actionType, "服务层获取猪类型详情失败", id)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 获取猪类型详情成功, ID: %d", actionType, id)
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取猪类型详情成功", resp, actionType, "获取猪类型详情成功", resp)
|
||||
}
|
||||
|
||||
// ListPigTypes godoc
|
||||
// @Summary 获取猪类型列表
|
||||
// @Description 获取所有猪类型的列表,支持分页和过滤。
|
||||
// @Tags 饲料管理
|
||||
// @Security BearerAuth
|
||||
// @Produce json
|
||||
// @Param query query dto.ListPigTypeRequest false "查询参数"
|
||||
// @Success 200 {object} controller.Response{data=dto.ListPigTypeResponse} "业务码为200代表成功获取列表"
|
||||
// @Router /api/v1/feed/pig-types [get]
|
||||
func (c *Controller) ListPigTypes(ctx echo.Context) error {
|
||||
reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "ListPigTypes")
|
||||
const actionType = "获取猪类型列表"
|
||||
var req dto.ListPigTypeRequest
|
||||
if err := ctx.Bind(&req); err != nil {
|
||||
logger.Errorf("%s: 查询参数绑定失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的查询参数: "+err.Error(), actionType, "查询参数绑定失败", req)
|
||||
}
|
||||
|
||||
resp, err := c.feedManagementService.ListPigTypes(reqCtx, &req)
|
||||
if err != nil {
|
||||
logger.Errorf("%s: 服务层获取猪类型列表失败: %v", actionType, err)
|
||||
return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪类型列表失败: "+err.Error(), actionType, "服务层获取猪类型列表失败", nil)
|
||||
}
|
||||
|
||||
logger.Infof("%s: 获取猪类型列表成功, 数量: %d", actionType, len(resp.List))
|
||||
return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取猪类型列表成功", resp, actionType, "获取猪类型列表成功", resp)
|
||||
}
|
||||
202
internal/app/dto/feed_converter.go
Normal file
202
internal/app/dto/feed_converter.go
Normal file
@@ -0,0 +1,202 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
||||
)
|
||||
|
||||
// ConvertNutrientToDTO 将 models.Nutrient 转换为 NutrientResponse DTO
|
||||
func ConvertNutrientToDTO(nutrient *models.Nutrient) *NutrientResponse {
|
||||
if nutrient == nil {
|
||||
return nil
|
||||
}
|
||||
return &NutrientResponse{
|
||||
ID: nutrient.ID,
|
||||
CreatedAt: nutrient.CreatedAt,
|
||||
UpdatedAt: nutrient.UpdatedAt,
|
||||
Name: nutrient.Name,
|
||||
Description: nutrient.Description,
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertNutrientListToDTO 将 []models.Nutrient 转换为 ListNutrientResponse DTO
|
||||
func ConvertNutrientListToDTO(nutrients []models.Nutrient, total int64, page, pageSize int) *ListNutrientResponse {
|
||||
nutrientDTOs := make([]NutrientResponse, len(nutrients))
|
||||
for i, n := range nutrients {
|
||||
nutrientDTOs[i] = *ConvertNutrientToDTO(&n)
|
||||
}
|
||||
|
||||
return &ListNutrientResponse{
|
||||
List: nutrientDTOs,
|
||||
Pagination: PaginationDTO{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
Total: total,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertRawMaterialToDTO 将 models.RawMaterial 转换为 RawMaterialResponse DTO
|
||||
func ConvertRawMaterialToDTO(rm *models.RawMaterial) *RawMaterialResponse {
|
||||
if rm == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
rawMaterialNutrientDTOs := make([]RawMaterialNutrientDTO, len(rm.RawMaterialNutrients))
|
||||
for i, rmn := range rm.RawMaterialNutrients {
|
||||
rawMaterialNutrientDTOs[i] = RawMaterialNutrientDTO{
|
||||
ID: rmn.ID,
|
||||
CreatedAt: rmn.CreatedAt,
|
||||
UpdatedAt: rmn.UpdatedAt,
|
||||
NutrientID: rmn.NutrientID,
|
||||
Nutrient: rmn.Nutrient.Name, // 假设 Nutrient 已经被预加载
|
||||
Value: rmn.Value,
|
||||
}
|
||||
}
|
||||
|
||||
return &RawMaterialResponse{
|
||||
ID: rm.ID,
|
||||
CreatedAt: rm.CreatedAt,
|
||||
UpdatedAt: rm.UpdatedAt,
|
||||
Name: rm.Name,
|
||||
Description: rm.Description,
|
||||
RawMaterialNutrients: rawMaterialNutrientDTOs,
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertRawMaterialListToDTO 将 []models.RawMaterial 转换为 ListRawMaterialResponse DTO
|
||||
func ConvertRawMaterialListToDTO(rawMaterials []models.RawMaterial, total int64, page, pageSize int) *ListRawMaterialResponse {
|
||||
rawMaterialDTOs := make([]RawMaterialResponse, len(rawMaterials))
|
||||
for i, rm := range rawMaterials {
|
||||
rawMaterialDTOs[i] = *ConvertRawMaterialToDTO(&rm)
|
||||
}
|
||||
|
||||
return &ListRawMaterialResponse{
|
||||
List: rawMaterialDTOs,
|
||||
Pagination: PaginationDTO{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
Total: total,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertPigBreedToDTO 将 models.PigBreed 转换为 PigBreedResponse DTO
|
||||
func ConvertPigBreedToDTO(breed *models.PigBreed) *PigBreedResponse {
|
||||
if breed == nil {
|
||||
return nil
|
||||
}
|
||||
return &PigBreedResponse{
|
||||
ID: breed.ID,
|
||||
CreatedAt: breed.CreatedAt,
|
||||
UpdatedAt: breed.UpdatedAt,
|
||||
Name: breed.Name,
|
||||
Description: breed.Description,
|
||||
ParentInfo: breed.ParentInfo,
|
||||
AppearanceFeatures: breed.AppearanceFeatures,
|
||||
BreedAdvantages: breed.BreedAdvantages,
|
||||
BreedDisadvantages: breed.BreedDisadvantages,
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertPigBreedListToDTO 将 []models.PigBreed 转换为 ListPigBreedResponse DTO
|
||||
func ConvertPigBreedListToDTO(breeds []models.PigBreed, total int64, page, pageSize int) *ListPigBreedResponse {
|
||||
breedDTOs := make([]PigBreedResponse, len(breeds))
|
||||
for i, b := range breeds {
|
||||
breedDTOs[i] = *ConvertPigBreedToDTO(&b)
|
||||
}
|
||||
|
||||
return &ListPigBreedResponse{
|
||||
List: breedDTOs,
|
||||
Pagination: PaginationDTO{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
Total: total,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertPigAgeStageToDTO 将 models.PigAgeStage 转换为 PigAgeStageResponse DTO
|
||||
func ConvertPigAgeStageToDTO(ageStage *models.PigAgeStage) *PigAgeStageResponse {
|
||||
if ageStage == nil {
|
||||
return nil
|
||||
}
|
||||
return &PigAgeStageResponse{
|
||||
ID: ageStage.ID,
|
||||
CreatedAt: ageStage.CreatedAt,
|
||||
UpdatedAt: ageStage.UpdatedAt,
|
||||
Name: ageStage.Name,
|
||||
Description: ageStage.Description,
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertPigAgeStageListToDTO 将 []models.PigAgeStage 转换为 ListPigAgeStageResponse DTO
|
||||
func ConvertPigAgeStageListToDTO(ageStages []models.PigAgeStage, total int64, page, pageSize int) *ListPigAgeStageResponse {
|
||||
ageStageDTOs := make([]PigAgeStageResponse, len(ageStages))
|
||||
for i, as := range ageStages {
|
||||
ageStageDTOs[i] = *ConvertPigAgeStageToDTO(&as)
|
||||
}
|
||||
|
||||
return &ListPigAgeStageResponse{
|
||||
List: ageStageDTOs,
|
||||
Pagination: PaginationDTO{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
Total: total,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertPigTypeToDTO 将 models.PigType 转换为 PigTypeResponse DTO
|
||||
func ConvertPigTypeToDTO(pt *models.PigType) *PigTypeResponse {
|
||||
if pt == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
pigNutrientRequirementDTOs := make([]PigNutrientRequirementDTO, len(pt.PigNutrientRequirements))
|
||||
for i, pnr := range pt.PigNutrientRequirements {
|
||||
pigNutrientRequirementDTOs[i] = PigNutrientRequirementDTO{
|
||||
ID: pnr.ID,
|
||||
CreatedAt: pnr.CreatedAt,
|
||||
UpdatedAt: pnr.UpdatedAt,
|
||||
NutrientID: pnr.NutrientID,
|
||||
NutrientName: pnr.Nutrient.Name, // 假设 Nutrient 已经被预加载
|
||||
MinRequirement: pnr.MinRequirement,
|
||||
MaxRequirement: pnr.MaxRequirement,
|
||||
}
|
||||
}
|
||||
|
||||
return &PigTypeResponse{
|
||||
ID: pt.ID,
|
||||
CreatedAt: pt.CreatedAt,
|
||||
UpdatedAt: pt.UpdatedAt,
|
||||
BreedID: pt.BreedID,
|
||||
BreedName: pt.Breed.Name, // 假设 Breed 已经被预加载
|
||||
AgeStageID: pt.AgeStageID,
|
||||
AgeStageName: pt.AgeStage.Name, // 假设 AgeStage 已经被预加载
|
||||
Description: pt.Description,
|
||||
DailyFeedIntake: pt.DailyFeedIntake,
|
||||
DailyGainWeight: pt.DailyGainWeight,
|
||||
MinDays: pt.MinDays,
|
||||
MaxDays: pt.MaxDays,
|
||||
MinWeight: pt.MinWeight,
|
||||
MaxWeight: pt.MaxWeight,
|
||||
PigNutrientRequirements: pigNutrientRequirementDTOs,
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertPigTypeListToDTO 将 []models.PigType 转换为 ListPigTypeResponse DTO
|
||||
func ConvertPigTypeListToDTO(pigTypes []models.PigType, total int64, page, pageSize int) *ListPigTypeResponse {
|
||||
pigTypeDTOs := make([]PigTypeResponse, len(pigTypes))
|
||||
for i, pt := range pigTypes {
|
||||
pigTypeDTOs[i] = *ConvertPigTypeToDTO(&pt)
|
||||
}
|
||||
|
||||
return &ListPigTypeResponse{
|
||||
List: pigTypeDTOs,
|
||||
Pagination: PaginationDTO{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
Total: total,
|
||||
},
|
||||
}
|
||||
}
|
||||
261
internal/app/dto/feed_dto.go
Normal file
261
internal/app/dto/feed_dto.go
Normal file
@@ -0,0 +1,261 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// =============================================================================================================
|
||||
// 营养种类 (Nutrient) 相关 DTO
|
||||
// =============================================================================================================
|
||||
|
||||
// CreateNutrientRequest 创建营养种类的请求体
|
||||
type CreateNutrientRequest struct {
|
||||
Name string `json:"name" validate:"required,max=100"` // 营养素名称
|
||||
Description string `json:"description" validate:"max=255"` // 描述
|
||||
}
|
||||
|
||||
// UpdateNutrientRequest 更新营养种类的请求体
|
||||
type UpdateNutrientRequest struct {
|
||||
Name string `json:"name" validate:"required,max=100"` // 营养素名称
|
||||
Description string `json:"description" validate:"max=255"` // 描述
|
||||
}
|
||||
|
||||
// NutrientResponse 营养种类响应体
|
||||
type NutrientResponse struct {
|
||||
ID uint32 `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// ListNutrientRequest 定义了获取营养种类列表的请求参数
|
||||
type ListNutrientRequest struct {
|
||||
Page int `json:"page" query:"page"` // 页码
|
||||
PageSize int `json:"page_size" query:"page_size"` // 每页数量
|
||||
Name *string `json:"name" query:"name"` // 按名称模糊查询
|
||||
OrderBy string `json:"order_by" query:"order_by"` // 排序字段,例如 "id DESC"
|
||||
}
|
||||
|
||||
// ListNutrientResponse 是获取营养种类列表的响应结构
|
||||
type ListNutrientResponse struct {
|
||||
List []NutrientResponse `json:"list"`
|
||||
Pagination PaginationDTO `json:"pagination"`
|
||||
}
|
||||
|
||||
// =============================================================================================================
|
||||
// 原料 (RawMaterial) 相关 DTO
|
||||
// =============================================================================================================
|
||||
|
||||
// CreateRawMaterialRequest 创建原料的请求体
|
||||
type CreateRawMaterialRequest struct {
|
||||
Name string `json:"name" validate:"required,max=100"` // 原料名称
|
||||
Description string `json:"description" validate:"max=255"` // 描述
|
||||
}
|
||||
|
||||
// UpdateRawMaterialRequest 更新原料的请求体
|
||||
type UpdateRawMaterialRequest struct {
|
||||
Name string `json:"name" validate:"required,max=100"` // 原料名称
|
||||
Description string `json:"description" validate:"max=255"` // 描述
|
||||
}
|
||||
|
||||
// RawMaterialNutrientDTO 原料营养素响应体
|
||||
type RawMaterialNutrientDTO struct {
|
||||
ID uint32 `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
NutrientID uint32 `json:"nutrient_id"`
|
||||
Nutrient string `json:"nutrient_name"` // 营养素名称
|
||||
Value float32 `json:"value"` // 营养价值含量
|
||||
}
|
||||
|
||||
// RawMaterialResponse 原料响应体
|
||||
type RawMaterialResponse struct {
|
||||
ID uint32 `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
RawMaterialNutrients []RawMaterialNutrientDTO `json:"raw_material_nutrients"` // 关联的营养素信息
|
||||
}
|
||||
|
||||
// ListRawMaterialRequest 定义了获取原料列表的请求参数
|
||||
type ListRawMaterialRequest struct {
|
||||
Page int `json:"page" query:"page"` // 页码
|
||||
PageSize int `json:"page_size" query:"page_size"` // 每页数量
|
||||
Name *string `json:"name" query:"name"` // 按名称模糊查询
|
||||
OrderBy string `json:"order_by" query:"order_by"` // 排序字段,例如 "id DESC"
|
||||
}
|
||||
|
||||
// ListRawMaterialResponse 是获取原料列表的响应结构
|
||||
type ListRawMaterialResponse struct {
|
||||
List []RawMaterialResponse `json:"list"`
|
||||
Pagination PaginationDTO `json:"pagination"`
|
||||
}
|
||||
|
||||
// =============================================================================================================
|
||||
// 猪品种 (PigBreed) 相关 DTO
|
||||
// =============================================================================================================
|
||||
|
||||
// CreatePigBreedRequest 创建猪品种的请求体
|
||||
type CreatePigBreedRequest struct {
|
||||
Name string `json:"name" validate:"required,max=50"` // 品种名称
|
||||
Description string `json:"description"` // 其他描述
|
||||
ParentInfo string `json:"parent_info"` // 父母信息
|
||||
AppearanceFeatures string `json:"appearance_features"` // 外貌特征
|
||||
BreedAdvantages string `json:"breed_advantages"` // 品种优点
|
||||
BreedDisadvantages string `json:"breed_disadvantages"` // 品种缺点
|
||||
}
|
||||
|
||||
// UpdatePigBreedRequest 更新猪品种的请求体
|
||||
type UpdatePigBreedRequest struct {
|
||||
Name string `json:"name" validate:"required,max=50"` // 品种名称
|
||||
Description string `json:"description"` // 其他描述
|
||||
ParentInfo string `json:"parent_info"` // 父母信息
|
||||
AppearanceFeatures string `json:"appearance_features"` // 外貌特征
|
||||
BreedAdvantages string `json:"breed_advantages"` // 品种优点
|
||||
BreedDisadvantages string `json:"breed_disadvantages"` // 品种缺点
|
||||
}
|
||||
|
||||
// PigBreedResponse 猪品种响应体
|
||||
type PigBreedResponse struct {
|
||||
ID uint32 `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
ParentInfo string `json:"parent_info"`
|
||||
AppearanceFeatures string `json:"appearance_features"`
|
||||
BreedAdvantages string `json:"breed_advantages"`
|
||||
BreedDisadvantages string `json:"breed_disadvantages"`
|
||||
}
|
||||
|
||||
// ListPigBreedRequest 定义了获取猪品种列表的请求参数
|
||||
type ListPigBreedRequest struct {
|
||||
Page int `json:"page" query:"page"` // 页码
|
||||
PageSize int `json:"page_size" query:"page_size"` // 每页数量
|
||||
Name *string `json:"name" query:"name"` // 按名称模糊查询
|
||||
OrderBy string `json:"order_by" query:"order_by"` // 排序字段,例如 "id DESC"
|
||||
}
|
||||
|
||||
// ListPigBreedResponse 是获取猪品种列表的响应结构
|
||||
type ListPigBreedResponse struct {
|
||||
List []PigBreedResponse `json:"list"`
|
||||
Pagination PaginationDTO `json:"pagination"`
|
||||
}
|
||||
|
||||
// =============================================================================================================
|
||||
// 猪年龄阶段 (PigAgeStage) 相关 DTO
|
||||
// =============================================================================================================
|
||||
|
||||
// CreatePigAgeStageRequest 创建猪年龄阶段的请求体
|
||||
type CreatePigAgeStageRequest struct {
|
||||
Name string `json:"name" validate:"required,max=50"` // 年龄阶段名称
|
||||
Description string `json:"description" validate:"max=255"` // 阶段描述
|
||||
}
|
||||
|
||||
// UpdatePigAgeStageRequest 更新猪年龄阶段的请求体
|
||||
type UpdatePigAgeStageRequest struct {
|
||||
Name string `json:"name" validate:"required,max=50"` // 年龄阶段名称
|
||||
Description string `json:"description" validate:"max=255"` // 阶段描述
|
||||
}
|
||||
|
||||
// PigAgeStageResponse 猪年龄阶段响应体
|
||||
type PigAgeStageResponse struct {
|
||||
ID uint32 `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// ListPigAgeStageRequest 定义了获取猪年龄阶段列表的请求参数
|
||||
type ListPigAgeStageRequest struct {
|
||||
Page int `json:"page" query:"page"` // 页码
|
||||
PageSize int `json:"page_size" query:"page_size"` // 每页数量
|
||||
Name *string `json:"name" query:"name"` // 按名称模糊查询
|
||||
OrderBy string `json:"order_by" query:"order_by"` // 排序字段,例如 "id DESC"
|
||||
}
|
||||
|
||||
// ListPigAgeStageResponse 是获取猪年龄阶段列表的响应结构
|
||||
type ListPigAgeStageResponse struct {
|
||||
List []PigAgeStageResponse `json:"list"`
|
||||
Pagination PaginationDTO `json:"pagination"`
|
||||
}
|
||||
|
||||
// =============================================================================================================
|
||||
// 猪类型 (PigType) 相关 DTO
|
||||
// =============================================================================================================
|
||||
|
||||
// CreatePigTypeRequest 创建猪类型的请求体
|
||||
type CreatePigTypeRequest struct {
|
||||
BreedID uint32 `json:"breed_id" validate:"required"` // 关联的猪品种ID
|
||||
AgeStageID uint32 `json:"age_stage_id" validate:"required"` // 关联的猪年龄阶段ID
|
||||
Description string `json:"description" validate:"max=255"` // 该猪类型的描述或特点
|
||||
DailyFeedIntake float32 `json:"daily_feed_intake"` // 理论日均食量 (g/天)
|
||||
DailyGainWeight float32 `json:"daily_gain_weight"` // 理论日增重 (g/天)
|
||||
MinDays uint32 `json:"min_days"` // 该猪类型在该年龄阶段的最小日龄
|
||||
MaxDays uint32 `json:"max_days"` // 该猪类型在该年龄阶段的最大日龄
|
||||
MinWeight float32 `json:"min_weight"` // 该猪类型在该年龄阶段的最小体重 (g)
|
||||
MaxWeight float32 `json:"max_weight"` // 该猪类型在该年龄阶段的最大体重 (g)
|
||||
}
|
||||
|
||||
// UpdatePigTypeRequest 更新猪类型的请求体
|
||||
type UpdatePigTypeRequest struct {
|
||||
BreedID uint32 `json:"breed_id" validate:"required"` // 关联的猪品种ID
|
||||
AgeStageID uint32 `json:"age_stage_id" validate:"required"` // 关联的猪年龄阶段ID
|
||||
Description string `json:"description" validate:"max=255"` // 该猪类型的描述或特点
|
||||
DailyFeedIntake float32 `json:"daily_feed_intake"` // 理论日均食量 (g/天)
|
||||
DailyGainWeight float32 `json:"daily_gain_weight"` // 理论日增重 (g/天)
|
||||
MinDays uint32 `json:"min_days"` // 该猪类型在该年龄阶段的最小日龄
|
||||
MaxDays uint32 `json:"max_days"` // 该猪类型在该年龄阶段的最大日龄
|
||||
MinWeight float32 `json:"min_weight"` // 该猪类型在该年龄阶段的最小体重 (g)
|
||||
MaxWeight float32 `json:"max_weight"` // 该猪类型在该年龄阶段的最大体重 (g)
|
||||
}
|
||||
|
||||
// PigNutrientRequirementDTO 猪营养需求响应体
|
||||
type PigNutrientRequirementDTO struct {
|
||||
ID uint32 `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
NutrientID uint32 `json:"nutrient_id"`
|
||||
NutrientName string `json:"nutrient_name"` // 营养素名称
|
||||
MinRequirement float32 `json:"min_requirement"` // 最低营养需求量
|
||||
MaxRequirement float32 `json:"max_requirement"` // 最高营养需求量
|
||||
}
|
||||
|
||||
// PigTypeResponse 猪类型响应体
|
||||
type PigTypeResponse struct {
|
||||
ID uint32 `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
BreedID uint32 `json:"breed_id"`
|
||||
BreedName string `json:"breed_name"` // 猪品种名称
|
||||
AgeStageID uint32 `json:"age_stage_id"`
|
||||
AgeStageName string `json:"age_stage_name"` // 猪年龄阶段名称
|
||||
Description string `json:"description"`
|
||||
DailyFeedIntake float32 `json:"daily_feed_intake"`
|
||||
DailyGainWeight float32 `json:"daily_gain_weight"`
|
||||
MinDays uint32 `json:"min_days"`
|
||||
MaxDays uint32 `json:"max_days"`
|
||||
MinWeight float32 `json:"min_weight"`
|
||||
MaxWeight float32 `json:"max_weight"`
|
||||
PigNutrientRequirements []PigNutrientRequirementDTO `json:"pig_nutrient_requirements"` // 关联的营养需求
|
||||
}
|
||||
|
||||
// ListPigTypeRequest 定义了获取猪类型列表的请求参数
|
||||
type ListPigTypeRequest struct {
|
||||
Page int `json:"page" query:"page"` // 页码
|
||||
PageSize int `json:"page_size" query:"page_size"` // 每页数量
|
||||
BreedID *uint32 `json:"breed_id" query:"breed_id"` // 关联的猪品种ID
|
||||
AgeStageID *uint32 `json:"age_stage_id" query:"age_stage_id"` // 关联的猪年龄阶段ID
|
||||
BreedName *string `json:"breed_name" query:"breed_name"` // 关联的猪品种名称 (用于模糊查询)
|
||||
AgeStageName *string `json:"age_stage_name" query:"age_stage_name"` // 关联的猪年龄阶段名称 (用于模糊查询)
|
||||
OrderBy string `json:"order_by" query:"order_by"` // 排序字段,例如 "id DESC"
|
||||
}
|
||||
|
||||
// ListPigTypeResponse 是获取猪类型列表的响应结构
|
||||
type ListPigTypeResponse struct {
|
||||
List []PigTypeResponse `json:"list"`
|
||||
Pagination PaginationDTO `json:"pagination"`
|
||||
}
|
||||
529
internal/app/service/feed_management_service.go
Normal file
529
internal/app/service/feed_management_service.go
Normal file
@@ -0,0 +1,529 @@
|
||||
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)
|
||||
|
||||
// 猪品种相关
|
||||
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)
|
||||
}
|
||||
|
||||
// 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")
|
||||
|
||||
nutrients, total, err := s.recipeSvc.ListNutrients(serviceCtx, 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")
|
||||
|
||||
rawMaterials, total, err := s.recipeSvc.ListRawMaterials(serviceCtx, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取原料列表失败: %w", err)
|
||||
}
|
||||
|
||||
return dto.ConvertRawMaterialListToDTO(rawMaterials, total, req.Page, req.PageSize), 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
|
||||
}
|
||||
@@ -63,6 +63,7 @@ func NewApplication(configPath string) (*Application, error) {
|
||||
appServices.userService,
|
||||
appServices.auditService,
|
||||
appServices.thresholdAlarmService,
|
||||
appServices.feedManagementService,
|
||||
infra.tokenGenerator,
|
||||
infra.lora.listenHandler,
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
domain_notify "git.huangwc.com/pig/pig-farm-controller/internal/domain/notify"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/pig"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/plan"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/recipe"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/task"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/config"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/database"
|
||||
@@ -82,6 +83,9 @@ type Repositories struct {
|
||||
medicationLogRepo repository.MedicationLogRepository
|
||||
notificationRepo repository.NotificationRepository
|
||||
alarmRepo repository.AlarmRepository
|
||||
pigTypeRepo repository.PigTypeRepository
|
||||
rawMaterialRepo repository.RawMaterialRepository
|
||||
nutrientRepo repository.NutrientRepository
|
||||
unitOfWork repository.UnitOfWork
|
||||
}
|
||||
|
||||
@@ -110,6 +114,9 @@ func initRepositories(ctx context.Context, db *gorm.DB) *Repositories {
|
||||
medicationLogRepo: repository.NewGormMedicationLogRepository(logs.AddCompName(baseCtx, "MedicationLogRepo"), db),
|
||||
notificationRepo: repository.NewGormNotificationRepository(logs.AddCompName(baseCtx, "NotificationRepo"), db),
|
||||
alarmRepo: repository.NewGormAlarmRepository(logs.AddCompName(baseCtx, "AlarmRepo"), db),
|
||||
pigTypeRepo: repository.NewGormPigTypeRepository(logs.AddCompName(baseCtx, "PigTypeRepo"), db),
|
||||
rawMaterialRepo: repository.NewGormRawMaterialRepository(logs.AddCompName(baseCtx, "RawMaterialRepo"), db),
|
||||
nutrientRepo: repository.NewGormNutrientRepository(logs.AddCompName(baseCtx, "NutrientRepo"), db),
|
||||
unitOfWork: repository.NewGormUnitOfWork(logs.AddCompName(baseCtx, "UnitOfWork"), db),
|
||||
}
|
||||
}
|
||||
@@ -127,6 +134,7 @@ type DomainServices struct {
|
||||
planService plan.Service
|
||||
notifyService domain_notify.Service
|
||||
alarmService alarm.AlarmService
|
||||
recipeService recipe.Service
|
||||
}
|
||||
|
||||
// initDomainServices 初始化所有的领域服务。
|
||||
@@ -206,6 +214,14 @@ func initDomainServices(ctx context.Context, cfg *config.Config, infra *Infrastr
|
||||
taskFactory,
|
||||
)
|
||||
|
||||
// 配方管理服务
|
||||
recipeService := recipe.NewRecipeService(
|
||||
logs.AddCompName(baseCtx, "RecipeService"),
|
||||
infra.repos.nutrientRepo,
|
||||
infra.repos.rawMaterialRepo,
|
||||
infra.repos.pigTypeRepo,
|
||||
)
|
||||
|
||||
return &DomainServices{
|
||||
pigPenTransferManager: pigPenTransferManager,
|
||||
pigTradeManager: pigTradeManager,
|
||||
@@ -218,6 +234,7 @@ func initDomainServices(ctx context.Context, cfg *config.Config, infra *Infrastr
|
||||
planService: planService,
|
||||
notifyService: notifyService,
|
||||
alarmService: alarmService,
|
||||
recipeService: recipeService,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -231,6 +248,7 @@ type AppServices struct {
|
||||
userService service.UserService
|
||||
auditService service.AuditService
|
||||
thresholdAlarmService service.ThresholdAlarmService
|
||||
feedManagementService service.FeedManagementService
|
||||
}
|
||||
|
||||
// initAppServices 初始化所有的应用服务。
|
||||
@@ -278,6 +296,7 @@ func initAppServices(ctx context.Context, infra *Infrastructure, domainServices
|
||||
auditService := service.NewAuditService(logs.AddCompName(baseCtx, "AuditService"), infra.repos.userActionLogRepo)
|
||||
planService := service.NewPlanService(logs.AddCompName(baseCtx, "AppPlanService"), domainServices.planService)
|
||||
userService := service.NewUserService(logs.AddCompName(baseCtx, "UserService"), infra.repos.userRepo, infra.tokenGenerator, domainServices.notifyService)
|
||||
feedManagementService := service.NewFeedManagementService(logs.AddCompName(baseCtx, "FeedManagementService"), domainServices.recipeService)
|
||||
|
||||
return &AppServices{
|
||||
pigFarmService: pigFarmService,
|
||||
@@ -288,6 +307,7 @@ func initAppServices(ctx context.Context, infra *Infrastructure, domainServices
|
||||
planService: planService,
|
||||
userService: userService,
|
||||
thresholdAlarmService: thresholdAlarmService,
|
||||
feedManagementService: feedManagementService,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ func (r *gormPigTypeRepository) CreatePigType(ctx context.Context, pigType *mode
|
||||
func (r *gormPigTypeRepository) GetPigTypeByID(ctx context.Context, id uint32) (*models.PigType, error) {
|
||||
repoCtx := logs.AddFuncName(ctx, r.ctx, "GetPigTypeByID")
|
||||
var pigType models.PigType
|
||||
err := r.db.WithContext(repoCtx).Preload("Breed").Preload("AgeStage").First(&pigType, id).Error
|
||||
err := r.db.WithContext(repoCtx).Preload("Breed").Preload("AgeStage").Preload("PigNutrientRequirements.Nutrient").First(&pigType, id).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -275,7 +275,7 @@ func (r *gormPigTypeRepository) ListPigTypes(ctx context.Context, opts PigTypeLi
|
||||
query = query.Order(orderBy)
|
||||
|
||||
offset := (page - 1) * pageSize
|
||||
err := query.Limit(pageSize).Offset(offset).Preload("Breed").Preload("AgeStage").Find(&results).Error
|
||||
err := query.Limit(pageSize).Offset(offset).Preload("Breed").Preload("AgeStage").Preload("PigNutrientRequirements.Nutrient").Find(&results).Error
|
||||
|
||||
return results, total, err
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ internal/app/api/router.go
|
||||
internal/app/controller/alarm/threshold_alarm_controller.go
|
||||
internal/app/controller/auth_utils.go
|
||||
internal/app/controller/device/device_controller.go
|
||||
internal/app/controller/feed/feed_controller.go
|
||||
internal/app/controller/health/health_controller.go
|
||||
internal/app/controller/management/controller_helpers.go
|
||||
internal/app/controller/management/pig_batch_controller.go
|
||||
@@ -64,6 +65,8 @@ internal/app/dto/alarm_dto.go
|
||||
internal/app/dto/device_converter.go
|
||||
internal/app/dto/device_dto.go
|
||||
internal/app/dto/dto.go
|
||||
internal/app/dto/feed_converter.go
|
||||
internal/app/dto/feed_dto.go
|
||||
internal/app/dto/monitor_converter.go
|
||||
internal/app/dto/monitor_dto.go
|
||||
internal/app/dto/notification_converter.go
|
||||
@@ -77,6 +80,7 @@ internal/app/middleware/audit.go
|
||||
internal/app/middleware/auth.go
|
||||
internal/app/service/audit_service.go
|
||||
internal/app/service/device_service.go
|
||||
internal/app/service/feed_management_service.go
|
||||
internal/app/service/monitor_service.go
|
||||
internal/app/service/pig_batch_service.go
|
||||
internal/app/service/pig_farm_service.go
|
||||
|
||||
Reference in New Issue
Block a user