Files
pig-farm-controller/internal/infra/repository/nutrient_repository.go

135 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repository
import (
"context"
"errors"
"fmt"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"gorm.io/gorm"
)
// NutrientRepository 定义了与营养种类相关的数据库操作接口
type NutrientRepository interface {
CreateNutrient(ctx context.Context, nutrient *models.Nutrient) error
GetNutrientByID(ctx context.Context, id uint32) (*models.Nutrient, error)
GetNutrientByName(ctx context.Context, name string) (*models.Nutrient, error)
ListNutrients(ctx context.Context, page, pageSize int) ([]models.Nutrient, int64, error)
UpdateNutrient(ctx context.Context, nutrient *models.Nutrient) error
DeleteNutrient(ctx context.Context, id uint32) error
}
// gormNutrientRepository 是 NutrientRepository 的 GORM 实现
type gormNutrientRepository struct {
ctx context.Context
db *gorm.DB
}
// NewGormNutrientRepository 创建一个新的 NutrientRepository GORM 实现实例
func NewGormNutrientRepository(ctx context.Context, db *gorm.DB) NutrientRepository {
return &gormNutrientRepository{ctx: ctx, db: db}
}
// CreateNutrient 创建一个新的营养种类
func (r *gormNutrientRepository) CreateNutrient(ctx context.Context, nutrient *models.Nutrient) error {
repoCtx := logs.AddFuncName(ctx, r.ctx, "CreateNutrient")
return r.db.WithContext(repoCtx).Create(nutrient).Error
}
// GetNutrientByID 根据ID获取单个营养种类
func (r *gormNutrientRepository) GetNutrientByID(ctx context.Context, id uint32) (*models.Nutrient, error) {
repoCtx := logs.AddFuncName(ctx, r.ctx, "GetNutrientByID")
var nutrient models.Nutrient
if err := r.db.WithContext(repoCtx).First(&nutrient, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil // 记录未找到不应视为错误
}
return nil, err
}
return &nutrient, nil
}
// GetNutrientByName 根据名称获取单个营养种类
func (r *gormNutrientRepository) GetNutrientByName(ctx context.Context, name string) (*models.Nutrient, error) {
repoCtx := logs.AddFuncName(ctx, r.ctx, "GetNutrientByName")
var nutrient models.Nutrient
if err := r.db.WithContext(repoCtx).Where("name = ?", name).First(&nutrient).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil // 记录未找到不应视为错误
}
return nil, err
}
return &nutrient, nil
}
// ListNutrients 列出所有营养种类(分页)
func (r *gormNutrientRepository) ListNutrients(ctx context.Context, page, pageSize int) ([]models.Nutrient, int64, error) {
repoCtx := logs.AddFuncName(ctx, r.ctx, "ListNutrients")
var nutrients []models.Nutrient
var total int64
db := r.db.WithContext(repoCtx).Model(&models.Nutrient{})
// 首先计算总数
if err := db.Count(&total).Error; err != nil {
return nil, 0, err
}
// 然后应用分页并获取数据
offset := (page - 1) * pageSize
if err := db.Offset(offset).Limit(pageSize).Find(&nutrients).Error; err != nil {
return nil, 0, err
}
return nutrients, total, nil
}
// UpdateNutrient 更新一个营养种类
func (r *gormNutrientRepository) UpdateNutrient(ctx context.Context, nutrient *models.Nutrient) error {
repoCtx := logs.AddFuncName(ctx, r.ctx, "UpdateNutrient")
// 使用 map 更新以避免 GORM 的零值问题,并确保只更新指定字段
updateData := map[string]interface{}{
"name": nutrient.Name,
"description": nutrient.Description,
}
result := r.db.WithContext(repoCtx).Model(&models.Nutrient{}).Where("id = ?", nutrient.ID).Updates(updateData)
if result.Error != nil {
return result.Error
}
if result.RowsAffected == 0 {
return fmt.Errorf("未找到要更新的营养种类ID: %d", nutrient.ID)
}
return nil
}
// DeleteNutrient 根据ID删除一个营养种类并级联软删除关联的 RawMaterialNutrient 记录
func (r *gormNutrientRepository) DeleteNutrient(ctx context.Context, id uint32) error {
repoCtx := logs.AddFuncName(ctx, r.ctx, "DeleteNutrient")
return r.db.WithContext(repoCtx).Transaction(func(tx *gorm.DB) error {
// 1. 查找 Nutrient 记录,确保其存在
var nutrient models.Nutrient
if err := tx.First(&nutrient, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("未找到要删除的营养种类ID: %d", id)
}
return fmt.Errorf("查询营养种类失败: %w", err)
}
// 2. 软删除所有关联的 RawMaterialNutrient 记录
if err := tx.Where("nutrient_id = ?", id).Delete(&models.RawMaterialNutrient{}).Error; err != nil {
return fmt.Errorf("软删除关联的原料营养素记录失败: %w", err)
}
// 3. 软删除 Nutrient 记录本身
if err := tx.Delete(&nutrient).Error; err != nil {
return fmt.Errorf("软删除营养种类失败: %w", err)
}
return nil
})
}