package controller import ( "bytes" "encoding/json" "fmt" "io" "net/http" "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 DeviceDetailsController struct { deviceDetailsUC usecase.DeviceDetailsUseCase rg *gin.RouterGroup } func NewDeviceDetailsController(deviceDetailsUC usecase.DeviceDetailsUseCase, rg *gin.RouterGroup) *DeviceDetailsController { return &DeviceDetailsController{ deviceDetailsUC: deviceDetailsUC, rg: rg, } } func (c *DeviceDetailsController) Route() { deviceDetails := c.rg.Group("/device-details") deviceDetails.Use(middleware.RequireAnyRole("Teknisi", "Admin", "Superadmin")) { deviceDetails.GET("", c.getAllDeviceDetails) deviceDetails.POST("", c.createDeviceDetails) deviceDetails.GET("/:id", c.getDeviceDetailsByID) deviceDetails.PUT("/:id", c.updateDeviceDetails) deviceDetails.DELETE("/:id", c.deleteDeviceDetails) deviceDetails.POST("/:id/recalculate-ports", c.recalculatePortUsage) deviceDetails.POST("/:id/assign-customer", c.assignCustomer) deviceDetails.PUT("/:id/port-usage", c.updatePortUsage) // New endpoint deviceDetails.PUT("/:id/port-assignments", c.updatePortAssignments) // New endpoint deviceDetails.PUT("/:id/update-customer-by-port", c.updateCustomerByPort) // Updated endpoint name deviceDetails.PUT("/:id/bulk-update-customers-by-port", c.bulkUpdateCustomersByPort) // Updated endpoint name deviceDetails.DELETE("/:id/remove-customer-by-port", c.removeCustomerByPort) } } func (c *DeviceDetailsController) updateCustomerByPort(ctx *gin.Context) { id := ctx.Param("id") deviceID, err := uuid.Parse(id) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID") return } var request req.UpdateCustomerByPortDTO if err := ctx.ShouldBindJSON(&request); err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } err = c.deviceDetailsUC.UpdateCustomerByPort(deviceID, request) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } if request.NewCustomerName == nil { common.SingleResponses(ctx, fmt.Sprintf("Customer removed from port %d successfully", request.PortNumber), nil) } else { common.SingleResponses(ctx, fmt.Sprintf("Customer assigned to port %d successfully", request.PortNumber), nil) } } func (c *DeviceDetailsController) bulkUpdateCustomersByPort(ctx *gin.Context) { id := ctx.Param("id") deviceID, err := uuid.Parse(id) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID") return } var request req.BulkUpdateCustomersByPortDTO if err := ctx.ShouldBindJSON(&request); err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } err = c.deviceDetailsUC.BulkUpdateCustomersByPort(deviceID, request.Updates) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } common.SingleResponses(ctx, fmt.Sprintf("%d port assignments updated successfully", len(request.Updates)), nil) } func (c *DeviceDetailsController) removeCustomerByPort(ctx *gin.Context) { id := ctx.Param("id") deviceID, err := uuid.Parse(id) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID") return } var request req.RemoveCustomerByPortDTO if err := ctx.ShouldBindJSON(&request); err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } err = c.deviceDetailsUC.RemoveCustomerByPort(deviceID, request.PortNumber) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } common.SingleResponses(ctx, fmt.Sprintf("Customer removed from port %d successfully", request.PortNumber), nil) } func (c *DeviceDetailsController) assignCustomer(ctx *gin.Context) { id := ctx.Param("id") deviceID, err := uuid.Parse(id) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID") return } // Try to parse as array first var arrayRequest []req.AssignMultipleCustomersDTO // Try to parse as single object var singleRequest struct { CustomerName string `json:"customer_name" binding:"required"` PortNumber *int `json:"port_number,omitempty"` } // Get raw JSON to determine the structure rawData, err := ctx.GetRawData() if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid JSON data") return } // Reset the request body for subsequent parsing ctx.Request.Body = io.NopCloser(bytes.NewBuffer(rawData)) // Check if it's an array by looking at the first character trimmed := bytes.TrimSpace(rawData) if len(trimmed) > 0 && trimmed[0] == '[' { // It's an array if err := json.Unmarshal(rawData, &arrayRequest); err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid array format: "+err.Error()) return } // Process array of assignments err = c.deviceDetailsUC.AssignMultipleCustomersToPort(deviceID, arrayRequest) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } common.SingleResponses(ctx, fmt.Sprintf("%d customers assigned successfully", len(arrayRequest)), nil) } else { // It's a single object if err := json.Unmarshal(rawData, &singleRequest); err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid object format: "+err.Error()) return } // Process single assignment err = c.deviceDetailsUC.AssignCustomerToPort(deviceID, singleRequest.CustomerName, singleRequest.PortNumber) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } common.SingleResponses(ctx, "Customer assigned successfully", nil) } } func (c *DeviceDetailsController) getAllDeviceDetails(ctx *gin.Context) { devices, err := c.deviceDetailsUC.GetAllDeviceDetails() if err != nil { common.ErrorResponses(ctx, http.StatusInternalServerError, err.Error()) return } common.SingleResponses(ctx, "Device details retrieved successfully", devices) } func (c *DeviceDetailsController) createDeviceDetails(ctx *gin.Context) { var request req.DeviceDetailsDTO if err := ctx.ShouldBindJSON(&request); err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } err := c.deviceDetailsUC.CreateDeviceDetails(request) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } common.SingleResponses(ctx, "Device details created successfully", nil) } func (c *DeviceDetailsController) getDeviceDetailsByID(ctx *gin.Context) { id := ctx.Param("id") deviceID, err := uuid.Parse(id) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID") return } device, err := c.deviceDetailsUC.GetDeviceDetailsByID(deviceID) if err != nil { common.ErrorResponses(ctx, http.StatusNotFound, err.Error()) return } common.SingleResponses(ctx, "Device details retrieved successfully", device) } func (c *DeviceDetailsController) updateDeviceDetails(ctx *gin.Context) { id := ctx.Param("id") deviceID, err := uuid.Parse(id) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID") return } var request req.UpdateDeviceDetailsDTO if err := ctx.ShouldBindJSON(&request); err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } err = c.deviceDetailsUC.UpdateDeviceDetails(deviceID, request) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } common.SingleResponses(ctx, "Device details updated successfully", nil) } func (c *DeviceDetailsController) deleteDeviceDetails(ctx *gin.Context) { id := ctx.Param("id") deviceID, err := uuid.Parse(id) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID") return } err = c.deviceDetailsUC.DeleteDeviceDetails(deviceID) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } common.SingleResponses(ctx, "Device details deleted successfully", nil) } func (c *DeviceDetailsController) recalculatePortUsage(ctx *gin.Context) { id := ctx.Param("id") deviceID, err := uuid.Parse(id) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID") return } err = c.deviceDetailsUC.RecalculatePortUsage(deviceID) if err != nil { common.ErrorResponses(ctx, http.StatusInternalServerError, err.Error()) return } common.SingleResponses(ctx, "Port usage recalculated successfully", nil) } func (c *DeviceDetailsController) updatePortUsage(ctx *gin.Context) { id := ctx.Param("id") deviceID, err := uuid.Parse(id) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID") return } var request req.UpdatePortUsageDTO if err := ctx.ShouldBindJSON(&request); err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } err = c.deviceDetailsUC.UpdatePortUsage(deviceID, request.PortUsed) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } common.SingleResponses(ctx, "Port usage updated successfully", nil) } func (c *DeviceDetailsController) updatePortAssignments(ctx *gin.Context) { id := ctx.Param("id") deviceID, err := uuid.Parse(id) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID") return } var request req.UpdatePortAssignmentsDTO if err := ctx.ShouldBindJSON(&request); err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } err = c.deviceDetailsUC.UpdatePortAssignments(deviceID, request.PortAssignments) if err != nil { common.ErrorResponses(ctx, http.StatusBadRequest, err.Error()) return } common.SingleResponses(ctx, "Port assignments updated successfully", nil) }