324 lines
9.3 KiB
Go
324 lines
9.3 KiB
Go
package usecase
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"mime/multipart"
|
|
"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 TowerUseCase interface {
|
|
Post(tower req.TowerDTO, imageFile *multipart.FileHeader) error
|
|
GetAll() ([]res.TowerResponse, error)
|
|
GetByID(id uuid.UUID) (res.TowerResponse, error)
|
|
UpdateTower(id uuid.UUID, tower req.UpdateTowerDTO, imageFile *multipart.FileHeader) error
|
|
BulkUploadImages(towers []req.BulkTowerImageUploadDTO, imageFiles []*multipart.FileHeader) error
|
|
PostWithMultipleImages(tower req.TowerDTO, imageFiles []*multipart.FileHeader) error
|
|
UpdateTowerWithMultipleImages(id uuid.UUID, tower req.UpdateTowerDTO, imageFiles []*multipart.FileHeader, replaceImages ...bool) error
|
|
}
|
|
|
|
type towerUsecase struct {
|
|
towerRepo repository.TowerRepo
|
|
validate *validator.Validate
|
|
geocoder service.GeocodingService
|
|
}
|
|
|
|
func NewTowerUseCase(towerRepo repository.TowerRepo, geocoder service.GeocodingService) TowerUseCase {
|
|
return &towerUsecase{
|
|
towerRepo: towerRepo,
|
|
geocoder: geocoder,
|
|
validate: validator.New(),
|
|
}
|
|
}
|
|
func (u *towerUsecase) PostWithMultipleImages(tower req.TowerDTO, imageFiles []*multipart.FileHeader) error {
|
|
err := u.validate.Struct(tower)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
|
|
// Validate that if DeviceID is provided, the device exists
|
|
if tower.DeviceID != nil {
|
|
deviceExists, err := u.towerRepo.CheckDeviceExists(*tower.DeviceID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !deviceExists {
|
|
return fmt.Errorf("device not found")
|
|
}
|
|
}
|
|
|
|
var imageURLs []string
|
|
var primaryImageURL string
|
|
|
|
if len(imageFiles) > 0 {
|
|
// Save all images
|
|
imageURLs, err = helper.SaveTowerImagesBulk(imageFiles)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// First image becomes primary
|
|
if len(imageURLs) > 0 && imageURLs[0] != "" {
|
|
primaryImageURL = imageURLs[0]
|
|
}
|
|
}
|
|
|
|
newTower := entity.Tower{
|
|
ID: uuid.New(),
|
|
DeviceID: tower.DeviceID,
|
|
TowerCode: tower.TowerCode,
|
|
Longitude: tower.Longitude,
|
|
Latitude: tower.Latitude,
|
|
ImageURL: primaryImageURL, // Primary image
|
|
ImageURLs: entity.StringSlice(imageURLs), // All images
|
|
ExternalTower: tower.ExternalTower,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
return u.towerRepo.Post(newTower)
|
|
}
|
|
|
|
func (u *towerUsecase) UpdateTowerWithMultipleImages(id uuid.UUID, tower req.UpdateTowerDTO, imageFiles []*multipart.FileHeader, replaceImages ...bool) error {
|
|
err := u.validate.Struct(tower)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
updates := make(map[string]interface{})
|
|
|
|
if tower.DeviceID != nil {
|
|
updates["DeviceID"] = *tower.DeviceID
|
|
}
|
|
if tower.TowerCode != nil {
|
|
updates["TowerCode"] = *tower.TowerCode
|
|
}
|
|
if tower.Longitude != nil {
|
|
updates["Longitude"] = *tower.Longitude
|
|
}
|
|
if tower.Latitude != nil {
|
|
updates["Latitude"] = *tower.Latitude
|
|
}
|
|
if tower.ExternalTower != nil {
|
|
updates["ExternalTower"] = *tower.ExternalTower
|
|
}
|
|
if tower.ImageURL != nil {
|
|
updates["ImageURL"] = *tower.ImageURL
|
|
}
|
|
|
|
// Handle multiple image uploads
|
|
if len(imageFiles) > 0 {
|
|
// Get current tower to handle existing images
|
|
currentTower, err := u.towerRepo.GetByID(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Save new images
|
|
newImageURLs, err := helper.SaveTowerImagesBulk(imageFiles)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var finalImageURLs []string
|
|
shouldReplace := len(replaceImages) > 0 && replaceImages[0]
|
|
|
|
if shouldReplace {
|
|
// Replace all images - delete old ones
|
|
for _, oldImageURL := range currentTower.GetAllImageURLs() {
|
|
helper.DeleteTowerImage(oldImageURL)
|
|
}
|
|
finalImageURLs = newImageURLs
|
|
} else {
|
|
// Append to existing images
|
|
existingImages := currentTower.GetAllImageURLs()
|
|
finalImageURLs = append(existingImages, newImageURLs...)
|
|
}
|
|
|
|
// Update primary image (first image in the final list)
|
|
if len(finalImageURLs) > 0 && finalImageURLs[0] != "" {
|
|
updates["ImageURL"] = finalImageURLs[0]
|
|
}
|
|
|
|
// Update all images
|
|
updates["ImageURLs"] = entity.StringSlice(finalImageURLs)
|
|
}
|
|
|
|
// If no fields are updated, return an error
|
|
if len(updates) == 0 {
|
|
return errors.New("no fields to update")
|
|
}
|
|
|
|
updates["UpdatedAt"] = time.Now()
|
|
|
|
return u.towerRepo.Update(id, updates)
|
|
}
|
|
|
|
|
|
func (u *towerUsecase) Post(tower req.TowerDTO, imageFile *multipart.FileHeader) error {
|
|
err := u.validate.Struct(tower)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Validate that if it's not an external tower, DeviceID must be provided
|
|
if tower.ExternalTower != nil && !*tower.ExternalTower && tower.DeviceID == nil {
|
|
return fmt.Errorf("device_id is required for internal towers")
|
|
}
|
|
|
|
// Validate that if DeviceID is provided, the device exists
|
|
if tower.DeviceID != nil {
|
|
deviceExists, err := u.towerRepo.CheckDeviceExists(*tower.DeviceID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !deviceExists {
|
|
return fmt.Errorf("device not found")
|
|
}
|
|
}
|
|
|
|
var imageURL string
|
|
if imageFile != nil {
|
|
imageURL, err = helper.SaveTowerImage(imageFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
newTower := entity.Tower{
|
|
ID: uuid.New(),
|
|
DeviceID: tower.DeviceID, // Now nullable
|
|
TowerCode: tower.TowerCode,
|
|
Longitude: tower.Longitude,
|
|
Latitude: tower.Latitude,
|
|
ImageURL: imageURL,
|
|
ExternalTower: tower.ExternalTower, // Now nullable
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
return u.towerRepo.Post(newTower)
|
|
}
|
|
|
|
func (u *towerUsecase) GetAll() ([]res.TowerResponse, error) {
|
|
towers, err := u.towerRepo.GetAll()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
towerResp, err := helper.ConvertToTowerResponses(towers,u.geocoder)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return towerResp, nil
|
|
}
|
|
|
|
|
|
func (u *towerUsecase) GetByID(id uuid.UUID) (res.TowerResponse, error) {
|
|
tower, err := u.towerRepo.GetByID(id)
|
|
if err != nil {
|
|
return res.TowerResponse{}, err
|
|
}
|
|
|
|
towerResp, err := helper.ConvertToTowerIDResponses(tower,u.geocoder)
|
|
if err != nil {
|
|
return res.TowerResponse{}, err
|
|
}
|
|
return towerResp, nil
|
|
}
|
|
|
|
func (u *towerUsecase) BulkUploadImages(towers []req.BulkTowerImageUploadDTO, imageFiles []*multipart.FileHeader) error {
|
|
// Validate input
|
|
if len(towers) != len(imageFiles) {
|
|
return fmt.Errorf("number of towers (%d) must match number of image files (%d)", len(towers), len(imageFiles))
|
|
}
|
|
|
|
if len(towers) == 0 {
|
|
return fmt.Errorf("no towers provided")
|
|
}
|
|
|
|
// Validate all tower IDs exist
|
|
for i, tower := range towers {
|
|
_, err := u.towerRepo.GetByID(tower.TowerID)
|
|
if err != nil {
|
|
return fmt.Errorf("tower %d with ID %s not found", i, tower.TowerID)
|
|
}
|
|
}
|
|
|
|
// Save all images
|
|
imageURLs, err := helper.SaveTowerImagesBulk(imageFiles)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to save images: %w", err)
|
|
}
|
|
|
|
// Create update map
|
|
updates := make(map[uuid.UUID]string)
|
|
for i, tower := range towers {
|
|
if i < len(imageURLs) && imageURLs[i] != "" {
|
|
updates[tower.TowerID] = imageURLs[i]
|
|
}
|
|
}
|
|
|
|
// Update database
|
|
return u.towerRepo.BulkUpdateImages(updates)
|
|
}
|
|
|
|
func (u *towerUsecase) UpdateTower(id uuid.UUID, tower req.UpdateTowerDTO, imageFile *multipart.FileHeader) error {
|
|
err := u.validate.Struct(tower)
|
|
if err != nil {
|
|
return err // Return validation error
|
|
}
|
|
updates := make(map[string]interface{})
|
|
|
|
if tower.DeviceID != nil {
|
|
updates["DeviceID"] = *tower.DeviceID
|
|
}
|
|
if tower.TowerCode != nil {
|
|
updates["TowerCode"] = *tower.TowerCode
|
|
}
|
|
if tower.Longitude != nil {
|
|
updates["Longitude"] = *tower.Longitude
|
|
}
|
|
if tower.Latitude != nil {
|
|
updates["Latitude"] = *tower.Latitude
|
|
}
|
|
if tower.ExternalTower != nil {
|
|
updates["ExternalTower"] = *tower.ExternalTower
|
|
}
|
|
|
|
// Handle image upload
|
|
if imageFile != nil {
|
|
// Get current tower to delete old image
|
|
currentTower, err := u.towerRepo.GetByID(id)
|
|
if err == nil && currentTower.ImageURL != "" {
|
|
// Delete old image
|
|
helper.DeleteTowerImage(currentTower.ImageURL)
|
|
}
|
|
|
|
// Save new image
|
|
imageURL, err := helper.SaveTowerImage(imageFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
updates["ImageURL"] = imageURL
|
|
}
|
|
|
|
// If no fields are updated, return an error
|
|
if len(updates) == 0 {
|
|
return errors.New("no fields to update")
|
|
}
|
|
|
|
updates["UpdatedAt"] = time.Now()
|
|
|
|
return u.towerRepo.Update(id, updates)
|
|
}
|