245 lines
9.1 KiB
Go
245 lines
9.1 KiB
Go
package helper
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"users_management/m/model/dto/res"
|
|
"users_management/m/model/entity"
|
|
"users_management/m/utils/service"
|
|
)
|
|
|
|
func ConvertToDeviceDetailsResponses(devices []entity.DeviceDetails, geocoder service.GeocodingService) ([]res.DeviceDetailsResponse, error) {
|
|
var responses []res.DeviceDetailsResponse
|
|
|
|
for _, device := range devices {
|
|
response, err := ConvertToDeviceDetailsResponse(device, geocoder)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
responses = append(responses, response)
|
|
}
|
|
|
|
return responses, nil
|
|
}
|
|
|
|
func ConvertToDeviceDetailsResponse(device entity.DeviceDetails, geocoder service.GeocodingService) (res.DeviceDetailsResponse, error) {
|
|
// Get address
|
|
address := ""
|
|
if geocoder != nil {
|
|
addr, err := geocoder.GetAddressFromCoordinates(device.Latitude, device.Longitude)
|
|
if err != nil {
|
|
log.Printf("Geocoding error for device %s: %v", device.DeviceCode, err)
|
|
address = fmt.Sprintf("Coordinates: %.6f, %.6f", device.Latitude, device.Longitude)
|
|
} else {
|
|
address = addr
|
|
}
|
|
}
|
|
|
|
// Get all backbones connected to this device
|
|
allBackbones := device.GetAllBackbones()
|
|
backboneInfos := make([]res.BackboneConnectionInfo, 0)
|
|
for _, backbone := range allBackbones {
|
|
isStartDevice := backbone.DeviceStartID == device.ID
|
|
connectedTo := ""
|
|
|
|
if isStartDevice && backbone.DeviceEnd.DeviceCode != "" {
|
|
connectedTo = backbone.DeviceEnd.DeviceCode
|
|
} else if !isStartDevice && backbone.DeviceStart.DeviceCode != "" {
|
|
connectedTo = backbone.DeviceStart.DeviceCode
|
|
}
|
|
|
|
info := res.BackboneConnectionInfo{
|
|
ID: backbone.ID,
|
|
BackboneCode: backbone.BackboneCode,
|
|
CoreAmount: backbone.CoreAmount,
|
|
IsStartDevice: isStartDevice,
|
|
ConnectedTo: connectedTo,
|
|
}
|
|
backboneInfos = append(backboneInfos, info)
|
|
}
|
|
|
|
// Get all fishbones connected to this device
|
|
allFishbones := device.GetAllFishbones()
|
|
fishboneInfos := make([]res.FishboneConnectionInfo, 0)
|
|
for _, fishbone := range allFishbones {
|
|
isStartDevice := fishbone.DeviceStartID == device.ID
|
|
connectedTo := ""
|
|
|
|
if isStartDevice && fishbone.DeviceEnd.DeviceCode != "" {
|
|
connectedTo = fishbone.DeviceEnd.DeviceCode
|
|
} else if !isStartDevice && fishbone.DeviceStart.DeviceCode != "" {
|
|
connectedTo = fishbone.DeviceStart.DeviceCode
|
|
}
|
|
|
|
info := res.FishboneConnectionInfo{
|
|
ID: fishbone.ID,
|
|
FishboneCode: fishbone.FishboneCode,
|
|
CoreAmount: fishbone.CoreAmount,
|
|
BackboneCode: fishbone.Backbone.BackboneCode,
|
|
IsStartDevice: isStartDevice,
|
|
ConnectedTo: connectedTo,
|
|
}
|
|
fishboneInfos = append(fishboneInfos, info)
|
|
}
|
|
|
|
// Convert tower connections - safely handle nullable ExternalTower
|
|
towerInfos := make([]res.TowerConnectionDetail, 0)
|
|
for _, tower := range device.Towers {
|
|
distance := calculateDistance(device.Latitude, device.Longitude, tower.Latitude, tower.Longitude)
|
|
|
|
// Safely handle nullable ExternalTower field
|
|
var externalTower *bool
|
|
if tower.ExternalTower != nil {
|
|
externalTower = tower.ExternalTower
|
|
} // If tower.ExternalTower is nil, externalTower remains nil
|
|
|
|
// Safely handle nullable ImageURL
|
|
var imageURL *string
|
|
if tower.ImageURL != "" {
|
|
imageURL = &tower.ImageURL
|
|
}
|
|
|
|
info := res.TowerConnectionDetail{
|
|
ID: tower.ID,
|
|
TowerCode: tower.TowerCode,
|
|
Distance: distance,
|
|
ExternalTower: externalTower, // This will be null if tower.ExternalTower is nil
|
|
ImageURL: imageURL,
|
|
ImageURLs: tower.GetAllImageURLs(), // Get all images as a slice
|
|
}
|
|
towerInfos = append(towerInfos, info)
|
|
}
|
|
|
|
// Convert entity.PortAssignmentResponse to res.PortAssignmentResponse
|
|
entityPortAssignments := device.DevicePort.GetPortAssignmentsWithDetails()
|
|
resPortAssignments := make([]res.PortAssignmentResponse, len(entityPortAssignments))
|
|
for i, pa := range entityPortAssignments {
|
|
resPortAssignments[i] = res.PortAssignmentResponse{
|
|
PortNumber: pa.PortNumber,
|
|
CustomerName: pa.CustomerName,
|
|
IsOccupied: pa.IsOccupied,
|
|
}
|
|
}
|
|
portAssignments := device.DevicePort.GetPortAssignmentsWithDetails()
|
|
|
|
// Ensure we show all ports up to PortAmount
|
|
portAssignmentMap := make(map[int]res.PortAssignmentResponse)
|
|
for _, pa := range portAssignments {
|
|
portAssignmentMap[pa.PortNumber] = res.PortAssignmentResponse{
|
|
PortNumber: pa.PortNumber,
|
|
CustomerName: pa.CustomerName,
|
|
IsOccupied: pa.IsOccupied,
|
|
}
|
|
}
|
|
|
|
// Fill in missing ports
|
|
finalPortAssignments := make([]res.PortAssignmentResponse, 0)
|
|
for i := 1; i <= device.PortAmount; i++ {
|
|
if pa, exists := portAssignmentMap[i]; exists {
|
|
finalPortAssignments = append(finalPortAssignments, pa)
|
|
} else {
|
|
// Determine if this port should be occupied
|
|
isOccupied := false
|
|
|
|
// Count occupied ports before this one
|
|
occupiedBefore := 0
|
|
for j := 1; j < i; j++ {
|
|
if existingPA, exists := portAssignmentMap[j]; exists && existingPA.IsOccupied {
|
|
occupiedBefore++
|
|
}
|
|
}
|
|
|
|
// Count total ports with customers
|
|
customersCount := 0
|
|
for _, pa := range portAssignments {
|
|
if pa.CustomerName != nil && *pa.CustomerName != "" {
|
|
customersCount++
|
|
}
|
|
}
|
|
|
|
// This port should be occupied if we haven't reached port_used yet
|
|
if occupiedBefore + customersCount < device.DevicePort.PortUsed {
|
|
isOccupied = true
|
|
}
|
|
|
|
finalPortAssignments = append(finalPortAssignments, res.PortAssignmentResponse{
|
|
PortNumber: i,
|
|
CustomerName: nil,
|
|
IsOccupied: isOccupied,
|
|
})
|
|
}
|
|
}
|
|
|
|
var customerNames []string
|
|
|
|
// If port_used is 0, return empty port assignments
|
|
if device.PortAmount == 0 {
|
|
finalPortAssignments = []res.PortAssignmentResponse{}
|
|
customerNames = []string{}
|
|
} else if device.DevicePort.PortUsed == 0 {
|
|
// If port_used is 0, return empty port assignments but keep port_amount structure
|
|
finalPortAssignments = []res.PortAssignmentResponse{}
|
|
customerNames = []string{}
|
|
} else {
|
|
// Get port assignments with details
|
|
portAssignments := device.DevicePort.GetPortAssignmentsWithDetails()
|
|
|
|
// Convert to response format
|
|
finalPortAssignments = make([]res.PortAssignmentResponse, len(portAssignments))
|
|
for i, pa := range portAssignments {
|
|
finalPortAssignments[i] = res.PortAssignmentResponse{
|
|
PortNumber: pa.PortNumber,
|
|
CustomerName: pa.CustomerName,
|
|
IsOccupied: pa.IsOccupied,
|
|
}
|
|
}
|
|
|
|
// Get customer names
|
|
customerNames = device.DevicePort.GetCustomerNamesOnly()
|
|
}
|
|
|
|
var deviceImageURLs []string
|
|
if device.ImageURL != nil && *device.ImageURL != "" {
|
|
deviceImageURLs = append(deviceImageURLs, *device.ImageURL)
|
|
}
|
|
|
|
// Use deviceImageURLs instead of trying to call a non-existent method
|
|
allImageURLs := deviceImageURLs
|
|
|
|
// Handle empty slice vs nil for JSON response
|
|
if len(allImageURLs) == 0 {
|
|
allImageURLs = []string{} // Return empty array instead of nil
|
|
}
|
|
|
|
response := res.DeviceDetailsResponse{
|
|
ID: device.ID,
|
|
DeviceCode: device.DeviceCode,
|
|
DeviceType: string(device.DeviceType),
|
|
Address: address,
|
|
Longitude: device.Longitude,
|
|
Latitude: device.Latitude,
|
|
Status: string(device.Status),
|
|
PortAmount: device.PortAmount,
|
|
PortUsed: device.DevicePort.PortUsed,
|
|
PortAvailable: device.DevicePort.PortAvailable,
|
|
CustomerNames: customerNames, // Just customer names
|
|
PortAssignments: finalPortAssignments, // Use finalPortAssignments instead of resPortAssignments
|
|
Region: device.Region,
|
|
Province: device.Province,
|
|
City: device.City,
|
|
District: device.District,
|
|
ImageURL: device.ImageURL,
|
|
ImageURLs: allImageURLs, // Use allImageURLs to ensure empty array instead of nil
|
|
Backbones: backboneInfos,
|
|
Fishbones: fishboneInfos,
|
|
Towers: towerInfos,
|
|
CreatedAt: device.CreatedAt,
|
|
UpdatedAt: device.UpdatedAt,
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
|
|
|
|
// ... rest of helper functions remain the same
|