diff --git a/internal/domain/pig/pen_transfer_manager.go b/internal/domain/pig/pen_transfer_manager.go index 99bc80d..9de7fbd 100644 --- a/internal/domain/pig/pen_transfer_manager.go +++ b/internal/domain/pig/pen_transfer_manager.go @@ -29,6 +29,9 @@ type PigPenTransferManager interface { // GetTotalPigsInPensForBatchTx 计算指定猪群下所有猪栏的当前总存栏数 GetTotalPigsInPensForBatchTx(tx *gorm.DB, batchID uint) (int, error) + + // ReleasePen 将猪栏的猪群归属移除,并将其状态标记为空闲。 + ReleasePen(tx *gorm.DB, penID uint) error } // pigPenTransferManager 是 PigPenTransferManager 接口的具体实现。 @@ -143,3 +146,30 @@ func (s *pigPenTransferManager) GetTotalPigsInPensForBatchTx(tx *gorm.DB, batchI return totalPigs, nil } + +// ReleasePen 将猪栏的猪群归属移除,并将其状态标记为空闲。 +// 此操作通常在猪栏被清空后调用。 +func (s *pigPenTransferManager) ReleasePen(tx *gorm.DB, penID uint) error { + // 1. 获取猪栏信息 + pen, err := s.penRepo.GetPenByIDTx(tx, penID) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return fmt.Errorf("猪栏 %d 不存在: %w", penID, ErrPenNotFound) + } + return fmt.Errorf("获取猪栏 %d 信息失败: %w", penID, err) + } + + // 2. 更新猪栏字段 + // 将 pig_batch_id 设置为 nil (SQL NULL) + // 将 status 设置为 PenStatusEmpty + updates := map[string]interface{}{ + "pig_batch_id": nil, // 使用 nil 来表示 SQL NULL + "status": models.PenStatusEmpty, + } + + if err := s.penRepo.UpdatePenFieldsTx(tx, penID, updates); err != nil { + return fmt.Errorf("释放猪栏 %v 失败: %w", pen.PenNumber, err) + } + + return nil +} diff --git a/internal/domain/pig/pig_batch_service.go b/internal/domain/pig/pig_batch_service.go index 55cfc15..cd6383e 100644 --- a/internal/domain/pig/pig_batch_service.go +++ b/internal/domain/pig/pig_batch_service.go @@ -79,27 +79,46 @@ func (s *pigBatchService) UpdatePigBatch(batch *models.PigBatch) (*models.PigBat // DeletePigBatch 实现了删除猪批次的逻辑,并包含业务规则校验。 func (s *pigBatchService) DeletePigBatch(id uint) error { - // 1. 获取猪批次信息 - batch, err := s.GetPigBatch(id) // 复用 GetPigBatch 方法 - if err != nil { - return err // GetPigBatch 已经处理了 ErrRecordNotFound 的情况 - } + return s.uow.ExecuteInTransaction(func(tx *gorm.DB) error { + // 1. 获取猪批次信息 + batch, err := s.pigBatchRepo.GetPigBatchByIDTx(tx, id) // 使用事务内方法 + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return ErrPigBatchNotFound + } + return err + } - // 2. 核心业务规则:检查猪批次是否为活跃状态 - if batch.IsActive() { - return ErrPigBatchActive // 如果活跃,则不允许删除 - } + // 2. 核心业务规则:检查猪批次是否为活跃状态 + if batch.IsActive() { + return ErrPigBatchActive // 如果活跃,则不允许删除 + } - // 3. 执行删除 - rowsAffected, err := s.pigBatchRepo.DeletePigBatch(id) - if err != nil { - return err - } - if rowsAffected == 0 { - return ErrPigBatchNotFound - } + // 3. 释放所有关联的猪栏 + // 获取该批次下所有猪栏 + pensInBatch, err := s.transferSvc.GetPensByBatchID(tx, id) + if err != nil { + return fmt.Errorf("获取猪批次 %d 关联猪栏失败: %w", id, err) + } - return nil + // 逐一释放猪栏 + for _, pen := range pensInBatch { + if err := s.transferSvc.ReleasePen(tx, pen.ID); err != nil { + return fmt.Errorf("释放猪栏 %d 失败: %w", pen.ID, err) + } + } + + // 4. 执行删除猪批次 + rowsAffected, err := s.pigBatchRepo.DeletePigBatchTx(tx, id) + if err != nil { + return err + } + if rowsAffected == 0 { + return ErrPigBatchNotFound + } + + return nil + }) } // ListPigBatches 实现了批量查询猪批次的逻辑。 diff --git a/internal/infra/repository/pig_batch_repository.go b/internal/infra/repository/pig_batch_repository.go index 3b57b72..1c46c5a 100644 --- a/internal/infra/repository/pig_batch_repository.go +++ b/internal/infra/repository/pig_batch_repository.go @@ -15,6 +15,7 @@ type PigBatchRepository interface { UpdatePigBatch(batch *models.PigBatch) (*models.PigBatch, int64, error) // DeletePigBatch 根据ID删除一个猪批次,返回受影响的行数和错误 DeletePigBatch(id uint) (int64, error) + DeletePigBatchTx(tx *gorm.DB, id uint) (int64, error) ListPigBatches(isActive *bool) ([]*models.PigBatch, error) } @@ -58,7 +59,11 @@ func (r *gormPigBatchRepository) UpdatePigBatch(batch *models.PigBatch) (*models // DeletePigBatch 根据ID删除一个猪批次 (GORM 会执行软删除) func (r *gormPigBatchRepository) DeletePigBatch(id uint) (int64, error) { - result := r.db.Delete(&models.PigBatch{}, id) + return r.DeletePigBatchTx(r.db, id) +} + +func (r *gormPigBatchRepository) DeletePigBatchTx(tx *gorm.DB, id uint) (int64, error) { + result := tx.Delete(&models.PigBatch{}, id) if result.Error != nil { return 0, result.Error }