159 lines
6.1 KiB
Go
159 lines
6.1 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)
|
|
GetNearestTowers(longitude, latitude, radius float64, limit int, province, city, district *string) ([]entity.TowerWithDistance, error)
|
|
GetTowerByIDWithConnections(id uuid.UUID) (entity.Tower, error)
|
|
|
|
}
|
|
|
|
type nearestDeviceRepo struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewNearestDeviceRepo(db *gorm.DB) NearestDeviceRepo {
|
|
return &nearestDeviceRepo{
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
func (r *nearestDeviceRepo) GetNearestTowers(longitude, latitude, radius float64, limit int, province, city, district *string) ([]entity.TowerWithDistance, error) {
|
|
var towers []entity.TowerWithDistance
|
|
|
|
// Build the subquery first - join with devices to get location filters
|
|
subQuery := r.db.Table("towers").
|
|
Select(`towers.id, towers.tower_code, towers.longitude, towers.latitude,
|
|
towers.image_url, towers.external_tower, towers.dev_id, towers.created_at, towers.updated_at,
|
|
devices.device_code, devices.province, devices.city, devices.district,
|
|
(6371 * acos(cos(radians(?)) * cos(radians(towers.latitude)) * cos(radians(towers.longitude) - radians(?)) + sin(radians(?)) * sin(radians(towers.latitude)))) AS distance`,
|
|
latitude, longitude, latitude).
|
|
Joins("LEFT JOIN devices ON towers.dev_id = devices.id")
|
|
|
|
// Apply location filters to subquery
|
|
if province != nil && *province != "" {
|
|
subQuery = subQuery.Where("devices.province = ?", *province)
|
|
}
|
|
if city != nil && *city != "" {
|
|
subQuery = subQuery.Where("devices.city = ?", *city)
|
|
}
|
|
if district != nil && *district != "" {
|
|
subQuery = subQuery.Where("devices.district = ?", *district)
|
|
}
|
|
|
|
// Use the subquery in the main query
|
|
err := r.db.Table("(?) as towers_with_distance", subQuery).
|
|
Where("distance <= ?", radius).
|
|
Order("distance ASC").
|
|
Limit(limit).
|
|
Scan(&towers).Error
|
|
|
|
return towers, err
|
|
}
|
|
|
|
func (r *nearestDeviceRepo) GetTowerByIDWithConnections(id uuid.UUID) (entity.Tower, error) {
|
|
var tower entity.Tower
|
|
err := r.db.Preload("Device").Where("id = ?", id).First(&tower).Error
|
|
return tower, err
|
|
}
|
|
|
|
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
|
|
} |