package service import ( "time" "git.huangwc.com/pig/pig-farm-controller/internal/app/dto" domain_pig "git.huangwc.com/pig/pig-farm-controller/internal/domain/pig" "git.huangwc.com/pig/pig-farm-controller/internal/infra/logs" "git.huangwc.com/pig/pig-farm-controller/internal/infra/models" ) // PigBatchService 接口定义保持不变,继续作为应用层对外的契约。 type PigBatchService interface { CreatePigBatch(operatorID uint, dto *dto.PigBatchCreateDTO) (*dto.PigBatchResponseDTO, error) GetPigBatch(id uint) (*dto.PigBatchResponseDTO, error) UpdatePigBatch(id uint, dto *dto.PigBatchUpdateDTO) (*dto.PigBatchResponseDTO, error) DeletePigBatch(id uint) error ListPigBatches(isActive *bool) ([]*dto.PigBatchResponseDTO, error) // Pig Pen Management AssignEmptyPensToBatch(batchID uint, penIDs []uint, operatorID uint) error ReclassifyPenToNewBatch(fromBatchID uint, toBatchID uint, penID uint, operatorID uint, remarks string) error RemoveEmptyPenFromBatch(batchID uint, penID uint) error MovePigsIntoPen(batchID uint, toPenID uint, quantity int, operatorID uint, remarks string) error // Trade Sub-service SellPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error BuyPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error // Transfer Sub-service TransferPigsAcrossBatches(sourceBatchID uint, destBatchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error TransferPigsWithinBatch(batchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error // Sick Pig Management RecordSickPigs(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error RecordSickPigRecovery(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error RecordSickPigDeath(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error RecordSickPigCull(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error // Normal Pig Management RecordDeath(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error RecordCull(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error } // pigBatchService 的实现现在依赖于领域服务接口。 type pigBatchService struct { logger *logs.Logger domainService domain_pig.PigBatchService // 依赖注入领域服务 } // NewPigBatchService 构造函数被修改,以注入领域服务。 func NewPigBatchService(domainService domain_pig.PigBatchService, logger *logs.Logger) PigBatchService { return &pigBatchService{ logger: logger, domainService: domainService, } } // toPigBatchResponseDTO 负责将领域模型转换为应用层DTO,这个职责保留在应用层。 func (s *pigBatchService) toPigBatchResponseDTO(batch *models.PigBatch, currentTotalQuantity, currentTotalPigsInPens int) *dto.PigBatchResponseDTO { if batch == nil { return nil } return &dto.PigBatchResponseDTO{ ID: batch.ID, BatchNumber: batch.BatchNumber, OriginType: batch.OriginType, StartDate: batch.StartDate, EndDate: batch.EndDate, InitialCount: batch.InitialCount, Status: batch.Status, IsActive: batch.IsActive(), CurrentTotalQuantity: currentTotalQuantity, CurrentTotalPigsInPens: currentTotalPigsInPens, CreateTime: batch.CreatedAt, UpdateTime: batch.UpdatedAt, } } // CreatePigBatch 现在将请求委托给领域服务处理。 func (s *pigBatchService) CreatePigBatch(operatorID uint, dto *dto.PigBatchCreateDTO) (*dto.PigBatchResponseDTO, error) { // 1. DTO -> 领域模型 batch := &models.PigBatch{ BatchNumber: dto.BatchNumber, OriginType: dto.OriginType, StartDate: dto.StartDate, InitialCount: dto.InitialCount, Status: dto.Status, } // 2. 调用领域服务 createdBatch, err := s.domainService.CreatePigBatch(operatorID, batch) if err != nil { s.logger.Errorf("应用层: 创建猪批次失败: %v", err) return nil, MapDomainError(err) } // 3. 领域模型 -> DTO return s.toPigBatchResponseDTO(createdBatch, dto.InitialCount, 0), nil } // GetPigBatch 从领域服务获取数据并转换为DTO,同时处理错误转换。 func (s *pigBatchService) GetPigBatch(id uint) (*dto.PigBatchResponseDTO, error) { batch, err := s.domainService.GetPigBatch(id) if err != nil { s.logger.Warnf("应用层: 获取猪批次失败, ID: %d, 错误: %v", id, err) return nil, MapDomainError(err) } currentTotalQuantity, err := s.domainService.GetCurrentPigQuantity(id) if err != nil { s.logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", id, err) return nil, MapDomainError(err) } currentTotalPigsInPens, err := s.domainService.GetTotalPigsInPensForBatch(id) if err != nil { s.logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", id, err) return nil, MapDomainError(err) } return s.toPigBatchResponseDTO(batch, currentTotalQuantity, currentTotalPigsInPens), nil } // UpdatePigBatch 协调获取、更新和保存的流程,并处理错误转换。 func (s *pigBatchService) UpdatePigBatch(id uint, dto *dto.PigBatchUpdateDTO) (*dto.PigBatchResponseDTO, error) { // 1. 先获取最新的领域模型 existingBatch, err := s.domainService.GetPigBatch(id) if err != nil { s.logger.Warnf("应用层: 更新猪批次失败,获取原批次信息错误, ID: %d, 错误: %v", id, err) return nil, MapDomainError(err) } // 2. 将DTO中的变更应用到模型上 if dto.BatchNumber != nil { existingBatch.BatchNumber = *dto.BatchNumber } if dto.OriginType != nil { existingBatch.OriginType = *dto.OriginType } if dto.StartDate != nil { existingBatch.StartDate = *dto.StartDate } if dto.EndDate != nil { existingBatch.EndDate = *dto.EndDate } if dto.InitialCount != nil { existingBatch.InitialCount = *dto.InitialCount } if dto.Status != nil { existingBatch.Status = *dto.Status } // 3. 调用领域服务执行更新 updatedBatch, err := s.domainService.UpdatePigBatch(existingBatch) if err != nil { s.logger.Errorf("应用层: 更新猪批次失败, ID: %d, 错误: %v", id, err) return nil, MapDomainError(err) } // 4. 填充猪群信息 currentTotalQuantity, err := s.domainService.GetCurrentPigQuantity(id) if err != nil { s.logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", id, err) return nil, MapDomainError(err) } currentTotalPigsInPens, err := s.domainService.GetTotalPigsInPensForBatch(id) if err != nil { s.logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", id, err) return nil, MapDomainError(err) } // 5. 转换并返回结果 return s.toPigBatchResponseDTO(updatedBatch, currentTotalQuantity, currentTotalPigsInPens), nil } // DeletePigBatch 将删除操作委托给领域服务,并转换领域错误为应用层错误。 func (s *pigBatchService) DeletePigBatch(id uint) error { err := s.domainService.DeletePigBatch(id) if err != nil { s.logger.Errorf("应用层: 删除猪批次失败, ID: %d, 错误: %v", id, err) return MapDomainError(err) } return nil } // ListPigBatches 从领域服务获取列表并进行转换。 func (s *pigBatchService) ListPigBatches(isActive *bool) ([]*dto.PigBatchResponseDTO, error) { batches, err := s.domainService.ListPigBatches(isActive) if err != nil { s.logger.Errorf("应用层: 批量查询猪批次失败: %v", err) return nil, MapDomainError(err) } var responseDTOs []*dto.PigBatchResponseDTO for _, batch := range batches { currentTotalQuantity, err := s.domainService.GetCurrentPigQuantity(batch.ID) if err != nil { s.logger.Warnf("应用层: 获取猪批次总数失败, ID: %d, 错误: %v", batch.ID, err) return nil, MapDomainError(err) } currentTotalPigsInPens, err := s.domainService.GetTotalPigsInPensForBatch(batch.ID) if err != nil { s.logger.Warnf("应用层: 获取猪批次存栏总数失败, ID: %d, 错误: %v", batch.ID, err) return nil, MapDomainError(err) } responseDTOs = append(responseDTOs, s.toPigBatchResponseDTO(batch, currentTotalQuantity, currentTotalPigsInPens)) } return responseDTOs, nil } // AssignEmptyPensToBatch 委托给领域服务 func (s *pigBatchService) AssignEmptyPensToBatch(batchID uint, penIDs []uint, operatorID uint) error { err := s.domainService.AssignEmptyPensToBatch(batchID, penIDs, operatorID) if err != nil { s.logger.Errorf("应用层: 为猪批次分配空栏失败, 批次ID: %d, 错误: %v", batchID, err) return MapDomainError(err) } return nil } // ReclassifyPenToNewBatch 委托给领域服务 func (s *pigBatchService) ReclassifyPenToNewBatch(fromBatchID uint, toBatchID uint, penID uint, operatorID uint, remarks string) error { err := s.domainService.ReclassifyPenToNewBatch(fromBatchID, toBatchID, penID, operatorID, remarks) if err != nil { s.logger.Errorf("应用层: 划拨猪栏到新批次失败, 源批次ID: %d, 错误: %v", fromBatchID, err) return MapDomainError(err) } return nil } // RemoveEmptyPenFromBatch 委托给领域服务 func (s *pigBatchService) RemoveEmptyPenFromBatch(batchID uint, penID uint) error { err := s.domainService.RemoveEmptyPenFromBatch(batchID, penID) if err != nil { s.logger.Errorf("应用层: 从猪批次移除空栏失败, 批次ID: %d, 猪栏ID: %d, 错误: %v", batchID, penID, err) return MapDomainError(err) } return nil } // MovePigsIntoPen 委托给领域服务 func (s *pigBatchService) MovePigsIntoPen(batchID uint, toPenID uint, quantity int, operatorID uint, remarks string) error { err := s.domainService.MovePigsIntoPen(batchID, toPenID, quantity, operatorID, remarks) if err != nil { s.logger.Errorf("应用层: 将猪只移入猪栏失败, 批次ID: %d, 目标猪栏ID: %d, 错误: %v", batchID, toPenID, err) return MapDomainError(err) } return nil } // SellPigs 委托给领域服务 func (s *pigBatchService) SellPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error { err := s.domainService.SellPigs(batchID, penID, quantity, unitPrice, tatalPrice, traderName, tradeDate, remarks, operatorID) if err != nil { s.logger.Errorf("应用层: 卖猪失败, 批次ID: %d, 错误: %v", batchID, err) return MapDomainError(err) } return nil } // BuyPigs 委托给领域服务 func (s *pigBatchService) BuyPigs(batchID uint, penID uint, quantity int, unitPrice float64, tatalPrice float64, traderName string, tradeDate time.Time, remarks string, operatorID uint) error { err := s.domainService.BuyPigs(batchID, penID, quantity, unitPrice, tatalPrice, traderName, tradeDate, remarks, operatorID) if err != nil { s.logger.Errorf("应用层: 买猪失败, 批次ID: %d, 错误: %v", batchID, err) return MapDomainError(err) } return nil } // TransferPigsAcrossBatches 委托给领域服务 func (s *pigBatchService) TransferPigsAcrossBatches(sourceBatchID uint, destBatchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error { err := s.domainService.TransferPigsAcrossBatches(sourceBatchID, destBatchID, fromPenID, toPenID, quantity, operatorID, remarks) if err != nil { s.logger.Errorf("应用层: 跨群调栏失败, 源批次ID: %d, 错误: %v", sourceBatchID, err) return MapDomainError(err) } return nil } // TransferPigsWithinBatch 委托给领域服务 func (s *pigBatchService) TransferPigsWithinBatch(batchID uint, fromPenID uint, toPenID uint, quantity uint, operatorID uint, remarks string) error { err := s.domainService.TransferPigsWithinBatch(batchID, fromPenID, toPenID, quantity, operatorID, remarks) if err != nil { s.logger.Errorf("应用层: 群内调栏失败, 批次ID: %d, 错误: %v", batchID, err) return MapDomainError(err) } return nil } // RecordSickPigs 委托给领域服务 func (s *pigBatchService) RecordSickPigs(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error { err := s.domainService.RecordSickPigs(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks) if err != nil { s.logger.Errorf("应用层: 记录病猪事件失败, 批次ID: %d, 错误: %v", batchID, err) return MapDomainError(err) } return nil } // RecordSickPigRecovery 委托给领域服务 func (s *pigBatchService) RecordSickPigRecovery(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error { err := s.domainService.RecordSickPigRecovery(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks) if err != nil { s.logger.Errorf("应用层: 记录病猪康复事件失败, 批次ID: %d, 错误: %v", batchID, err) return MapDomainError(err) } return nil } // RecordSickPigDeath 委托给领域服务 func (s *pigBatchService) RecordSickPigDeath(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error { err := s.domainService.RecordSickPigDeath(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks) if err != nil { s.logger.Errorf("应用层: 记录病猪死亡事件失败, 批次ID: %d, 错误: %v", batchID, err) return MapDomainError(err) } return nil } // RecordSickPigCull 委托给领域服务 func (s *pigBatchService) RecordSickPigCull(operatorID uint, batchID uint, penID uint, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error { err := s.domainService.RecordSickPigCull(operatorID, batchID, penID, quantity, treatmentLocation, happenedAt, remarks) if err != nil { s.logger.Errorf("应用层: 记录病猪淘汰事件失败, 批次ID: %d, 错误: %v", batchID, err) return MapDomainError(err) } return nil } // RecordDeath 委托给领域服务 func (s *pigBatchService) RecordDeath(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error { err := s.domainService.RecordDeath(operatorID, batchID, penID, quantity, happenedAt, remarks) if err != nil { s.logger.Errorf("应用层: 记录正常猪只死亡事件失败, 批次ID: %d, 错误: %v", batchID, err) return MapDomainError(err) } return nil } // RecordCull 委托给领域服务 func (s *pigBatchService) RecordCull(operatorID uint, batchID uint, penID uint, quantity int, happenedAt time.Time, remarks string) error { err := s.domainService.RecordCull(operatorID, batchID, penID, quantity, happenedAt, remarks) if err != nil { s.logger.Errorf("应用层: 记录正常猪只淘汰事件失败, 批次ID: %d, 错误: %v", batchID, err) return MapDomainError(err) } return nil }