feat: add backbone_code to Tower for road routing waypoints
Towers can now be explicitly assigned to a backbone by setting backbone_code. This field is included in create/update DTOs and the response. The backbone OSRM routing merges these tower waypoints with Closure waypoints, sorted by distance from OTB-start. Run once on DB: ALTER TABLE towers ADD COLUMN backbone_code VARCHAR(255); Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9ae9de471d
commit
4461aff5c1
|
|
@ -8,7 +8,8 @@ type TowerDTO struct {
|
||||||
TowerCode string `json:"tower_code" validate:"required"`
|
TowerCode string `json:"tower_code" validate:"required"`
|
||||||
Longitude float64 `json:"longitude" validate:"required"`
|
Longitude float64 `json:"longitude" validate:"required"`
|
||||||
Latitude float64 `json:"latitude" validate:"required"`
|
Latitude float64 `json:"latitude" validate:"required"`
|
||||||
ExternalTower *bool `json:"external_tower,omitempty"` // Make nullable
|
ExternalTower *bool `json:"external_tower,omitempty"`
|
||||||
|
BackboneCode *string `json:"backbone_code,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateTowerDTO struct {
|
type UpdateTowerDTO struct {
|
||||||
|
|
@ -17,8 +18,9 @@ type UpdateTowerDTO struct {
|
||||||
TowerCode *string `json:"tower_code,omitempty"`
|
TowerCode *string `json:"tower_code,omitempty"`
|
||||||
Longitude *float64 `json:"longitude,omitempty" validate:"omitempty,longitude"`
|
Longitude *float64 `json:"longitude,omitempty" validate:"omitempty,longitude"`
|
||||||
Latitude *float64 `json:"latitude,omitempty" validate:"omitempty,latitude"`
|
Latitude *float64 `json:"latitude,omitempty" validate:"omitempty,latitude"`
|
||||||
ExternalTower *bool `json:"external_tower,omitempty"` // Make nullable
|
ExternalTower *bool `json:"external_tower,omitempty"`
|
||||||
ImageURL *string `json:"image_url,omitempty"`
|
ImageURL *string `json:"image_url,omitempty"`
|
||||||
|
BackboneCode *string `json:"backbone_code,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to model/dto/req/tower_dto.go
|
// Add to model/dto/req/tower_dto.go
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ type TowerResponse struct {
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
ImageURL string `json:"image_url"`
|
ImageURL string `json:"image_url"`
|
||||||
ImageURLs []string `json:"image_urls"` // Store multiple images as JSONB
|
ImageURLs []string `json:"image_urls"` // Store multiple images as JSONB
|
||||||
ExternalTower *bool `json:"external_tower"` // Make nullable
|
ExternalTower *bool `json:"external_tower"`
|
||||||
|
BackboneCode *string `json:"backbone_code,omitempty"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
@ -15,6 +15,7 @@ type Tower struct {
|
||||||
ImageURL string `json:"image_url"` // Keep for backward compatibility
|
ImageURL string `json:"image_url"` // Keep for backward compatibility
|
||||||
ImageURLs StringSlice `json:"image_urls" gorm:"type:jsonb"` // Multiple images
|
ImageURLs StringSlice `json:"image_urls" gorm:"type:jsonb"` // Multiple images
|
||||||
ExternalTower *bool `json:"external_tower,omitempty"`
|
ExternalTower *bool `json:"external_tower,omitempty"`
|
||||||
|
BackboneCode *string `json:"backbone_code,omitempty" gorm:"column:backbone_code"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,10 @@ func (u *towerUsecase) PostWithMultipleImages(tower req.TowerDTO, imageFiles []*
|
||||||
TowerCode: tower.TowerCode,
|
TowerCode: tower.TowerCode,
|
||||||
Longitude: tower.Longitude,
|
Longitude: tower.Longitude,
|
||||||
Latitude: tower.Latitude,
|
Latitude: tower.Latitude,
|
||||||
ImageURL: primaryImageURL, // Primary image
|
ImageURL: primaryImageURL,
|
||||||
ImageURLs: entity.StringSlice(imageURLs), // All images
|
ImageURLs: entity.StringSlice(imageURLs),
|
||||||
ExternalTower: tower.ExternalTower,
|
ExternalTower: tower.ExternalTower,
|
||||||
|
BackboneCode: tower.BackboneCode,
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
UpdatedAt: time.Now(),
|
UpdatedAt: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
@ -115,6 +116,9 @@ func (u *towerUsecase) UpdateTowerWithMultipleImages(id uuid.UUID, tower req.Upd
|
||||||
if tower.ImageURL != nil {
|
if tower.ImageURL != nil {
|
||||||
updates["ImageURL"] = *tower.ImageURL
|
updates["ImageURL"] = *tower.ImageURL
|
||||||
}
|
}
|
||||||
|
if tower.BackboneCode != nil {
|
||||||
|
updates["BackboneCode"] = *tower.BackboneCode
|
||||||
|
}
|
||||||
|
|
||||||
// Handle multiple image uploads
|
// Handle multiple image uploads
|
||||||
if len(imageFiles) > 0 {
|
if len(imageFiles) > 0 {
|
||||||
|
|
@ -197,12 +201,13 @@ func (u *towerUsecase) Post(tower req.TowerDTO, imageFile *multipart.FileHeader)
|
||||||
|
|
||||||
newTower := entity.Tower{
|
newTower := entity.Tower{
|
||||||
ID: uuid.New(),
|
ID: uuid.New(),
|
||||||
DeviceID: tower.DeviceID, // Now nullable
|
DeviceID: tower.DeviceID,
|
||||||
TowerCode: tower.TowerCode,
|
TowerCode: tower.TowerCode,
|
||||||
Longitude: tower.Longitude,
|
Longitude: tower.Longitude,
|
||||||
Latitude: tower.Latitude,
|
Latitude: tower.Latitude,
|
||||||
ImageURL: imageURL,
|
ImageURL: imageURL,
|
||||||
ExternalTower: tower.ExternalTower, // Now nullable
|
ExternalTower: tower.ExternalTower,
|
||||||
|
BackboneCode: tower.BackboneCode,
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
UpdatedAt: time.Now(),
|
UpdatedAt: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,8 @@ func ConvertToTowerResponses(towers []entity.Tower, geocoder service.GeocodingSe
|
||||||
Address: address,
|
Address: address,
|
||||||
ImageURL: tower.ImageURL,
|
ImageURL: tower.ImageURL,
|
||||||
ImageURLs: allImageURLs, // All images
|
ImageURLs: allImageURLs, // All images
|
||||||
ExternalTower: tower.ExternalTower, // Now nullable
|
ExternalTower: tower.ExternalTower,
|
||||||
|
BackboneCode: tower.BackboneCode,
|
||||||
CreatedAt: tower.CreatedAt,
|
CreatedAt: tower.CreatedAt,
|
||||||
UpdatedAt: tower.UpdatedAt,
|
UpdatedAt: tower.UpdatedAt,
|
||||||
}
|
}
|
||||||
|
|
@ -62,19 +63,19 @@ func ConvertToTowerIDResponses(tower entity.Tower, geocoder service.GeocodingSer
|
||||||
if tower.Device.DeviceCode != "" {
|
if tower.Device.DeviceCode != "" {
|
||||||
deviceCode = &tower.Device.DeviceCode
|
deviceCode = &tower.Device.DeviceCode
|
||||||
}
|
}
|
||||||
// Get all image URLs
|
|
||||||
allImageURLs := tower.GetAllImageURLs()
|
allImageURLs := tower.GetAllImageURLs()
|
||||||
|
|
||||||
towerResp := res.TowerResponse{
|
towerResp := res.TowerResponse{
|
||||||
ID: tower.ID,
|
ID: tower.ID,
|
||||||
DeviceCode: deviceCode, // Now nullable
|
DeviceCode: deviceCode,
|
||||||
TowerCode: &tower.TowerCode,
|
TowerCode: &tower.TowerCode,
|
||||||
Longitude: tower.Longitude,
|
Longitude: tower.Longitude,
|
||||||
Latitude: tower.Latitude,
|
Latitude: tower.Latitude,
|
||||||
Address: address,
|
Address: address,
|
||||||
ImageURL: tower.ImageURL,
|
ImageURL: tower.ImageURL,
|
||||||
ImageURLs: allImageURLs, // All images
|
ImageURLs: allImageURLs,
|
||||||
ExternalTower: tower.ExternalTower, // Now nullable
|
ExternalTower: tower.ExternalTower,
|
||||||
|
BackboneCode: tower.BackboneCode,
|
||||||
CreatedAt: tower.CreatedAt,
|
CreatedAt: tower.CreatedAt,
|
||||||
UpdatedAt: tower.UpdatedAt,
|
UpdatedAt: tower.UpdatedAt,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue