244 lines
7.7 KiB
Go
244 lines
7.7 KiB
Go
package usecase
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
"users_management/m/model/dto/req"
|
|
"users_management/m/model/dto/res"
|
|
"users_management/m/model/entity"
|
|
"users_management/m/repository"
|
|
"users_management/m/utils/helper"
|
|
|
|
"github.com/go-playground/validator/v10"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type FishboneUseCase interface {
|
|
CreateFishbone(fishbone req.FishboneDTO) error
|
|
GetAllFishbone() ([]res.FishboneResponse, error)
|
|
GetByID(id uuid.UUID) (res.FishboneDetailResponse, error)
|
|
UpdateFishbone(id uuid.UUID, fishbone req.UpdateFishboneDTO) error
|
|
DeleteFishbone(id uuid.UUID) error
|
|
GetFishboneStats() (map[string]interface{}, error)
|
|
}
|
|
|
|
type fishboneUseCase struct {
|
|
fishboneRepo repository.FishboneRepo
|
|
backboneRepo repository.BackboneRepo
|
|
deviceDetailsRepo repository.DeviceDetailsRepo // Add this field
|
|
validate *validator.Validate
|
|
}
|
|
|
|
func NewFishboneUseCase(fishboneRepo repository.FishboneRepo, backboneRepo repository.BackboneRepo, deviceDetailsRepo repository.DeviceDetailsRepo) FishboneUseCase {
|
|
return &fishboneUseCase{
|
|
fishboneRepo: fishboneRepo,
|
|
backboneRepo: backboneRepo,
|
|
deviceDetailsRepo: deviceDetailsRepo, // Initialize the field
|
|
validate: validator.New(),
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (u *fishboneUseCase) CreateFishbone(fishbone req.FishboneDTO) error {
|
|
err := u.validate.Struct(fishbone)
|
|
if err != nil {
|
|
return fmt.Errorf("validation error: %w", err)
|
|
}
|
|
|
|
// Validate that both devices exist and are ODP type
|
|
startExists, err := u.deviceDetailsRepo.CheckDeviceExists(fishbone.DeviceStartID)
|
|
if err != nil {
|
|
return fmt.Errorf("error checking start device: %w", err)
|
|
}
|
|
if !startExists {
|
|
return fmt.Errorf("start device does not exist")
|
|
}
|
|
|
|
endExists, err := u.deviceDetailsRepo.CheckDeviceExists(fishbone.DeviceEndID)
|
|
if err != nil {
|
|
return fmt.Errorf("error checking end device: %w", err)
|
|
}
|
|
if !endExists {
|
|
return fmt.Errorf("end device does not exist")
|
|
}
|
|
|
|
// Validate port availability for ODP devices (each core needs 1 port)
|
|
if err := u.deviceDetailsRepo.ValidatePortAvailability(fishbone.DeviceStartID, fishbone.CoreAmount); err != nil {
|
|
return fmt.Errorf("start device: %w", err)
|
|
}
|
|
if err := u.deviceDetailsRepo.ValidatePortAvailability(fishbone.DeviceEndID, fishbone.CoreAmount); err != nil {
|
|
return fmt.Errorf("end device: %w", err)
|
|
}
|
|
|
|
newFishbone := entity.Fishbone{
|
|
ID: uuid.New(),
|
|
FishboneCode: fishbone.FishboneCode,
|
|
BackboneID: fishbone.BackboneID,
|
|
DeviceStartID: fishbone.DeviceStartID,
|
|
DeviceEndID: fishbone.DeviceEndID,
|
|
CoreAmount: fishbone.CoreAmount,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
// Create fishbone
|
|
err = u.fishboneRepo.Post(newFishbone)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Update port usage for both devices
|
|
u.deviceDetailsRepo.UpdateDevicePortUsage(fishbone.DeviceStartID)
|
|
u.deviceDetailsRepo.UpdateDevicePortUsage(fishbone.DeviceEndID)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (u *fishboneUseCase) GetAllFishbone() ([]res.FishboneResponse, error) {
|
|
fishbones, err := u.fishboneRepo.GetAll()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return helper.ConvertToSimpleFishboneResponses(fishbones), nil
|
|
}
|
|
|
|
func (u *fishboneUseCase) GetByID(id uuid.UUID) (res.FishboneDetailResponse, error) {
|
|
fishbone, err := u.fishboneRepo.GetByIDWithRelations(id)
|
|
if err != nil {
|
|
return res.FishboneDetailResponse{}, err
|
|
}
|
|
|
|
// Convert to detailed response using helper
|
|
return helper.ConvertToFishboneDetailResponse(fishbone), nil
|
|
}
|
|
|
|
func (u *fishboneUseCase) UpdateFishbone(id uuid.UUID, fishbone req.UpdateFishboneDTO) error {
|
|
err := u.validate.Struct(fishbone)
|
|
if err != nil {
|
|
return fmt.Errorf("validation error: %w", err)
|
|
}
|
|
|
|
// Get original fishbone for comparison
|
|
originalFishbone, err := u.fishboneRepo.GetByID(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
updates := make(map[string]interface{})
|
|
|
|
// Track devices that need port recalculation
|
|
devicesToUpdate := make(map[uuid.UUID]bool)
|
|
devicesToUpdate[originalFishbone.DeviceStartID] = true
|
|
devicesToUpdate[originalFishbone.DeviceEndID] = true
|
|
|
|
// If core amount is changed, validate port availability
|
|
if fishbone.CoreAmount != nil && *fishbone.CoreAmount != originalFishbone.CoreAmount {
|
|
coreDiff := *fishbone.CoreAmount - originalFishbone.CoreAmount
|
|
if coreDiff > 0 {
|
|
// Increasing cores - check port availability
|
|
if err := u.deviceDetailsRepo.ValidatePortAvailability(originalFishbone.DeviceStartID, coreDiff); err != nil {
|
|
return fmt.Errorf("start device: %w", err)
|
|
}
|
|
if err := u.deviceDetailsRepo.ValidatePortAvailability(originalFishbone.DeviceEndID, coreDiff); err != nil {
|
|
return fmt.Errorf("end device: %w", err)
|
|
}
|
|
}
|
|
updates["core_amount"] = *fishbone.CoreAmount
|
|
}
|
|
|
|
if fishbone.DeviceStartID != nil {
|
|
exists, err := u.deviceDetailsRepo.CheckDeviceExists(*fishbone.DeviceStartID)
|
|
if err != nil {
|
|
return fmt.Errorf("error checking new start device: %w", err)
|
|
}
|
|
if !exists {
|
|
return fmt.Errorf("new start device does not exist")
|
|
}
|
|
|
|
coreAmount := originalFishbone.CoreAmount
|
|
if fishbone.CoreAmount != nil {
|
|
coreAmount = *fishbone.CoreAmount
|
|
}
|
|
|
|
if err := u.deviceDetailsRepo.ValidatePortAvailability(*fishbone.DeviceStartID, coreAmount); err != nil {
|
|
return fmt.Errorf("new start device: %w", err)
|
|
}
|
|
|
|
updates["dev_start_id"] = *fishbone.DeviceStartID
|
|
devicesToUpdate[*fishbone.DeviceStartID] = true
|
|
}
|
|
|
|
if fishbone.DeviceEndID != nil {
|
|
exists, err := u.deviceDetailsRepo.CheckDeviceExists(*fishbone.DeviceEndID)
|
|
if err != nil {
|
|
return fmt.Errorf("error checking new end device: %w", err)
|
|
}
|
|
if !exists {
|
|
return fmt.Errorf("new end device does not exist")
|
|
}
|
|
|
|
coreAmount := originalFishbone.CoreAmount
|
|
if fishbone.CoreAmount != nil {
|
|
coreAmount = *fishbone.CoreAmount
|
|
}
|
|
|
|
if err := u.deviceDetailsRepo.ValidatePortAvailability(*fishbone.DeviceEndID, coreAmount); err != nil {
|
|
return fmt.Errorf("new end device: %w", err)
|
|
}
|
|
|
|
updates["dev_end_id"] = *fishbone.DeviceEndID
|
|
devicesToUpdate[*fishbone.DeviceEndID] = true
|
|
}
|
|
|
|
if fishbone.BackboneID != nil {
|
|
updates["backbone_id"] = *fishbone.BackboneID
|
|
}
|
|
|
|
if fishbone.FishboneCode != nil {
|
|
updates["fishbone_code"] = *fishbone.FishboneCode
|
|
}
|
|
|
|
if len(updates) == 0 {
|
|
return fmt.Errorf("no fields to update")
|
|
}
|
|
|
|
updates["updated_at"] = time.Now()
|
|
|
|
// Update fishbone
|
|
err = u.fishboneRepo.Update(id, updates)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Recalculate port usage for all affected devices
|
|
for deviceID := range devicesToUpdate {
|
|
u.deviceDetailsRepo.UpdateDevicePortUsage(deviceID)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (u *fishboneUseCase) DeleteFishbone(id uuid.UUID) error {
|
|
// Check if fishbone exists
|
|
exists, err := u.fishboneRepo.CheckFishboneExists(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exists {
|
|
return errors.New("fishbone not found")
|
|
}
|
|
|
|
return u.fishboneRepo.Delete(id)
|
|
}
|
|
|
|
func (u *fishboneUseCase) GetFishboneStats() (map[string]interface{}, error) {
|
|
fishbones, err := u.fishboneRepo.GetAll()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return helper.GetFishboneStats(fishbones), nil
|
|
} |