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 } 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) 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) 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 } // 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) }