NAM-APJATEL-BACKEND/usecase/olt_usecase.go

234 lines
7.2 KiB
Go

package usecase
import (
"errors"
"fmt"
"log"
"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 OLTUsecase interface {
CreateOLT(oltDTO req.OLTDTO) error
GetAllOLTs() ([]res.OLTResponse, error)
GetOLTByID(id uuid.UUID) (res.OLTDetailResponse, error)
UpdateOLT(id uuid.UUID, updateDTO req.UpdateOLTDTO) error
DeleteOLT(id uuid.UUID) error
AssignDeviceToOLT(oltID, deviceID uuid.UUID) error
UnassignDeviceFromOLT(deviceID uuid.UUID) error
GetDevicesByOLT(oltID uuid.UUID) ([]res.OLTDeviceResponse, error)
}
type oltUsecase struct {
oltRepo repository.OLTRepo
deviceRepo repository.DeviceDetailsRepo
validate *validator.Validate
geocoder service.GeocodingService
}
func NewOLTUsecase(oltRepo repository.OLTRepo, deviceRepo repository.DeviceDetailsRepo, geocoder service.GeocodingService) OLTUsecase {
return &oltUsecase{
oltRepo: oltRepo,
deviceRepo: deviceRepo,
validate: validator.New(),
geocoder: geocoder,
}
}
func (u *oltUsecase) CreateOLT(oltDTO req.OLTDTO) error {
if err := u.validate.Struct(oltDTO); err != nil {
return fmt.Errorf("validation error: %w", err)
}
// Check if OLT name already exists
existingOLT, err := u.oltRepo.GetByName(oltDTO.OLTName)
if err == nil && existingOLT.ID != uuid.Nil {
return errors.New("OLT name already exists")
}
olt := entity.OLT{
ID: uuid.New(),
OLTName: oltDTO.OLTName,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
return u.oltRepo.Create(olt)
}
func (u *oltUsecase) GetAllOLTs() ([]res.OLTResponse, error) {
olts, err := u.oltRepo.GetAll()
if err != nil {
return nil, err
}
var responses []res.OLTResponse
for _, olt := range olts {
response := res.OLTResponse{
ID: olt.ID,
OLTName: olt.OLTName,
CreatedAt: olt.CreatedAt,
UpdatedAt: olt.UpdatedAt,
}
responses = append(responses, response)
}
return responses, nil
}
func (u *oltUsecase) GetOLTByID(id uuid.UUID) (res.OLTDetailResponse, error) {
// First, check if OLT exists using the basic GetByID method
olt, err := u.oltRepo.GetByID(id)
if err != nil {
log.Printf("OLT not found: %v", err)
return res.OLTDetailResponse{}, errors.New("OLT not found")
}
log.Printf("OLT found: %+v", olt)
// Try to get OLT with devices, but fallback to basic info if it fails
oltWithDevices, err := u.oltRepo.GetByIDWithDevices(id)
if err != nil {
log.Printf("Error getting OLT with devices, using basic OLT info: %v", err)
// Use the basic OLT info we already retrieved
oltWithDevices = olt
oltWithDevices.Devices = []entity.Device{} // Ensure devices is empty slice, not nil
}
log.Printf("OLT retrieved with devices: %+v", oltWithDevices)
// Convert devices to device details responses
var deviceResponses []res.DeviceDetailsResponse
for _, device := range oltWithDevices.Devices {
log.Printf("Processing device: %s", device.DeviceCode)
// Get the device details using the existing method which properly loads DevicePort
deviceDetails, err := u.deviceRepo.GetByID(device.ID)
if err != nil {
log.Printf("Error getting device details for %s: %v", device.DeviceCode, err)
continue
}
deviceResponse, err := helper.ConvertToDeviceDetailsResponse(deviceDetails, u.geocoder)
if err != nil {
log.Printf("Error converting device response for %s: %v", device.DeviceCode, err)
continue
}
deviceResponses = append(deviceResponses, deviceResponse)
}
// Initialize empty slice if nil to ensure JSON response shows empty array instead of null
if deviceResponses == nil {
deviceResponses = []res.DeviceDetailsResponse{}
}
response := res.OLTDetailResponse{
ID: oltWithDevices.ID,
OLTName: oltWithDevices.OLTName,
DeviceCount: len(deviceResponses),
Devices: deviceResponses,
CreatedAt: oltWithDevices.CreatedAt,
UpdatedAt: oltWithDevices.UpdatedAt,
}
return response, nil
}
func (u *oltUsecase) UpdateOLT(id uuid.UUID, updateDTO req.UpdateOLTDTO) error {
if err := u.validate.Struct(updateDTO); err != nil {
return fmt.Errorf("validation error: %w", err)
}
// Check if OLT exists
_, err := u.oltRepo.GetByID(id)
if err != nil {
return errors.New("OLT not found")
}
// Check if new name already exists (if name is being updated)
if updateDTO.OLTName != nil {
existingOLT, err := u.oltRepo.GetByName(*updateDTO.OLTName)
if err == nil && existingOLT.ID != id {
return errors.New("OLT name already exists")
}
}
return u.oltRepo.Update(id, updateDTO)
}
func (u *oltUsecase) DeleteOLT(id uuid.UUID) error {
// Check if OLT exists
_, err := u.oltRepo.GetByID(id)
if err != nil {
return errors.New("OLT not found")
}
return u.oltRepo.Delete(id)
}
func (u *oltUsecase) AssignDeviceToOLT(oltID, deviceID uuid.UUID) error {
return u.oltRepo.AssignDeviceToOLT(oltID, deviceID)
}
func (u *oltUsecase) UnassignDeviceFromOLT(deviceID uuid.UUID) error {
return u.oltRepo.UnassignDeviceFromOLT(deviceID)
}
func (u *oltUsecase) GetDevicesByOLT(oltID uuid.UUID) ([]res.OLTDeviceResponse, error) {
// Check if OLT exists
_, err := u.oltRepo.GetByID(oltID)
if err != nil {
return nil, errors.New("OLT not found")
}
devices, err := u.oltRepo.GetDevicesByOLTID(oltID)
if err != nil {
return nil, err
}
var responses []res.OLTDeviceResponse
for _, device := range devices {
// Get address using geocoder
address := ""
if u.geocoder != nil {
addr, err := u.geocoder.GetAddressFromCoordinates(device.Latitude, device.Longitude)
if err == nil {
address = addr
}
}
// Get port usage from device port repository
portUsed := 0
portUsageInfo, _, err := u.deviceRepo.GetPortUsageByDevice(device.ID)
if err == nil {
portUsed = portUsageInfo
}
response := res.OLTDeviceResponse{
ID: device.ID,
DeviceCode: device.DeviceCode,
DeviceType: string(device.DeviceType),
Address: address,
Province: device.Province,
City: device.City,
District: device.District,
Status: string(device.Status),
PortAmount: device.PortAmount,
PortUsed: portUsed,
ImageURL: device.ImageURL,
CreatedAt: device.CreatedAt,
UpdatedAt: device.UpdatedAt,
}
responses = append(responses, response)
}
return responses, nil
}