NAM-APJATEL-BACKEND/delivery/controller/tower_controller.go

357 lines
12 KiB
Go

package controller
import (
"encoding/json"
"fmt"
"mime/multipart"
"net/http"
"strconv"
"strings"
"users_management/m/config"
"users_management/m/middleware"
"users_management/m/model/dto/req"
"users_management/m/usecase"
"users_management/m/utils/common"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
type TowerController struct {
tu usecase.TowerUseCase
rg *gin.RouterGroup
cfg *config.Config
}
func (tc *TowerController) Route() {
rg := tc.rg.Group("/tower")
rg.Use(middleware.ConditionalRequireAnyRole(tc.cfg,"Teknisi", "Admin","Super Admin")) // Apply middleware to all routes
{
rg.GET("", tc.GetTower())
rg.POST("", tc.CreateTower())
rg.GET("/:uuid", tc.GetTowerByID())
rg.PUT("/:uuid", tc.UpdateTower())
rg.POST("/bulk-upload-images", tc.BulkUploadImages())
}
}
func NewTowerController(tu usecase.TowerUseCase, rg *gin.RouterGroup, cfg *config.Config) *TowerController {
return &TowerController{
tu: tu,
rg: rg,
cfg: cfg,
}
}
func (tc *TowerController) BulkUploadImages() gin.HandlerFunc {
return func(c *gin.Context) {
// Parse multipart form
err := c.Request.ParseMultipartForm(50 << 20) // 50MB max for bulk
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, "Failed to parse multipart form")
return
}
// Get tower data from form
towerDataStr := c.PostForm("towers")
if towerDataStr == "" {
common.ErrorResponses(c, http.StatusBadRequest, "towers data is required")
return
}
// Parse tower data
var towersData []req.BulkTowerImageUploadDTO
if err := json.Unmarshal([]byte(towerDataStr), &towersData); err != nil {
common.ErrorResponses(c, http.StatusBadRequest, "Invalid towers data format")
return
}
// Get image files
form := c.Request.MultipartForm
files := form.File["images"]
if len(files) == 0 {
common.ErrorResponses(c, http.StatusBadRequest, "No image files provided")
return
}
if len(files) != len(towersData) {
common.ErrorResponses(c, http.StatusBadRequest,
fmt.Sprintf("Number of images (%d) must match number of towers (%d)",
len(files), len(towersData)))
return
}
// Call use case
err = tc.tu.BulkUploadImages(towersData, files)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, err.Error())
return
}
common.SingleResponses(c, fmt.Sprintf("%d tower images uploaded successfully", len(towersData)), nil)
}
}
func (tc *TowerController) GetTower() gin.HandlerFunc {
return func(c *gin.Context) {
towers, err := tc.tu.GetAll()
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, err.Error())
return
}
common.SingleResponses(c, "Success", towers)
}
}
func (tc *TowerController) CreateTower() gin.HandlerFunc {
return func(c *gin.Context) {
contentType := c.GetHeader("Content-Type")
// Handle JSON request (no images)
if strings.Contains(contentType, "application/json") {
var towerDTO req.TowerDTO
if err := c.ShouldBindJSON(&towerDTO); err != nil {
common.ErrorResponses(c, http.StatusBadRequest, "Invalid JSON format: "+err.Error())
return
}
// No image files for JSON requests
err := tc.tu.Post(towerDTO, nil)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, err.Error())
return
}
common.SingleResponses(c, "Tower has been created", nil)
return
}
// Parse multipart form
err := c.Request.ParseMultipartForm(50 << 20) // Increase to 50MB for multiple images
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, "Failed to parse multipart form")
return
}
// Extract form data
deviceIDStr := c.PostForm("dev_id")
towerCode := c.PostForm("tower_code")
longitudeStr := c.PostForm("longitude")
latitudeStr := c.PostForm("latitude")
externalTowerStr := c.PostForm("external_tower")
// Validate required fields
if towerCode == "" || longitudeStr == "" || latitudeStr == "" {
common.ErrorResponses(c, http.StatusBadRequest, "Missing required fields")
return
}
var deviceID *uuid.UUID
if deviceIDStr != "" {
parsedDeviceID, err := uuid.Parse(deviceIDStr)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, "Invalid device ID")
return
}
deviceID = &parsedDeviceID
}
// Parse coordinates
longitude, err := strconv.ParseFloat(longitudeStr, 64)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, "Invalid longitude")
return
}
latitude, err := strconv.ParseFloat(latitudeStr, 64)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, "Invalid latitude")
return
}
var externalTower *bool
if externalTowerStr != "" {
parsedExternalTower, err := strconv.ParseBool(externalTowerStr)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, "Invalid external_tower value")
return
}
externalTower = &parsedExternalTower
}
var backboneCode *string
if bc := c.PostForm("backbone_code"); bc != "" {
backboneCode = &bc
}
// Create DTO
towerDTO := req.TowerDTO{
DeviceID: deviceID,
TowerCode: towerCode,
Longitude: longitude,
Latitude: latitude,
ExternalTower: externalTower,
BackboneCode: backboneCode,
}
// Get multiple image files
form := c.Request.MultipartForm
imageFiles := form.File["images"] // Changed from "image" to "images" to support multiple
// Also support single image upload for backward compatibility
if len(imageFiles) == 0 {
if singleImage, err := c.FormFile("image"); err == nil {
imageFiles = []*multipart.FileHeader{singleImage}
}
}
err = tc.tu.PostWithMultipleImages(towerDTO, imageFiles)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, err.Error())
return
}
common.SingleResponses(c, "Tower has been created", nil)
}
}
func (tc *TowerController) GetTowerByID() gin.HandlerFunc {
return func(c *gin.Context) {
id := c.Param("uuid")
uuid, err := uuid.Parse(id)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, err.Error())
return
}
tower, err := tc.tu.GetByID(uuid)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, err.Error())
return
}
common.SingleResponses(c, "Success", tower)
}
}
func (tc *TowerController) UpdateTower() gin.HandlerFunc {
return func(c *gin.Context) {
id := c.Param("uuid")
tower_uuid, err := uuid.Parse(id)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, err.Error())
return
}
contentType := c.GetHeader("Content-Type")
// Handle JSON request (no images)
if strings.Contains(contentType, "application/json") {
var towerUpdateDTO req.UpdateTowerDTO
if err := c.ShouldBindJSON(&towerUpdateDTO); err != nil {
common.ErrorResponses(c, http.StatusBadRequest, "Invalid JSON format: "+err.Error())
return
}
// No image files for JSON requests
err := tc.tu.UpdateTowerWithMultipleImages(tower_uuid, towerUpdateDTO, nil)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, err.Error())
return
}
common.SingleResponses(c, "Tower has been updated", nil)
return
}
// Handle multipart form request
err = c.Request.ParseMultipartForm(50 << 20) // Increase to 50MB for multiple images
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, "Failed to parse multipart form")
return
}
// Create update DTO
towerUpdateDTO := req.UpdateTowerDTO{}
// Optional fields - handle form data
if deviceIDStr := c.PostForm("dev_id"); deviceIDStr != "" {
if deviceID, err := uuid.Parse(deviceIDStr); err == nil {
towerUpdateDTO.DeviceID = &deviceID
} else {
common.ErrorResponses(c, http.StatusBadRequest, "Invalid device ID format")
return
}
}
if towerCode := c.PostForm("tower_code"); towerCode != "" {
towerUpdateDTO.TowerCode = &towerCode
}
if longitudeStr := c.PostForm("longitude"); longitudeStr != "" {
if longitude, err := strconv.ParseFloat(longitudeStr, 64); err == nil {
towerUpdateDTO.Longitude = &longitude
} else {
common.ErrorResponses(c, http.StatusBadRequest, "Invalid longitude format")
return
}
}
if latitudeStr := c.PostForm("latitude"); latitudeStr != "" {
if latitude, err := strconv.ParseFloat(latitudeStr, 64); err == nil {
towerUpdateDTO.Latitude = &latitude
} else {
common.ErrorResponses(c, http.StatusBadRequest, "Invalid latitude format")
return
}
}
// Handle external_tower field
if externalTowerStr := c.PostForm("external_tower"); externalTowerStr != "" {
if externalTower, err := strconv.ParseBool(externalTowerStr); err == nil {
towerUpdateDTO.ExternalTower = &externalTower
} else {
common.ErrorResponses(c, http.StatusBadRequest, "Invalid external_tower value")
return
}
}
// Handle image_url field (for updating image URL directly)
if imageURL := c.PostForm("image_url"); imageURL != "" {
towerUpdateDTO.ImageURL = &imageURL
}
if backboneCode := c.PostForm("backbone_code"); backboneCode != "" {
towerUpdateDTO.BackboneCode = &backboneCode
}
// Get multiple image files
form := c.Request.MultipartForm
imageFiles := form.File["images"] // Support multiple images
// Also support single image upload for backward compatibility
if len(imageFiles) == 0 {
if singleImage, err := c.FormFile("image"); err == nil {
imageFiles = []*multipart.FileHeader{singleImage}
}
}
// Handle replace_images flag - if true, replace all images; if false, append to existing
replaceImages := c.PostForm("replace_images") == "true"
err = tc.tu.UpdateTowerWithMultipleImages(tower_uuid, towerUpdateDTO, imageFiles, replaceImages)
if err != nil {
common.ErrorResponses(c, http.StatusBadRequest, err.Error())
return
}
common.SingleResponses(c, "Tower has been updated", nil)
}
}