实现 猪舍相关路由组 和 猪圈相关路由组
This commit is contained in:
@@ -17,9 +17,11 @@ import (
|
||||
|
||||
_ "git.huangwc.com/pig/pig-farm-controller/docs" // 引入 swag 生成的 docs
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/device"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/management"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/plan"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/user"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/middleware"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/webhook"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/audit"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/task"
|
||||
@@ -45,6 +47,7 @@ type API struct {
|
||||
userController *user.Controller // 用户控制器实例
|
||||
deviceController *device.Controller // 设备控制器实例
|
||||
planController *plan.Controller // 计划控制器实例
|
||||
pigFarmController *management.PigFarmController // 猪场管理控制器实例
|
||||
listenHandler webhook.ListenHandler // 设备上行事件监听器
|
||||
analysisTaskManager *task.AnalysisPlanTaskManager // 计划触发器管理器实例
|
||||
}
|
||||
@@ -58,6 +61,7 @@ func NewAPI(cfg config.ServerConfig,
|
||||
areaControllerRepository repository.AreaControllerRepository,
|
||||
deviceTemplateRepository repository.DeviceTemplateRepository, // 添加设备模板仓库
|
||||
planRepository repository.PlanRepository,
|
||||
pigFarmService service.PigFarmService,
|
||||
userActionLogRepository repository.UserActionLogRepository,
|
||||
tokenService token.TokenService,
|
||||
auditService audit.Service, // 注入审计服务
|
||||
@@ -90,6 +94,8 @@ func NewAPI(cfg config.ServerConfig,
|
||||
deviceController: device.NewController(deviceRepository, areaControllerRepository, deviceTemplateRepository, logger),
|
||||
// 在 NewAPI 中初始化计划控制器,并将其作为 API 结构体的成员
|
||||
planController: plan.NewController(logger, planRepository, analysisTaskManager),
|
||||
// 在 NewAPI 中初始化猪场管理控制器
|
||||
pigFarmController: management.NewPigFarmController(logger, pigFarmService),
|
||||
}
|
||||
|
||||
api.setupRoutes() // 设置所有路由
|
||||
@@ -192,6 +198,29 @@ func (a *API) setupRoutes() {
|
||||
planGroup.POST("/:id/stop", a.planController.StopPlan)
|
||||
}
|
||||
a.logger.Info("计划相关接口注册成功 (需要认证和审计)")
|
||||
|
||||
// 猪舍相关路由组
|
||||
pigHouseGroup := authGroup.Group("/pighouses")
|
||||
{
|
||||
pigHouseGroup.POST("", a.pigFarmController.CreatePigHouse)
|
||||
pigHouseGroup.GET("", a.pigFarmController.ListPigHouses)
|
||||
pigHouseGroup.GET("/:id", a.pigFarmController.GetPigHouse)
|
||||
pigHouseGroup.PUT("/:id", a.pigFarmController.UpdatePigHouse)
|
||||
pigHouseGroup.DELETE("/:id", a.pigFarmController.DeletePigHouse)
|
||||
}
|
||||
a.logger.Info("猪舍相关接口注册成功 (需要认证和审计)")
|
||||
|
||||
// 猪圈相关路由组
|
||||
penGroup := authGroup.Group("/pens")
|
||||
{
|
||||
penGroup.POST("", a.pigFarmController.CreatePen)
|
||||
penGroup.GET("", a.pigFarmController.ListPens)
|
||||
penGroup.GET("/:id", a.pigFarmController.GetPen)
|
||||
penGroup.PUT("/:id", a.pigFarmController.UpdatePen)
|
||||
penGroup.DELETE("/:id", a.pigFarmController.DeletePen)
|
||||
}
|
||||
a.logger.Info("猪圈相关接口注册成功 (需要认证和审计)")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1
internal/app/controller/management/feed_controller.go
Normal file
1
internal/app/controller/management/feed_controller.go
Normal file
@@ -0,0 +1 @@
|
||||
package management
|
||||
@@ -0,0 +1 @@
|
||||
package management
|
||||
1
internal/app/controller/management/pig_controller.go
Normal file
1
internal/app/controller/management/pig_controller.go
Normal file
@@ -0,0 +1 @@
|
||||
package management
|
||||
426
internal/app/controller/management/pig_farm_controller.go
Normal file
426
internal/app/controller/management/pig_farm_controller.go
Normal file
@@ -0,0 +1,426 @@
|
||||
package management
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// --- 数据传输对象 (DTOs) ---
|
||||
|
||||
// PigHouseResponse 定义了猪舍信息的响应结构
|
||||
type PigHouseResponse struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// PenResponse 定义了猪栏信息的响应结构
|
||||
type PenResponse struct {
|
||||
ID uint `json:"id"`
|
||||
PenNumber string `json:"pen_number"`
|
||||
HouseID uint `json:"house_id"`
|
||||
Capacity int `json:"capacity"`
|
||||
Status models.PenStatus `json:"status"`
|
||||
PigBatchID uint `json:"pig_batch_id"`
|
||||
}
|
||||
|
||||
// CreatePigHouseRequest 定义了创建猪舍的请求结构
|
||||
type CreatePigHouseRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// UpdatePigHouseRequest 定义了更新猪舍的请求结构
|
||||
type UpdatePigHouseRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// CreatePenRequest 定义了创建猪栏的请求结构
|
||||
type CreatePenRequest struct {
|
||||
PenNumber string `json:"pen_number" binding:"required"`
|
||||
HouseID uint `json:"house_id" binding:"required"`
|
||||
Capacity int `json:"capacity" binding:"required"`
|
||||
Status models.PenStatus `json:"status" binding:"required"`
|
||||
}
|
||||
|
||||
// UpdatePenRequest 定义了更新猪栏的请求结构
|
||||
type UpdatePenRequest struct {
|
||||
PenNumber string `json:"pen_number" binding:"required"`
|
||||
HouseID uint `json:"house_id" binding:"required"`
|
||||
Capacity int `json:"capacity" binding:"required"`
|
||||
Status models.PenStatus `json:"status" binding:"required"`
|
||||
}
|
||||
|
||||
// --- 控制器定义 ---
|
||||
|
||||
// PigFarmController 负责处理猪舍和猪栏相关的API请求
|
||||
type PigFarmController struct {
|
||||
logger *logs.Logger
|
||||
service service.PigFarmService
|
||||
}
|
||||
|
||||
// NewPigFarmController 创建一个新的 PigFarmController 实例
|
||||
func NewPigFarmController(logger *logs.Logger, service service.PigFarmService) *PigFarmController {
|
||||
return &PigFarmController{
|
||||
logger: logger,
|
||||
service: service,
|
||||
}
|
||||
}
|
||||
|
||||
// --- 猪舍 (PigHouse) API 实现 ---
|
||||
|
||||
// CreatePigHouse godoc
|
||||
// @Summary 创建猪舍
|
||||
// @Description 创建一个新的猪舍
|
||||
// @Tags 猪场管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body CreatePigHouseRequest true "猪舍信息"
|
||||
// @Success 201 {object} controller.Response{data=PigHouseResponse} "创建成功"
|
||||
// @Router /api/v1/pighouses [post]
|
||||
func (c *PigFarmController) CreatePigHouse(ctx *gin.Context) {
|
||||
const action = "创建猪舍"
|
||||
var req CreatePigHouseRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
|
||||
return
|
||||
}
|
||||
|
||||
house, err := c.service.CreatePigHouse(req.Name, req.Description)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪舍失败", action, "业务逻辑失败", req)
|
||||
return
|
||||
}
|
||||
|
||||
resp := PigHouseResponse{
|
||||
ID: house.ID,
|
||||
Name: house.Name,
|
||||
Description: house.Description,
|
||||
}
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "创建成功", resp, action, "创建成功", resp)
|
||||
}
|
||||
|
||||
// GetPigHouse godoc
|
||||
// @Summary 获取单个猪舍
|
||||
// @Description 根据ID获取单个猪舍信息
|
||||
// @Tags 猪场管理
|
||||
// @Produce json
|
||||
// @Param id path int true "猪舍ID"
|
||||
// @Success 200 {object} controller.Response{data=PigHouseResponse} "获取成功"
|
||||
// @Router /api/v1/pighouses/{id} [get]
|
||||
func (c *PigFarmController) GetPigHouse(ctx *gin.Context) {
|
||||
const action = "获取猪舍"
|
||||
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
|
||||
return
|
||||
}
|
||||
|
||||
house, err := c.service.GetPigHouseByID(uint(id))
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
|
||||
return
|
||||
}
|
||||
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪舍失败", action, "业务逻辑失败", id)
|
||||
return
|
||||
}
|
||||
|
||||
resp := PigHouseResponse{
|
||||
ID: house.ID,
|
||||
Name: house.Name,
|
||||
Description: house.Description,
|
||||
}
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", resp, action, "获取成功", resp)
|
||||
}
|
||||
|
||||
// ListPigHouses godoc
|
||||
// @Summary 获取猪舍列表
|
||||
// @Description 获取所有猪舍的列表
|
||||
// @Tags 猪场管理
|
||||
// @Produce json
|
||||
// @Success 200 {object} controller.Response{data=[]PigHouseResponse} "获取成功"
|
||||
// @Router /api/v1/pighouses [get]
|
||||
func (c *PigFarmController) ListPigHouses(ctx *gin.Context) {
|
||||
const action = "获取猪舍列表"
|
||||
houses, err := c.service.ListPigHouses()
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取列表失败", action, "业务逻辑失败", nil)
|
||||
return
|
||||
}
|
||||
|
||||
var resp []PigHouseResponse
|
||||
for _, house := range houses {
|
||||
resp = append(resp, PigHouseResponse{
|
||||
ID: house.ID,
|
||||
Name: house.Name,
|
||||
Description: house.Description,
|
||||
})
|
||||
}
|
||||
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", resp, action, "获取成功", resp)
|
||||
}
|
||||
|
||||
// UpdatePigHouse godoc
|
||||
// @Summary 更新猪舍
|
||||
// @Description 更新一个已存在的猪舍信息
|
||||
// @Tags 猪场管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "猪舍ID"
|
||||
// @Param body body UpdatePigHouseRequest true "猪舍信息"
|
||||
// @Success 200 {object} controller.Response{data=PigHouseResponse} "更新成功"
|
||||
// @Router /api/v1/pighouses/{id} [put]
|
||||
func (c *PigFarmController) UpdatePigHouse(ctx *gin.Context) {
|
||||
const action = "更新猪舍"
|
||||
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdatePigHouseRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
|
||||
return
|
||||
}
|
||||
|
||||
house, err := c.service.UpdatePigHouse(uint(id), req.Name, req.Description)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
|
||||
return
|
||||
}
|
||||
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新失败", action, "业务逻辑失败", req)
|
||||
return
|
||||
}
|
||||
|
||||
resp := PigHouseResponse{
|
||||
ID: house.ID,
|
||||
Name: house.Name,
|
||||
Description: house.Description,
|
||||
}
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "更新成功", resp, action, "更新成功", resp)
|
||||
}
|
||||
|
||||
// DeletePigHouse godoc
|
||||
// @Summary 删除猪舍
|
||||
// @Description 根据ID删除一个猪舍
|
||||
// @Tags 猪场管理
|
||||
// @Produce json
|
||||
// @Param id path int true "猪舍ID"
|
||||
// @Success 200 {object} controller.Response "删除成功"
|
||||
// @Router /api/v1/pighouses/{id} [delete]
|
||||
func (c *PigFarmController) DeletePigHouse(ctx *gin.Context) {
|
||||
const action = "删除猪舍"
|
||||
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.service.DeletePigHouse(uint(id)); err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
|
||||
return
|
||||
}
|
||||
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除失败", action, "业务逻辑失败", id)
|
||||
return
|
||||
}
|
||||
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "删除成功", nil, action, "删除成功", id)
|
||||
}
|
||||
|
||||
// --- 猪栏 (Pen) API 实现 ---
|
||||
|
||||
// CreatePen godoc
|
||||
// @Summary 创建猪栏
|
||||
// @Description 创建一个新的猪栏
|
||||
// @Tags 猪场管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body CreatePenRequest true "猪栏信息"
|
||||
// @Success 201 {object} controller.Response{data=PenResponse} "创建成功"
|
||||
// @Router /api/v1/pens [post]
|
||||
func (c *PigFarmController) CreatePen(ctx *gin.Context) {
|
||||
const action = "创建猪栏"
|
||||
var req CreatePenRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
|
||||
return
|
||||
}
|
||||
|
||||
pen, err := c.service.CreatePen(req.PenNumber, req.HouseID, req.Capacity, req.Status)
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪栏失败", action, "业务逻辑失败", req)
|
||||
return
|
||||
}
|
||||
|
||||
resp := PenResponse{
|
||||
ID: pen.ID,
|
||||
PenNumber: pen.PenNumber,
|
||||
HouseID: pen.HouseID,
|
||||
Capacity: pen.Capacity,
|
||||
Status: pen.Status,
|
||||
PigBatchID: pen.PigBatchID,
|
||||
}
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "创建成功", resp, action, "创建成功", resp)
|
||||
}
|
||||
|
||||
// GetPen godoc
|
||||
// @Summary 获取单个猪栏
|
||||
// @Description 根据ID获取单个猪栏信息
|
||||
// @Tags 猪场管理
|
||||
// @Produce json
|
||||
// @Param id path int true "猪栏ID"
|
||||
// @Success 200 {object} controller.Response{data=PenResponse} "获取成功"
|
||||
// @Router /api/v1/pens/{id} [get]
|
||||
func (c *PigFarmController) GetPen(ctx *gin.Context) {
|
||||
const action = "获取猪栏"
|
||||
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
|
||||
return
|
||||
}
|
||||
|
||||
pen, err := c.service.GetPenByID(uint(id))
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
|
||||
return
|
||||
}
|
||||
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪栏失败", action, "业务逻辑失败", id)
|
||||
return
|
||||
}
|
||||
|
||||
resp := PenResponse{
|
||||
ID: pen.ID,
|
||||
PenNumber: pen.PenNumber,
|
||||
HouseID: pen.HouseID,
|
||||
Capacity: pen.Capacity,
|
||||
Status: pen.Status,
|
||||
PigBatchID: pen.PigBatchID,
|
||||
}
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", resp, action, "获取成功", resp)
|
||||
}
|
||||
|
||||
// ListPens godoc
|
||||
// @Summary 获取猪栏列表
|
||||
// @Description 获取所有猪栏的列表
|
||||
// @Tags 猪场管理
|
||||
// @Produce json
|
||||
// @Success 200 {object} controller.Response{data=[]PenResponse} "获取成功"
|
||||
// @Router /api/v1/pens [get]
|
||||
func (c *PigFarmController) ListPens(ctx *gin.Context) {
|
||||
const action = "获取猪栏列表"
|
||||
pens, err := c.service.ListPens()
|
||||
if err != nil {
|
||||
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取列表失败", action, "业务逻辑失败", nil)
|
||||
return
|
||||
}
|
||||
|
||||
var resp []PenResponse
|
||||
for _, pen := range pens {
|
||||
resp = append(resp, PenResponse{
|
||||
ID: pen.ID,
|
||||
PenNumber: pen.PenNumber,
|
||||
HouseID: pen.HouseID,
|
||||
Capacity: pen.Capacity,
|
||||
Status: pen.Status,
|
||||
PigBatchID: pen.PigBatchID,
|
||||
})
|
||||
}
|
||||
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", resp, action, "获取成功", resp)
|
||||
}
|
||||
|
||||
// UpdatePen godoc
|
||||
// @Summary 更新猪栏
|
||||
// @Description 更新一个已存在的猪栏信息
|
||||
// @Tags 猪场管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "猪栏ID"
|
||||
// @Param body body UpdatePenRequest true "猪栏信息"
|
||||
// @Success 200 {object} controller.Response{data=PenResponse} "更新成功"
|
||||
// @Router /api/v1/pens/{id} [put]
|
||||
func (c *PigFarmController) UpdatePen(ctx *gin.Context) {
|
||||
const action = "更新猪栏"
|
||||
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdatePenRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
|
||||
return
|
||||
}
|
||||
|
||||
pen, err := c.service.UpdatePen(uint(id), req.PenNumber, req.HouseID, req.Capacity, req.Status)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
|
||||
return
|
||||
}
|
||||
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新失败", action, "业务逻辑失败", req)
|
||||
return
|
||||
}
|
||||
|
||||
resp := PenResponse{
|
||||
ID: pen.ID,
|
||||
PenNumber: pen.PenNumber,
|
||||
HouseID: pen.HouseID,
|
||||
Capacity: pen.Capacity,
|
||||
Status: pen.Status,
|
||||
PigBatchID: pen.PigBatchID,
|
||||
}
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "更新成功", resp, action, "更新成功", resp)
|
||||
}
|
||||
|
||||
// DeletePen godoc
|
||||
// @Summary 删除猪栏
|
||||
// @Description 根据ID删除一个猪栏
|
||||
// @Tags 猪场管理
|
||||
// @Produce json
|
||||
// @Param id path int true "猪栏ID"
|
||||
// @Success 200 {object} controller.Response "删除成功"
|
||||
// @Router /api/v1/pens/{id} [delete]
|
||||
func (c *PigFarmController) DeletePen(ctx *gin.Context) {
|
||||
const action = "删除猪栏"
|
||||
id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.service.DeletePen(uint(id)); err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
|
||||
return
|
||||
}
|
||||
c.logger.Errorf("%s: 业务逻辑失败: %v", action, err)
|
||||
controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除失败", action, "业务逻辑失败", id)
|
||||
return
|
||||
}
|
||||
|
||||
controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "删除成功", nil, action, "删除成功", id)
|
||||
}
|
||||
116
internal/app/service/pig_farm_service.go
Normal file
116
internal/app/service/pig_farm_service.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"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"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// PigFarmService 提供了猪场资产管理的业务逻辑
|
||||
type PigFarmService interface {
|
||||
// PigHouse methods
|
||||
CreatePigHouse(name, description string) (*models.PigHouse, error)
|
||||
GetPigHouseByID(id uint) (*models.PigHouse, error)
|
||||
ListPigHouses() ([]models.PigHouse, error)
|
||||
UpdatePigHouse(id uint, name, description string) (*models.PigHouse, error)
|
||||
DeletePigHouse(id uint) error
|
||||
|
||||
// Pen methods
|
||||
CreatePen(penNumber string, houseID uint, capacity int, status models.PenStatus) (*models.Pen, error)
|
||||
GetPenByID(id uint) (*models.Pen, error)
|
||||
ListPens() ([]models.Pen, error)
|
||||
UpdatePen(id uint, penNumber string, houseID uint, capacity int, status models.PenStatus) (*models.Pen, error)
|
||||
DeletePen(id uint) error
|
||||
}
|
||||
|
||||
type pigFarmService struct {
|
||||
logger *logs.Logger
|
||||
repo repository.PigFarmRepository
|
||||
}
|
||||
|
||||
// NewPigFarmService 创建一个新的 PigFarmService 实例
|
||||
func NewPigFarmService(repo repository.PigFarmRepository, logger *logs.Logger) PigFarmService {
|
||||
return &pigFarmService{
|
||||
logger: logger,
|
||||
repo: repo,
|
||||
}
|
||||
}
|
||||
|
||||
// --- PigHouse Implementation ---
|
||||
|
||||
func (s *pigFarmService) CreatePigHouse(name, description string) (*models.PigHouse, error) {
|
||||
house := &models.PigHouse{
|
||||
Name: name,
|
||||
Description: description,
|
||||
}
|
||||
err := s.repo.CreatePigHouse(house)
|
||||
return house, err
|
||||
}
|
||||
|
||||
func (s *pigFarmService) GetPigHouseByID(id uint) (*models.PigHouse, error) {
|
||||
return s.repo.GetPigHouseByID(id)
|
||||
}
|
||||
|
||||
func (s *pigFarmService) ListPigHouses() ([]models.PigHouse, error) {
|
||||
return s.repo.ListPigHouses()
|
||||
}
|
||||
|
||||
func (s *pigFarmService) UpdatePigHouse(id uint, name, description string) (*models.PigHouse, error) {
|
||||
house := &models.PigHouse{
|
||||
Model: gorm.Model{ID: id},
|
||||
Name: name,
|
||||
Description: description,
|
||||
}
|
||||
err := s.repo.UpdatePigHouse(house)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 返回更新后的完整信息
|
||||
return s.repo.GetPigHouseByID(id)
|
||||
}
|
||||
|
||||
func (s *pigFarmService) DeletePigHouse(id uint) error {
|
||||
return s.repo.DeletePigHouse(id)
|
||||
}
|
||||
|
||||
// --- Pen Implementation ---
|
||||
|
||||
func (s *pigFarmService) CreatePen(penNumber string, houseID uint, capacity int, status models.PenStatus) (*models.Pen, error) {
|
||||
pen := &models.Pen{
|
||||
PenNumber: penNumber,
|
||||
HouseID: houseID,
|
||||
Capacity: capacity,
|
||||
Status: status,
|
||||
}
|
||||
err := s.repo.CreatePen(pen)
|
||||
return pen, err
|
||||
}
|
||||
|
||||
func (s *pigFarmService) GetPenByID(id uint) (*models.Pen, error) {
|
||||
return s.repo.GetPenByID(id)
|
||||
}
|
||||
|
||||
func (s *pigFarmService) ListPens() ([]models.Pen, error) {
|
||||
return s.repo.ListPens()
|
||||
}
|
||||
|
||||
func (s *pigFarmService) UpdatePen(id uint, penNumber string, houseID uint, capacity int, status models.PenStatus) (*models.Pen, error) {
|
||||
pen := &models.Pen{
|
||||
Model: gorm.Model{ID: id},
|
||||
PenNumber: penNumber,
|
||||
HouseID: houseID,
|
||||
Capacity: capacity,
|
||||
Status: status,
|
||||
}
|
||||
err := s.repo.UpdatePen(pen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 返回更新后的完整信息
|
||||
return s.repo.GetPenByID(id)
|
||||
}
|
||||
|
||||
func (s *pigFarmService) DeletePen(id uint) error {
|
||||
return s.repo.DeletePen(id)
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/api"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/app/webhook"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/audit"
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/domain/device"
|
||||
@@ -58,39 +59,23 @@ func NewApplication(configPath string) (*Application, error) {
|
||||
// 初始化 Token 服务
|
||||
tokenService := token.NewTokenService([]byte(cfg.App.JWTSecret))
|
||||
|
||||
// 初始化用户仓库
|
||||
// --- 仓库对象初始化 ---
|
||||
userRepo := repository.NewGormUserRepository(storage.GetDB())
|
||||
|
||||
// 初始化设备仓库
|
||||
deviceRepo := repository.NewGormDeviceRepository(storage.GetDB())
|
||||
|
||||
// 初始化区域主控仓库
|
||||
areaControllerRepo := repository.NewGormAreaControllerRepository(storage.GetDB())
|
||||
|
||||
// 初始化设备模板仓库
|
||||
deviceTemplateRepo := repository.NewGormDeviceTemplateRepository(storage.GetDB())
|
||||
|
||||
// 初始化计划仓库
|
||||
planRepo := repository.NewGormPlanRepository(storage.GetDB())
|
||||
|
||||
// 初始化待执行任务仓库
|
||||
pigFarmRepo := repository.NewGormPigFarmRepository(storage.GetDB())
|
||||
pendingTaskRepo := repository.NewGormPendingTaskRepository(storage.GetDB())
|
||||
|
||||
// 初始化执行日志仓库
|
||||
executionLogRepo := repository.NewGormExecutionLogRepository(storage.GetDB())
|
||||
|
||||
// 初始化传感器数据仓库
|
||||
sensorDataRepo := repository.NewGormSensorDataRepository(storage.GetDB())
|
||||
|
||||
// 初始化命令下发历史仓库
|
||||
deviceCommandLogRepo := repository.NewGormDeviceCommandLogRepository(storage.GetDB())
|
||||
|
||||
// 初始化待采集请求仓库
|
||||
pendingCollectionRepo := repository.NewGormPendingCollectionRepository(storage.GetDB())
|
||||
|
||||
// 初始化审计日志仓库
|
||||
userActionLogRepo := repository.NewGormUserActionLogRepository(storage.GetDB())
|
||||
|
||||
// --- 业务逻辑处理器初始化 ---
|
||||
pigFarmService := service.NewPigFarmService(pigFarmRepo, logger)
|
||||
|
||||
// 初始化审计服务
|
||||
auditService := audit.NewService(userActionLogRepo, logger)
|
||||
|
||||
@@ -135,6 +120,7 @@ func NewApplication(configPath string) (*Application, error) {
|
||||
areaControllerRepo,
|
||||
deviceTemplateRepo,
|
||||
planRepo,
|
||||
pigFarmService,
|
||||
userActionLogRepo,
|
||||
tokenService,
|
||||
auditService,
|
||||
|
||||
@@ -160,11 +160,16 @@ func (ps *PostgresStorage) creatingHyperTable() error {
|
||||
{models.TaskExecutionLog{}, "created_at"},
|
||||
{models.PendingCollection{}, "created_at"},
|
||||
{models.UserActionLog{}, "time"},
|
||||
{models.RawMaterialPurchase{}, "purchase_date"},
|
||||
{models.RawMaterialStockLog{}, "happened_at"},
|
||||
{models.FeedUsageRecord{}, "recorded_at"},
|
||||
{models.GroupMedicationLog{}, "happened_at"},
|
||||
{models.PigBatchLog{}, "happened_at"},
|
||||
}
|
||||
|
||||
for _, table := range tablesToConvert {
|
||||
tableName := table.model.TableName()
|
||||
chunkInterval := "1 day" // 统一设置为1天
|
||||
chunkInterval := "7 days" // 统一设置为7天
|
||||
ps.logger.Infow("准备将表转换为超表", "table", tableName, "chunk_interval", chunkInterval)
|
||||
sql := fmt.Sprintf("SELECT create_hypertable('%s', '%s', chunk_time_interval => INTERVAL '%s', if_not_exists => TRUE);", tableName, table.timeColumn, chunkInterval)
|
||||
if err := ps.db.Exec(sql).Error; err != nil {
|
||||
@@ -193,7 +198,7 @@ func (ps *PostgresStorage) applyCompressionPolicies() error {
|
||||
|
||||
for _, policy := range policies {
|
||||
tableName := policy.model.TableName()
|
||||
compressAfter := "3 days" // 统一设置为2天后(即进入第3天)开始压缩
|
||||
compressAfter := "15 days" // 统一设置为15天后开始压缩
|
||||
|
||||
// 1. 开启表的压缩设置,并指定分段列
|
||||
ps.logger.Infow("为表启用压缩设置", "table", tableName, "segment_by", policy.segmentColumn)
|
||||
@@ -239,14 +244,5 @@ func (ps *PostgresStorage) creatingIndex() error {
|
||||
}
|
||||
ps.logger.Info("成功为 tasks 的 parameters 字段创建 GIN 索引 (或已存在)")
|
||||
|
||||
// 为 devices 表的 properties 字段创建 GIN 索引
|
||||
//ps.logger.Info("正在为 devices 表的 properties 字段创建 GIN 索引")
|
||||
//ginDevicePropertiesIndexSQL := "CREATE INDEX IF NOT EXISTS idx_devices_properties_gin ON devices USING GIN (properties);"
|
||||
//if err := ps.db.Exec(ginDevicePropertiesIndexSQL).Error; err != nil {
|
||||
// ps.logger.Errorw("为 devices 的 properties 字段创建 GIN 索引失败", "error", err)
|
||||
// return fmt.Errorf("为 devices 的 properties 字段创建 GIN 索引失败: %w", err)
|
||||
//}
|
||||
//ps.logger.Info("成功为 devices 的 properties 字段创建 GIN 索引 (或已存在)")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -19,16 +19,27 @@ type RawMaterial struct {
|
||||
Quantity float64 `gorm:"not null;comment:库存总量, 单位: g"`
|
||||
}
|
||||
|
||||
func (RawMaterial) TableName() string {
|
||||
return "raw_materials"
|
||||
}
|
||||
|
||||
// RawMaterialPurchase 记录了原料的每一次采购。
|
||||
type RawMaterialPurchase struct {
|
||||
gorm.Model
|
||||
ID uint `gorm:"primaryKey"`
|
||||
RawMaterialID uint `gorm:"not null;index;comment:关联的原料ID"`
|
||||
RawMaterial RawMaterial `gorm:"foreignKey:RawMaterialID"`
|
||||
Supplier string `gorm:"size:100;comment:供应商"`
|
||||
Amount float64 `gorm:"not null;comment:采购数量, 单位: g"`
|
||||
UnitPrice float64 `gorm:"comment:单价"`
|
||||
TotalPrice float64 `gorm:"comment:总价"`
|
||||
PurchaseDate time.Time `gorm:"not null;comment:采购日期"`
|
||||
PurchaseDate time.Time `gorm:"primaryKey;comment:采购日期"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
}
|
||||
|
||||
func (RawMaterialPurchase) TableName() string {
|
||||
return "raw_material_purchases"
|
||||
}
|
||||
|
||||
// StockLogSourceType 定义了库存日志来源的类型
|
||||
@@ -45,13 +56,20 @@ const (
|
||||
|
||||
// RawMaterialStockLog 记录了原料库存的所有变动,提供了完整的追溯链。
|
||||
type RawMaterialStockLog struct {
|
||||
gorm.Model
|
||||
ID uint `gorm:"primaryKey"`
|
||||
RawMaterialID uint `gorm:"not null;index;comment:关联的原料ID"`
|
||||
ChangeAmount float64 `gorm:"not null;comment:变动数量, 正数为入库, 负数为出库"`
|
||||
SourceType StockLogSourceType `gorm:"size:50;not null;index;comment:库存变动来源类型"`
|
||||
SourceID uint `gorm:"not null;index;comment:来源记录的ID (如 RawMaterialPurchase.ID 或 FeedUsageRecord.ID)"`
|
||||
HappenedAt time.Time `gorm:"not null;comment:业务发生时间"`
|
||||
HappenedAt time.Time `gorm:"primaryKey;comment:业务发生时间"`
|
||||
Remarks string `gorm:"comment:备注, 如主动领取的理由等"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
}
|
||||
|
||||
func (RawMaterialStockLog) TableName() string {
|
||||
return "raw_material_stock_logs"
|
||||
}
|
||||
|
||||
// FeedFormula 代表饲料配方。
|
||||
@@ -63,6 +81,10 @@ type FeedFormula struct {
|
||||
Components []FeedFormulaComponent `gorm:"foreignKey:FeedFormulaID"`
|
||||
}
|
||||
|
||||
func (FeedFormula) TableName() string {
|
||||
return "feed_formulas"
|
||||
}
|
||||
|
||||
// FeedFormulaComponent 代表配方中的一种原料及其占比。
|
||||
type FeedFormulaComponent struct {
|
||||
gorm.Model
|
||||
@@ -72,17 +94,28 @@ type FeedFormulaComponent struct {
|
||||
Percentage float64 `gorm:"not null;comment:该原料在配方中的百分比 (0-1.0)"`
|
||||
}
|
||||
|
||||
func (FeedFormulaComponent) TableName() string {
|
||||
return "feed_formula_components"
|
||||
}
|
||||
|
||||
// FeedUsageRecord 代表饲料使用记录。
|
||||
// 应用层逻辑:当一条使用记录被创建时,应根据其使用的 FeedFormula,
|
||||
// 计算出每种 RawMaterial 的消耗量,并在 RawMaterialStockLog 中创建对应的出库记录。
|
||||
type FeedUsageRecord struct {
|
||||
gorm.Model
|
||||
ID uint `gorm:"primaryKey"`
|
||||
PenID uint `gorm:"not null;index;comment:关联的猪栏ID"`
|
||||
Pen Pen `gorm:"foreignKey:PenID"`
|
||||
FeedFormulaID uint `gorm:"not null;index;comment:使用的饲料配方ID"`
|
||||
FeedFormula FeedFormula `gorm:"foreignKey:FeedFormulaID"`
|
||||
Amount float64 `gorm:"not null;comment:使用数量, 单位: g"`
|
||||
RecordedAt time.Time `gorm:"not null;comment:记录时间"`
|
||||
RecordedAt time.Time `gorm:"primaryKey;comment:记录时间"`
|
||||
OperatorID uint `gorm:"not null;comment:操作员"`
|
||||
Remarks string `gorm:"comment:备注, 如 '例行喂料, 弱猪补料' 等"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
}
|
||||
|
||||
func (FeedUsageRecord) TableName() string {
|
||||
return "feed_usage_records"
|
||||
}
|
||||
|
||||
@@ -67,6 +67,10 @@ type Medication struct {
|
||||
Instructions datatypes.JSON `gorm:"type:jsonb;comment:使用说明" json:"instructions"`
|
||||
}
|
||||
|
||||
func (Medication) TableName() string {
|
||||
return "medications"
|
||||
}
|
||||
|
||||
// MedicationReasonType 定义了用药原因
|
||||
type MedicationReasonType string
|
||||
|
||||
@@ -78,7 +82,7 @@ const (
|
||||
|
||||
// GroupMedicationLog 记录了对整个猪批次的用药情况
|
||||
type GroupMedicationLog struct {
|
||||
gorm.Model
|
||||
ID uint `gorm:"primaryKey"`
|
||||
PigBatchID uint `gorm:"not null;index;comment:关联的猪批次ID"`
|
||||
MedicationID uint `gorm:"not null;index;comment:关联的药品ID"`
|
||||
Medication Medication `gorm:"foreignKey:MedicationID"` // 预加载药品信息
|
||||
@@ -87,5 +91,12 @@ type GroupMedicationLog struct {
|
||||
Reason MedicationReasonType `gorm:"size:20;not null;comment:用药原因"`
|
||||
Description string `gorm:"size:255;comment:具体描述,如'治疗呼吸道病'"`
|
||||
Operator string `gorm:"size:50;comment:操作员"`
|
||||
HappenedAt time.Time `gorm:"not null;default:CURRENT_TIMESTAMP;comment:用药时间"`
|
||||
HappenedAt time.Time `gorm:"primaryKey;comment:用药时间"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
}
|
||||
|
||||
func (GroupMedicationLog) TableName() string {
|
||||
return "group_medication_logs"
|
||||
}
|
||||
|
||||
@@ -12,20 +12,45 @@ import (
|
||||
// 这个函数用于在数据库初始化时自动迁移所有的表结构。
|
||||
func GetAllModels() []interface{} {
|
||||
return []interface{}{
|
||||
// Core Models
|
||||
&User{},
|
||||
&UserActionLog{},
|
||||
|
||||
// Device Models
|
||||
&Device{},
|
||||
&AreaController{},
|
||||
&DeviceTemplate{},
|
||||
&SensorData{},
|
||||
&DeviceCommandLog{},
|
||||
|
||||
// Plan & Task Models
|
||||
&Plan{},
|
||||
&SubPlan{},
|
||||
&Task{},
|
||||
&PlanExecutionLog{},
|
||||
&TaskExecutionLog{},
|
||||
&PendingTask{},
|
||||
&SensorData{},
|
||||
&DeviceCommandLog{},
|
||||
&PendingCollection{},
|
||||
&AreaController{},
|
||||
&DeviceTemplate{},
|
||||
&UserActionLog{},
|
||||
|
||||
// Farm Asset Models
|
||||
&PigHouse{},
|
||||
&Pen{},
|
||||
|
||||
// Pig & Batch Models
|
||||
&PigBatch{},
|
||||
&PigBatchLog{},
|
||||
|
||||
// Feed Models
|
||||
&RawMaterial{},
|
||||
&RawMaterialPurchase{},
|
||||
&RawMaterialStockLog{},
|
||||
&FeedFormula{},
|
||||
&FeedFormulaComponent{},
|
||||
&FeedUsageRecord{},
|
||||
|
||||
// Medication Models
|
||||
&Medication{},
|
||||
&GroupMedicationLog{},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,10 @@ type PigBatch struct {
|
||||
Pens []Pen `gorm:"foreignKey:PigBatchID;comment:所在圈舍ID"`
|
||||
}
|
||||
|
||||
func (PigBatch) TableName() string {
|
||||
return "pig_batches"
|
||||
}
|
||||
|
||||
// LogChangeType 定义了猪批次数量变更的类型
|
||||
type LogChangeType string
|
||||
|
||||
@@ -60,7 +64,7 @@ const (
|
||||
|
||||
// PigBatchLog 记录了猪批次数量或状态的每一次变更
|
||||
type PigBatchLog struct {
|
||||
gorm.Model
|
||||
ID uint `gorm:"primaryKey"`
|
||||
PigBatchID uint `gorm:"not null;index;comment:关联的猪批次ID"`
|
||||
ChangeType LogChangeType `gorm:"size:20;not null;comment:变更类型"`
|
||||
ChangeCount int `gorm:"not null;comment:数量变化,负数表示减少"`
|
||||
@@ -70,5 +74,12 @@ type PigBatchLog struct {
|
||||
BeforeSickCount int `gorm:"not null;comment:变更前病猪数"`
|
||||
AfterSickCount int `gorm:"not null;comment:变更后病猪数"`
|
||||
Operator string `gorm:"size:50;comment:操作员"`
|
||||
HappenedAt time.Time `gorm:"not null;default:CURRENT_TIMESTAMP;comment:事件发生时间"`
|
||||
HappenedAt time.Time `gorm:"primaryKey;comment:事件发生时间"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
}
|
||||
|
||||
func (PigBatchLog) TableName() string {
|
||||
return "pig_batch_logs"
|
||||
}
|
||||
|
||||
157
internal/infra/repository/pig_farm_repository.go
Normal file
157
internal/infra/repository/pig_farm_repository.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrHouseContainsPens = errors.New("cannot delete a pig house that still contains pens")
|
||||
ErrHouseNotFound = errors.New("the specified pig house does not exist")
|
||||
)
|
||||
|
||||
// PigFarmRepository 定义了与猪场资产(猪舍、猪栏)相关的数据库操作接口
|
||||
type PigFarmRepository interface {
|
||||
// PigHouse methods
|
||||
CreatePigHouse(house *models.PigHouse) error
|
||||
GetPigHouseByID(id uint) (*models.PigHouse, error)
|
||||
ListPigHouses() ([]models.PigHouse, error)
|
||||
UpdatePigHouse(house *models.PigHouse) error
|
||||
DeletePigHouse(id uint) error
|
||||
|
||||
// Pen methods
|
||||
CreatePen(pen *models.Pen) error
|
||||
GetPenByID(id uint) (*models.Pen, error)
|
||||
ListPens() ([]models.Pen, error)
|
||||
UpdatePen(pen *models.Pen) error
|
||||
DeletePen(id uint) error
|
||||
}
|
||||
|
||||
// gormPigFarmRepository 是 PigFarmRepository 的 GORM 实现
|
||||
type gormPigFarmRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewGormPigFarmRepository 创建一个新的 PigFarmRepository GORM 实现实例
|
||||
func NewGormPigFarmRepository(db *gorm.DB) PigFarmRepository {
|
||||
return &gormPigFarmRepository{db: db}
|
||||
}
|
||||
|
||||
// --- PigHouse Implementation ---
|
||||
|
||||
func (r *gormPigFarmRepository) CreatePigHouse(house *models.PigHouse) error {
|
||||
return r.db.Create(house).Error
|
||||
}
|
||||
|
||||
func (r *gormPigFarmRepository) GetPigHouseByID(id uint) (*models.PigHouse, error) {
|
||||
var house models.PigHouse
|
||||
if err := r.db.First(&house, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &house, nil
|
||||
}
|
||||
|
||||
func (r *gormPigFarmRepository) ListPigHouses() ([]models.PigHouse, error) {
|
||||
var houses []models.PigHouse
|
||||
if err := r.db.Find(&houses).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return houses, nil
|
||||
}
|
||||
|
||||
func (r *gormPigFarmRepository) UpdatePigHouse(house *models.PigHouse) error {
|
||||
result := r.db.Model(&models.PigHouse{}).Where("id = ?", house.ID).Updates(house)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return gorm.ErrRecordNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *gormPigFarmRepository) DeletePigHouse(id uint) error {
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
var penCount int64
|
||||
if err := tx.Model(&models.Pen{}).Where("house_id = ?", id).Count(&penCount).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if penCount > 0 {
|
||||
return ErrHouseContainsPens
|
||||
}
|
||||
|
||||
result := tx.Delete(&models.PigHouse{}, id)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return gorm.ErrRecordNotFound
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// --- Pen Implementation ---
|
||||
|
||||
func (r *gormPigFarmRepository) CreatePen(pen *models.Pen) error {
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
// 验证所属猪舍是否存在
|
||||
if err := tx.First(&models.PigHouse{}, pen.HouseID).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return ErrHouseNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
return tx.Create(pen).Error
|
||||
})
|
||||
}
|
||||
|
||||
func (r *gormPigFarmRepository) GetPenByID(id uint) (*models.Pen, error) {
|
||||
var pen models.Pen
|
||||
if err := r.db.First(&pen, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pen, nil
|
||||
}
|
||||
|
||||
func (r *gormPigFarmRepository) ListPens() ([]models.Pen, error) {
|
||||
var pens []models.Pen
|
||||
if err := r.db.Find(&pens).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pens, nil
|
||||
}
|
||||
|
||||
func (r *gormPigFarmRepository) UpdatePen(pen *models.Pen) error {
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
// 验证所属猪舍是否存在
|
||||
if err := tx.First(&models.PigHouse{}, pen.HouseID).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return ErrHouseNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
result := tx.Model(&models.Pen{}).Where("id = ?", pen.ID).Updates(pen)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return gorm.ErrRecordNotFound
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *gormPigFarmRepository) DeletePen(id uint) error {
|
||||
result := r.db.Delete(&models.Pen{}, id)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return gorm.ErrRecordNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user