NAM-APJATEL-BACKEND/usecase/device_details.go

176 lines
5.4 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"
"users_management/m/utils/service"
"github.com/go-playground/validator/v10"
"github.com/google/uuid"
)
type DeviceDetailsUseCase interface {
CreateDeviceDetails(device req.DeviceDetailsDTO) error
GetAllDeviceDetails() ([]res.DeviceDetailsResponse, error)
GetDeviceDetailsByID(id uuid.UUID) (res.DeviceDetailsResponse, error)
UpdateDeviceDetails(id uuid.UUID, device req.UpdateDeviceDetailsDTO) error
DeleteDeviceDetails(id uuid.UUID) error
// Port management
// ValidatePortUsage(deviceID uuid.UUID, requiredPorts int) error
RecalculatePortUsage(deviceID uuid.UUID) error
}
type deviceDetailsUseCase struct {
deviceDetailsRepo repository.DeviceDetailsRepo
geocoder service.GeocodingService
validate *validator.Validate
}
func NewDeviceDetailsUseCase(deviceDetailsRepo repository.DeviceDetailsRepo, geocoder service.GeocodingService) DeviceDetailsUseCase {
return &deviceDetailsUseCase{
deviceDetailsRepo: deviceDetailsRepo,
geocoder: geocoder,
validate: validator.New(),
}
}
func (u *deviceDetailsUseCase) CreateDeviceDetails(deviceDTO req.DeviceDetailsDTO) error {
err := u.validate.Struct(deviceDTO)
if err != nil {
return fmt.Errorf("validation error: %w", err)
}
newDevice := entity.Device{
ID: uuid.New(),
DeviceCode: deviceDTO.DeviceCode,
DeviceType: entity.DeviceType(deviceDTO.DeviceType),
Longitude: deviceDTO.Longitude,
Latitude: deviceDTO.Latitude,
PortAmount: deviceDTO.PortAmount,
Status: entity.DeviceStatus(deviceDTO.Status),
Province: deviceDTO.Province,
City: deviceDTO.City,
District: deviceDTO.District,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
return u.deviceDetailsRepo.Create(newDevice)
}
func (u *deviceDetailsUseCase) GetAllDeviceDetails() ([]res.DeviceDetailsResponse, error) {
devices, err := u.deviceDetailsRepo.GetAll()
if err != nil {
return nil, err
}
return helper.ConvertToDeviceDetailsResponses(devices, u.geocoder)
}
func (u *deviceDetailsUseCase) GetDeviceDetailsByID(id uuid.UUID) (res.DeviceDetailsResponse, error) {
device, err := u.deviceDetailsRepo.GetByID(id)
if err != nil {
return res.DeviceDetailsResponse{}, err
}
return helper.ConvertToDeviceDetailsResponse(device, u.geocoder)
}
func (u *deviceDetailsUseCase) UpdateDeviceDetails(id uuid.UUID, deviceDTO req.UpdateDeviceDetailsDTO) error {
err := u.validate.Struct(deviceDTO)
if err != nil {
return fmt.Errorf("validation error: %w", err)
}
// Check if device exists
updates := map[string]interface{}{}
if deviceDTO.DeviceCode != nil {
updates["device_code"] = *deviceDTO.DeviceCode
}
if deviceDTO.DeviceType != nil {
updates["device_type"] = *deviceDTO.DeviceType
}
if deviceDTO.Longitude != nil {
updates["longitude"] = *deviceDTO.Longitude
}
if deviceDTO.Latitude != nil {
updates["latitude"] = *deviceDTO.Latitude
}
if deviceDTO.PortAmount != nil {
// Validate port amount change
currentUsed, _, err := u.deviceDetailsRepo.GetPortUsageByDevice(id)
if err != nil {
return err
}
if *deviceDTO.PortAmount < currentUsed {
return fmt.Errorf("cannot reduce port amount to %d, currently using %d ports", *deviceDTO.PortAmount, currentUsed)
}
updates["port_amount"] = *deviceDTO.PortAmount
}
if deviceDTO.Status != nil {
updates["status"] = *deviceDTO.Status
}
if deviceDTO.Region != nil {
updates["region"] = *deviceDTO.Region
}
if deviceDTO.Province != nil {
updates["province"] = *deviceDTO.Province
}
if deviceDTO.City != nil {
updates["city"] = *deviceDTO.City
}
if deviceDTO.District != nil {
updates["district"] = *deviceDTO.District
}
if len(updates) == 0 {
return errors.New("no fields to update")
}
updates["updated_at"] = time.Now()
return u.deviceDetailsRepo.Update(id, updates)
}
func (u *deviceDetailsUseCase) DeleteDeviceDetails(id uuid.UUID) error {
// Check if device has connections
backbones, err := u.deviceDetailsRepo.GetBackbonesByDeviceID(id)
if err != nil {
return err
}
if len(backbones) > 0 {
return errors.New("cannot delete device with active backbone connections")
}
fishbones, err := u.deviceDetailsRepo.GetFishbonesByDeviceID(id)
if err != nil {
return err
}
if len(fishbones) > 0 {
return errors.New("cannot delete device with active fishbone connections")
}
towers, err := u.deviceDetailsRepo.GetTowersByDeviceID(id)
if err != nil {
return err
}
if len(towers) > 0 {
return errors.New("cannot delete device with active tower connections")
}
return u.deviceDetailsRepo.Delete(id)
}
func (u *deviceDetailsUseCase) RecalculatePortUsage(deviceID uuid.UUID) error {
return u.deviceDetailsRepo.UpdateDevicePortUsage(deviceID)
}