package repository import ( "context" "time" "git.huangwc.com/pig/pig-farm-controller/internal/infra/logs" "git.huangwc.com/pig/pig-farm-controller/internal/infra/models" "gorm.io/gorm" ) // PigBatchRepository 定义了与猪批次相关的数据库操作接口 type PigBatchRepository interface { CreatePigBatch(ctx context.Context, batch *models.PigBatch) (*models.PigBatch, error) CreatePigBatchTx(ctx context.Context, tx *gorm.DB, batch *models.PigBatch) (*models.PigBatch, error) GetPigBatchByID(ctx context.Context, id uint) (*models.PigBatch, error) GetPigBatchByIDTx(ctx context.Context, tx *gorm.DB, id uint) (*models.PigBatch, error) // UpdatePigBatch 更新一个猪批次,返回更新后的批次、受影响的行数和错误 UpdatePigBatch(ctx context.Context, batch *models.PigBatch) (*models.PigBatch, int64, error) // DeletePigBatch 根据ID删除一个猪批次,返回受影响的行数和错误 DeletePigBatch(ctx context.Context, id uint) (int64, error) DeletePigBatchTx(ctx context.Context, tx *gorm.DB, id uint) (int64, error) ListPigBatches(ctx context.Context, isActive *bool) ([]*models.PigBatch, error) // ListWeighingBatches 支持分页和过滤的批次称重列表查询 ListWeighingBatches(ctx context.Context, opts WeighingBatchListOptions, page, pageSize int) ([]models.WeighingBatch, int64, error) // ListWeighingRecords 支持分页和过滤的单次称重记录列表查询 ListWeighingRecords(ctx context.Context, opts WeighingRecordListOptions, page, pageSize int) ([]models.WeighingRecord, int64, error) } // WeighingBatchListOptions 定义了查询批次称重记录时的可选参数 type WeighingBatchListOptions struct { PigBatchID *uint StartTime *time.Time // 基于 weighing_time 字段 EndTime *time.Time // 基于 weighing_time 字段 OrderBy string // 例如 "weighing_time asc" } // WeighingRecordListOptions 定义了查询单次称重记录时的可选参数 type WeighingRecordListOptions struct { WeighingBatchID *uint PenID *uint OperatorID *uint StartTime *time.Time // 基于 weighing_time 字段 EndTime *time.Time // 基于 weighing_time 字段 OrderBy string // 例如 "weighing_time asc" } // gormPigBatchRepository 是 PigBatchRepository 的 GORM 实现 type gormPigBatchRepository struct { ctx context.Context db *gorm.DB } // NewGormPigBatchRepository 创建一个新的 PigBatchRepository GORM 实现实例 func NewGormPigBatchRepository(ctx context.Context, db *gorm.DB) PigBatchRepository { return &gormPigBatchRepository{ctx: ctx, db: db} } // CreatePigBatch 创建一个新的猪批次 func (r *gormPigBatchRepository) CreatePigBatch(ctx context.Context, batch *models.PigBatch) (*models.PigBatch, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "CreatePigBatch") return r.CreatePigBatchTx(repoCtx, r.db, batch) } // CreatePigBatchTx 在指定的事务中,创建一个新的猪批次 func (r *gormPigBatchRepository) CreatePigBatchTx(ctx context.Context, tx *gorm.DB, batch *models.PigBatch) (*models.PigBatch, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "CreatePigBatchTx") if err := tx.WithContext(repoCtx).Create(batch).Error; err != nil { return nil, err } return batch, nil } // GetPigBatchByID 根据ID获取单个猪批次 func (r *gormPigBatchRepository) GetPigBatchByID(ctx context.Context, id uint) (*models.PigBatch, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "GetPigBatchByID") return r.GetPigBatchByIDTx(repoCtx, r.db, id) } // UpdatePigBatch 更新一个猪批次 func (r *gormPigBatchRepository) UpdatePigBatch(ctx context.Context, batch *models.PigBatch) (*models.PigBatch, int64, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "UpdatePigBatch") result := r.db.WithContext(repoCtx).Model(&models.PigBatch{}).Where("id = ?", batch.ID).Updates(batch) if result.Error != nil { return nil, 0, result.Error } // 返回更新后的批次、受影响的行数和错误 return batch, result.RowsAffected, nil } // DeletePigBatch 根据ID删除一个猪批次 (GORM 会执行软删除) func (r *gormPigBatchRepository) DeletePigBatch(ctx context.Context, id uint) (int64, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "DeletePigBatch") return r.DeletePigBatchTx(repoCtx, r.db, id) } func (r *gormPigBatchRepository) DeletePigBatchTx(ctx context.Context, tx *gorm.DB, id uint) (int64, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "DeletePigBatchTx") result := tx.WithContext(repoCtx).Delete(&models.PigBatch{}, id) if result.Error != nil { return 0, result.Error } // 返回受影响的行数和错误 return result.RowsAffected, nil } // ListPigBatches 批量查询猪批次,支持根据 IsActive 筛选 func (r *gormPigBatchRepository) ListPigBatches(ctx context.Context, isActive *bool) ([]*models.PigBatch, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "ListPigBatches") var batches []*models.PigBatch query := r.db.WithContext(repoCtx).Model(&models.PigBatch{}) if isActive != nil { if *isActive { // 查询活跃的批次:状态不是已出售或已归档 query = query.Where("status NOT IN (?) ", []models.PigBatchStatus{models.BatchStatusSold, models.BatchStatusArchived}) } else { // 查询非活跃的批次:状态是已出售或已归档 query = query.Where("status IN (?) ", []models.PigBatchStatus{models.BatchStatusSold, models.BatchStatusArchived}) } } if err := query.Find(&batches).Error; err != nil { return nil, err } return batches, nil } // GetPigBatchByIDTx 在指定的事务中,通过ID获取单个猪批次 func (r *gormPigBatchRepository) GetPigBatchByIDTx(ctx context.Context, tx *gorm.DB, id uint) (*models.PigBatch, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "GetPigBatchByIDTx") var batch models.PigBatch if err := tx.WithContext(repoCtx).First(&batch, id).Error; err != nil { return nil, err } return &batch, nil } // ListWeighingBatches 实现了分页和过滤查询批次称重记录的功能 func (r *gormPigBatchRepository) ListWeighingBatches(ctx context.Context, opts WeighingBatchListOptions, page, pageSize int) ([]models.WeighingBatch, int64, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "ListWeighingBatches") if page <= 0 || pageSize <= 0 { return nil, 0, ErrInvalidPagination } var results []models.WeighingBatch var total int64 query := r.db.WithContext(repoCtx).Model(&models.WeighingBatch{}) if opts.PigBatchID != nil { query = query.Where("pig_batch_id = ?", *opts.PigBatchID) } if opts.StartTime != nil { query = query.Where("weighing_time >= ?", *opts.StartTime) } if opts.EndTime != nil { query = query.Where("weighing_time <= ?", *opts.EndTime) } if err := query.Count(&total).Error; err != nil { return nil, 0, err } orderBy := "weighing_time DESC" if opts.OrderBy != "" { orderBy = opts.OrderBy } query = query.Order(orderBy) offset := (page - 1) * pageSize err := query.Limit(pageSize).Offset(offset).Find(&results).Error return results, total, err } // ListWeighingRecords 实现了分页和过滤查询单次称重记录的功能 func (r *gormPigBatchRepository) ListWeighingRecords(ctx context.Context, opts WeighingRecordListOptions, page, pageSize int) ([]models.WeighingRecord, int64, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "ListWeighingRecords") if page <= 0 || pageSize <= 0 { return nil, 0, ErrInvalidPagination } var results []models.WeighingRecord var total int64 query := r.db.WithContext(repoCtx).Model(&models.WeighingRecord{}) if opts.WeighingBatchID != nil { query = query.Where("weighing_batch_id = ?", *opts.WeighingBatchID) } if opts.PenID != nil { query = query.Where("pen_id = ?", *opts.PenID) } if opts.OperatorID != nil { query = query.Where("operator_id = ?", *opts.OperatorID) } if opts.StartTime != nil { query = query.Where("weighing_time >= ?", *opts.StartTime) } if opts.EndTime != nil { query = query.Where("weighing_time <= ?", *opts.EndTime) } if err := query.Count(&total).Error; err != nil { return nil, 0, err } orderBy := "weighing_time DESC" if opts.OrderBy != "" { orderBy = opts.OrderBy } query = query.Order(orderBy) offset := (page - 1) * pageSize err := query.Limit(pageSize).Offset(offset).Find(&results).Error return results, total, err }