package service import ( "errors" "fmt" "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) (*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 // UpdatePenStatus 更新猪栏状态 UpdatePenStatus(id uint, newStatus models.PenStatus) (*models.Pen, error) } type pigFarmService struct { logger *logs.Logger farmRepository repository.PigFarmRepository penRepository repository.PigPenRepository batchRepository repository.PigBatchRepository uow repository.UnitOfWork // 工作单元,用于事务管理 } // NewPigFarmService 创建一个新的 PigFarmService 实例 func NewPigFarmService(farmRepository repository.PigFarmRepository, penRepository repository.PigPenRepository, batchRepository repository.PigBatchRepository, uow repository.UnitOfWork, logger *logs.Logger) PigFarmService { return &pigFarmService{ logger: logger, farmRepository: farmRepository, penRepository: penRepository, batchRepository: batchRepository, uow: uow, } } // --- PigHouse Implementation --- func (s *pigFarmService) CreatePigHouse(name, description string) (*models.PigHouse, error) { house := &models.PigHouse{ Name: name, Description: description, } err := s.farmRepository.CreatePigHouse(house) return house, err } func (s *pigFarmService) GetPigHouseByID(id uint) (*models.PigHouse, error) { return s.farmRepository.GetPigHouseByID(id) } func (s *pigFarmService) ListPigHouses() ([]models.PigHouse, error) { return s.farmRepository.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, } rowsAffected, err := s.farmRepository.UpdatePigHouse(house) if err != nil { return nil, err } if rowsAffected == 0 { return nil, ErrHouseNotFound } // 返回更新后的完整信息 return s.farmRepository.GetPigHouseByID(id) } func (s *pigFarmService) DeletePigHouse(id uint) error { // 业务逻辑:检查猪舍是否包含猪栏 penCount, err := s.farmRepository.CountPensInHouse(id) if err != nil { return err } if penCount > 0 { return ErrHouseContainsPens } // 调用仓库层进行删除 rowsAffected, err := s.farmRepository.DeletePigHouse(id) if err != nil { return err } if rowsAffected == 0 { return ErrHouseNotFound } return nil } // --- Pen Implementation --- func (s *pigFarmService) CreatePen(penNumber string, houseID uint, capacity int) (*models.Pen, error) { // 业务逻辑:验证所属猪舍是否存在 _, err := s.farmRepository.GetPigHouseByID(houseID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrHouseNotFound } return nil, err } pen := &models.Pen{ PenNumber: penNumber, HouseID: houseID, Capacity: capacity, Status: models.PenStatusEmpty, } err = s.penRepository.CreatePen(pen) return pen, err } func (s *pigFarmService) GetPenByID(id uint) (*models.Pen, error) { return s.penRepository.GetPenByID(id) } func (s *pigFarmService) ListPens() ([]models.Pen, error) { return s.penRepository.ListPens() } func (s *pigFarmService) UpdatePen(id uint, penNumber string, houseID uint, capacity int, status models.PenStatus) (*models.Pen, error) { // 业务逻辑:验证所属猪舍是否存在 _, err := s.farmRepository.GetPigHouseByID(houseID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrHouseNotFound } return nil, err } pen := &models.Pen{ Model: gorm.Model{ID: id}, PenNumber: penNumber, HouseID: houseID, Capacity: capacity, Status: status, } rowsAffected, err := s.penRepository.UpdatePen(pen) if err != nil { return nil, err } if rowsAffected == 0 { return nil, ErrPenNotFound } // 返回更新后的完整信息 return s.penRepository.GetPenByID(id) } func (s *pigFarmService) DeletePen(id uint) error { // 业务逻辑:检查猪栏是否被活跃批次使用 pen, err := s.penRepository.GetPenByID(id) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return ErrPenNotFound // 猪栏不存在 } return err } // 检查猪栏是否关联了活跃批次 // 注意:pen.PigBatchID 是指针类型,需要检查是否为 nil if pen.PigBatchID != nil && *pen.PigBatchID != 0 { pigBatch, err := s.batchRepository.GetPigBatchByID(*pen.PigBatchID) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return err } // 如果批次活跃,则不能删除猪栏 if pigBatch != nil && pigBatch.IsActive() { return ErrPenInUse } } // 调用仓库层进行删除 rowsAffected, err := s.penRepository.DeletePen(id) if err != nil { return err } if rowsAffected == 0 { return ErrPenNotFound } return nil } // UpdatePenStatus 更新猪栏状态 func (s *pigFarmService) UpdatePenStatus(id uint, newStatus models.PenStatus) (*models.Pen, error) { var updatedPen *models.Pen err := s.uow.ExecuteInTransaction(func(tx *gorm.DB) error { pen, err := s.penRepository.GetPenByIDTx(tx, id) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return ErrPenNotFound } s.logger.Errorf("更新猪栏状态失败: 获取猪栏 %d 信息错误: %v", id, err) return fmt.Errorf("获取猪栏 %d 信息失败: %w", id, err) } // 业务逻辑:根据猪栏的 PigBatchID 和当前状态,判断是否允许设置为 newStatus if pen.PigBatchID != nil && *pen.PigBatchID != 0 { // 猪栏已被批次使用 if newStatus == models.PenStatusEmpty { // 猪栏已被批次使用,不能直接设置为空闲 return ErrPenStatusInvalidForOccupiedPen } } else { // 猪栏未被批次使用 (PigBatchID == nil) if newStatus == models.PenStatusOccupied { // 猪栏未被批次使用,不能设置为使用中 return ErrPenStatusInvalidForUnoccupiedPen } } // 如果新状态与旧状态相同,则无需更新 if pen.Status == newStatus { updatedPen = pen // 返回原始猪栏,因为没有实际更新 return nil } updates := map[string]interface{}{ "status": newStatus, } if err := s.penRepository.UpdatePenFields(tx, id, updates); err != nil { s.logger.Errorf("更新猪栏 %d 状态失败: %v", id, err) return fmt.Errorf("更新猪栏 %d 状态失败: %w", id, err) } // 获取更新后的猪栏信息 updatedPen, err = s.penRepository.GetPenByIDTx(tx, id) if err != nil { s.logger.Errorf("更新猪栏状态后获取猪栏 %d 信息失败: %v", id, err) return fmt.Errorf("更新猪栏状态后获取猪栏 %d 信息失败: %w", id, err) } return nil }) if err != nil { return nil, err } return updatedPen, nil }