Merge pull request 'adding delete method' (#20) from feature/responses-v2 into dev
Reviewed-on: winter-access/backend_nam#20
This commit is contained in:
commit
c90d3ea345
|
|
@ -48,9 +48,52 @@ func (c *DeviceDetailsController) Route() {
|
||||||
deviceDetails.PUT("/:id/bulk-update-customers-by-port", c.bulkUpdateCustomersByPort) // 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)
|
deviceDetails.DELETE("/:id/remove-customer-by-port", c.removeCustomerByPort)
|
||||||
|
|
||||||
|
// delete images by filename
|
||||||
|
deviceDetails.DELETE("/:id/images/:filename", c.deleteDeviceImage)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *DeviceDetailsController) deleteDeviceImage(ctx *gin.Context) {
|
||||||
|
// Parse device ID
|
||||||
|
id := ctx.Param("id")
|
||||||
|
deviceID, err := uuid.Parse(id)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid device ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get filename from URL parameter
|
||||||
|
filename := ctx.Param("filename")
|
||||||
|
if filename == "" {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, "Filename is required")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate filename format (basic security check)
|
||||||
|
if strings.Contains(filename, "..") || strings.Contains(filename, "/") || strings.Contains(filename, "\\") {
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, "Invalid filename format")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call use case to delete the image
|
||||||
|
err = c.deviceDetailsUC.DeleteDeviceImage(deviceID, filename)
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "device not found" {
|
||||||
|
common.ErrorResponses(ctx, http.StatusNotFound, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err.Error() == "image not found in device" {
|
||||||
|
common.ErrorResponses(ctx, http.StatusNotFound, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
common.ErrorResponses(ctx, http.StatusBadRequest, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
common.SingleResponses(ctx, fmt.Sprintf("Image %s deleted successfully", filename), nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *DeviceDetailsController) updateCustomerByPort(ctx *gin.Context) {
|
func (c *DeviceDetailsController) updateCustomerByPort(ctx *gin.Context) {
|
||||||
id := ctx.Param("id")
|
id := ctx.Param("id")
|
||||||
deviceID, err := uuid.Parse(id)
|
deviceID, err := uuid.Parse(id)
|
||||||
|
|
|
||||||
|
|
@ -44,4 +44,8 @@ type BulkUpdateCustomersByPortDTO struct {
|
||||||
|
|
||||||
type RemoveCustomerByPortDTO struct {
|
type RemoveCustomerByPortDTO struct {
|
||||||
PortNumber int `json:"port_number" binding:"required,min=1"`
|
PortNumber int `json:"port_number" binding:"required,min=1"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteImageDTO struct {
|
||||||
|
Filename string `json:"filename" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"users_management/m/model/dto/req"
|
"users_management/m/model/dto/req"
|
||||||
"users_management/m/model/dto/res"
|
"users_management/m/model/dto/res"
|
||||||
|
|
@ -34,6 +35,7 @@ type DeviceDetailsUseCase interface {
|
||||||
BulkUpdateCustomersByPort(deviceID uuid.UUID, updates []req.UpdateCustomerByPortDTO) error
|
BulkUpdateCustomersByPort(deviceID uuid.UUID, updates []req.UpdateCustomerByPortDTO) error
|
||||||
RemoveCustomerByPort(deviceID uuid.UUID, portNumber int) error
|
RemoveCustomerByPort(deviceID uuid.UUID, portNumber int) error
|
||||||
UpdateDeviceDetailsWithMultipleImages(id uuid.UUID, deviceDTO req.UpdateDeviceDetailsDTO, imageFiles []*multipart.FileHeader, replaceImages ...bool) error
|
UpdateDeviceDetailsWithMultipleImages(id uuid.UUID, deviceDTO req.UpdateDeviceDetailsDTO, imageFiles []*multipart.FileHeader, replaceImages ...bool) error
|
||||||
|
DeleteDeviceImage(deviceID uuid.UUID, filename string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type deviceDetailsUseCase struct {
|
type deviceDetailsUseCase struct {
|
||||||
|
|
@ -50,6 +52,72 @@ func NewDeviceDetailsUseCase(deviceDetailsRepo repository.DeviceDetailsRepo, geo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *deviceDetailsUseCase) DeleteDeviceImage(deviceID uuid.UUID, filename string) error {
|
||||||
|
// Get current device
|
||||||
|
currentDevice, err := u.deviceDetailsRepo.GetByID(deviceID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("device not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all current image URLs
|
||||||
|
allImageURLs := currentDevice.GetAllImageURLs()
|
||||||
|
|
||||||
|
// Find the image URL that contains the filename
|
||||||
|
var imageURLToDelete string
|
||||||
|
var updatedImageURLs []string
|
||||||
|
|
||||||
|
for _, imageURL := range allImageURLs {
|
||||||
|
if strings.Contains(imageURL, filename) {
|
||||||
|
imageURLToDelete = imageURL
|
||||||
|
} else {
|
||||||
|
updatedImageURLs = append(updatedImageURLs, imageURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if image was found
|
||||||
|
if imageURLToDelete == "" {
|
||||||
|
return fmt.Errorf("image not found in device")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't allow deleting the last image if it's the primary image
|
||||||
|
if len(allImageURLs) == 1 && currentDevice.ImageURL != nil && *currentDevice.ImageURL == imageURLToDelete {
|
||||||
|
return fmt.Errorf("cannot delete the only remaining image")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare updates
|
||||||
|
updates := map[string]interface{}{
|
||||||
|
"updated_at": time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(updatedImageURLs) == 0 {
|
||||||
|
// No images left
|
||||||
|
updates["image_url"] = nil
|
||||||
|
updates["image_urls"] = entity.StringSlice([]string{})
|
||||||
|
} else {
|
||||||
|
// Update primary image if it was deleted
|
||||||
|
if currentDevice.ImageURL != nil && *currentDevice.ImageURL == imageURLToDelete {
|
||||||
|
updates["image_url"] = updatedImageURLs[0] // Set first remaining image as primary
|
||||||
|
}
|
||||||
|
// Update all images
|
||||||
|
updates["image_urls"] = entity.StringSlice(updatedImageURLs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update database
|
||||||
|
err = u.deviceDetailsRepo.Update(deviceID, updates)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to update device in database: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the actual file from filesystem
|
||||||
|
err = helper.DeleteDeviceImage(imageURLToDelete)
|
||||||
|
if err != nil {
|
||||||
|
// Log error but don't fail the request since database was already updated
|
||||||
|
fmt.Printf("Warning: Failed to delete image file %s: %v\n", imageURLToDelete, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (u *deviceDetailsUseCase) UpdateDeviceDetailsWithMultipleImages(id uuid.UUID, deviceDTO req.UpdateDeviceDetailsDTO, imageFiles []*multipart.FileHeader, replaceImages ...bool) error {
|
func (u *deviceDetailsUseCase) UpdateDeviceDetailsWithMultipleImages(id uuid.UUID, deviceDTO req.UpdateDeviceDetailsDTO, imageFiles []*multipart.FileHeader, replaceImages ...bool) error {
|
||||||
err := u.validate.Struct(deviceDTO)
|
err := u.validate.Struct(deviceDTO)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue