NAM-APJATEL-BACKEND/repository/nearest_device_repo.go

118 lines
4.2 KiB
Go

package repository
import (
"users_management/m/model/entity"
"github.com/google/uuid"
"gorm.io/gorm"
)
type NearestDeviceRepo interface {
GetNearestDevices(longitude, latitude, radius float64, limit int, province, city, district *string) ([]entity.DeviceWithDistance, error)
GetDeviceByIDWithConnections(id uuid.UUID) (entity.Device, error)
GetBackbonesByDeviceID(deviceID uuid.UUID) ([]entity.Backbone, error)
GetFishbonesByDeviceID(deviceID uuid.UUID) ([]entity.Fishbone, error)
GetTowersByDeviceID(deviceID uuid.UUID) ([]entity.Tower, error)
CountConnectionsByDeviceID(deviceID uuid.UUID) (backboneCount, fishboneCount, towerCount int, err error)
}
type nearestDeviceRepo struct {
db *gorm.DB
}
func NewNearestDeviceRepo(db *gorm.DB) NearestDeviceRepo {
return &nearestDeviceRepo{
db: db,
}
}
func (r *nearestDeviceRepo) GetNearestDevices(longitude, latitude, radius float64, limit int, province, city, district *string) ([]entity.DeviceWithDistance, error) {
var devices []entity.DeviceWithDistance
// Build the subquery first
subQuery := r.db.Table("devices").
Select(`id, device_code, device_type, longitude, latitude, port_amount, status,
region, province, city, district, image_url, created_at, updated_at,
(6371 * acos(cos(radians(?)) * cos(radians(latitude)) * cos(radians(longitude) - radians(?)) + sin(radians(?)) * sin(radians(latitude)))) AS distance`,
latitude, longitude, latitude)
// Apply location filters to subquery
if province != nil && *province != "" {
subQuery = subQuery.Where("province = ?", *province)
}
if city != nil && *city != "" {
subQuery = subQuery.Where("city = ?", *city)
}
if district != nil && *district != "" {
subQuery = subQuery.Where("district = ?", *district)
}
// Use the subquery in the main query
err := r.db.Table("(?) as devices_with_distance", subQuery).
Where("distance <= ?", radius).
Order("distance ASC").
Limit(limit).
Scan(&devices).Error
return devices, err
}
func (r *nearestDeviceRepo) GetDeviceByIDWithConnections(id uuid.UUID) (entity.Device, error) {
var device entity.Device
err := r.db.Where("id = ?", id).First(&device).Error
return device, err
}
func (r *nearestDeviceRepo) GetBackbonesByDeviceID(deviceID uuid.UUID) ([]entity.Backbone, error) {
var backbones []entity.Backbone
err := r.db.Preload("DeviceStart").Preload("DeviceEnd").
Where("dev_start_id = ? OR dev_end_id = ?", deviceID, deviceID).
Find(&backbones).Error
return backbones, err
}
func (r *nearestDeviceRepo) GetFishbonesByDeviceID(deviceID uuid.UUID) ([]entity.Fishbone, error) {
var fishbones []entity.Fishbone
err := r.db.Preload("Backbone").Preload("DeviceStart").Preload("DeviceEnd").
Where("dev_start_id = ? OR dev_end_id = ?", deviceID, deviceID).
Find(&fishbones).Error
return fishbones, err
}
func (r *nearestDeviceRepo) GetTowersByDeviceID(deviceID uuid.UUID) ([]entity.Tower, error) {
var towers []entity.Tower
err := r.db.Preload("Device").
Where("dev_id = ?", deviceID).
Find(&towers).Error
return towers, err
}
func (r *nearestDeviceRepo) CountConnectionsByDeviceID(deviceID uuid.UUID) (backboneCount, fishboneCount, towerCount int, err error) {
var backboneCountInt64, fishboneCountInt64, towerCountInt64 int64
// Count backbones
err = r.db.Model(&entity.Backbone{}).
Where("dev_start_id = ? OR dev_end_id = ?", deviceID, deviceID).
Count(&backboneCountInt64).Error
if err != nil {
return 0, 0, 0, err
}
// Count fishbones
err = r.db.Model(&entity.Fishbone{}).
Where("dev_start_id = ? OR dev_end_id = ?", deviceID, deviceID).
Count(&fishboneCountInt64).Error
if err != nil {
return 0, 0, 0, err
}
// Count towers
err = r.db.Model(&entity.Tower{}).
Where("dev_id = ?", deviceID).
Count(&towerCountInt64).Error
if err != nil {
return 0, 0, 0, err
}
return int(backboneCountInt64), int(fishboneCountInt64), int(towerCountInt64), nil
}