issue_29 #32
| @@ -47,8 +47,6 @@ type PigBatchService interface { | |||||||
| 	DeletePigBatch(id uint) error | 	DeletePigBatch(id uint) error | ||||||
| 	// ListPigBatches 批量查询猪批次。 | 	// ListPigBatches 批量查询猪批次。 | ||||||
| 	ListPigBatches(isActive *bool) ([]*models.PigBatch, error) | 	ListPigBatches(isActive *bool) ([]*models.PigBatch, error) | ||||||
| 	// UpdatePigBatchPens 更新猪批次关联的猪栏。 |  | ||||||
| 	UpdatePigBatchPens(batchID uint, desiredPenIDs []uint) error |  | ||||||
| 	// AssignEmptyPensToBatch 为猪群分配空栏 | 	// AssignEmptyPensToBatch 为猪群分配空栏 | ||||||
| 	AssignEmptyPensToBatch(batchID uint, penIDs []uint, operatorID uint) error | 	AssignEmptyPensToBatch(batchID uint, penIDs []uint, operatorID uint) error | ||||||
| 	// MovePigsIntoPen 将猪只从“虚拟库存”移入指定猪栏 | 	// MovePigsIntoPen 将猪只从“虚拟库存”移入指定猪栏 | ||||||
|   | |||||||
| @@ -126,106 +126,6 @@ func (s *pigBatchService) ListPigBatches(isActive *bool) ([]*models.PigBatch, er | |||||||
| 	return s.pigBatchRepo.ListPigBatches(isActive) | 	return s.pigBatchRepo.ListPigBatches(isActive) | ||||||
| } | } | ||||||
|  |  | ||||||
| // UpdatePigBatchPens 实现了在事务中更新猪批次关联猪栏的复杂逻辑。 |  | ||||||
| // 它通过调用底层的 PigPenTransferManager 来执行数据库操作,从而保持了职责的清晰。 |  | ||||||
| func (s *pigBatchService) UpdatePigBatchPens(batchID uint, desiredPenIDs []uint) error { |  | ||||||
| 	// 使用工作单元来确保操作的原子性 |  | ||||||
| 	return s.uow.ExecuteInTransaction(func(tx *gorm.DB) error { |  | ||||||
| 		// 1. 验证猪批次是否存在且活跃 |  | ||||||
| 		// 注意: 此处依赖一个假设存在的 pigBatchRepo.GetPigBatchByIDTx 方法 |  | ||||||
| 		pigBatch, err := s.pigBatchRepo.GetPigBatchByIDTx(tx, batchID) |  | ||||||
| 		if err != nil { |  | ||||||
| 			if errors.Is(err, gorm.ErrRecordNotFound) { |  | ||||||
| 				return ErrPigBatchNotFound |  | ||||||
| 			} |  | ||||||
| 			return fmt.Errorf("获取猪批次信息失败: %w", err) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if !pigBatch.IsActive() { |  | ||||||
| 			return ErrPigBatchNotActive |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		// 2. 获取当前关联的猪栏 (通过子服务) |  | ||||||
| 		currentPens, err := s.transferSvc.GetPensByBatchID(tx, batchID) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return fmt.Errorf("获取当前关联猪栏失败: %w", err) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		currentPenMap := make(map[uint]models.Pen) |  | ||||||
| 		currentPenIDsSet := make(map[uint]struct{}) |  | ||||||
| 		for _, pen := range currentPens { |  | ||||||
| 			currentPenMap[pen.ID] = *pen |  | ||||||
| 			currentPenIDsSet[pen.ID] = struct{}{} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		// 3. 构建期望猪栏ID集合 |  | ||||||
| 		desiredPenIDsSet := make(map[uint]struct{}) |  | ||||||
| 		for _, penID := range desiredPenIDs { |  | ||||||
| 			desiredPenIDsSet[penID] = struct{}{} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		// 4. 计算需要添加和移除的猪栏 |  | ||||||
| 		var pensToRemove []uint |  | ||||||
| 		for penID := range currentPenIDsSet { |  | ||||||
| 			if _, found := desiredPenIDsSet[penID]; !found { |  | ||||||
| 				pensToRemove = append(pensToRemove, penID) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		var pensToAdd []uint |  | ||||||
| 		for _, penID := range desiredPenIDs { |  | ||||||
| 			if _, found := currentPenIDsSet[penID]; !found { |  | ||||||
| 				pensToAdd = append(pensToAdd, penID) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		// 5. 处理移除猪栏的逻辑 |  | ||||||
| 		for _, penID := range pensToRemove { |  | ||||||
| 			currentPen := currentPenMap[penID] |  | ||||||
| 			updates := make(map[string]interface{}) |  | ||||||
| 			updates["pig_batch_id"] = nil |  | ||||||
|  |  | ||||||
| 			if currentPen.Status == models.PenStatusOccupied { |  | ||||||
| 				updates["status"] = models.PenStatusEmpty |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			if err := s.transferSvc.UpdatePenFields(tx, penID, updates); err != nil { |  | ||||||
| 				return fmt.Errorf("移除猪栏 %d 失败: %w", penID, err) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		// 6. 处理添加猪栏的逻辑 |  | ||||||
| 		for _, penID := range pensToAdd { |  | ||||||
| 			// 通过子服务获取猪栏信息 |  | ||||||
| 			actualPen, err := s.transferSvc.GetPenByID(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) |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			// 核心业务规则:校验猪栏是否可被分配 |  | ||||||
| 			if actualPen.Status != models.PenStatusEmpty { |  | ||||||
| 				return fmt.Errorf("猪栏 %s 状态为 %s,无法分配: %w", actualPen.PenNumber, actualPen.Status, ErrPenStatusInvalidForAllocation) |  | ||||||
| 			} |  | ||||||
| 			if actualPen.PigBatchID != nil { |  | ||||||
| 				return fmt.Errorf("猪栏 %s 已被其他批次 %d 使用: %w", actualPen.PenNumber, *actualPen.PigBatchID, ErrPenOccupiedByOtherBatch) |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			updates := map[string]interface{}{ |  | ||||||
| 				"pig_batch_id": &batchID, |  | ||||||
| 				"status":       models.PenStatusOccupied, |  | ||||||
| 			} |  | ||||||
| 			if err := s.transferSvc.UpdatePenFields(tx, penID, updates); err != nil { |  | ||||||
| 				return fmt.Errorf("添加猪栏 %d 失败: %w", penID, err) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return nil |  | ||||||
| 	}) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // GetCurrentPigQuantity 实现了获取指定猪批次的当前猪只数量的逻辑。 | // GetCurrentPigQuantity 实现了获取指定猪批次的当前猪只数量的逻辑。 | ||||||
| func (s *pigBatchService) GetCurrentPigQuantity(batchID uint) (int, error) { | func (s *pigBatchService) GetCurrentPigQuantity(batchID uint) (int, error) { | ||||||
| 	var getErr error | 	var getErr error | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user