fix: code and statemnt and add update delete products(yet)

This commit is contained in:
pahmiudahgede 2025-02-26 15:03:02 +07:00
parent 4f586076e7
commit 3de0d9c101
4 changed files with 331 additions and 1 deletions

View File

@ -118,3 +118,109 @@ func (h *ProductHandler) GetProductByID(c *fiber.Ctx) error {
return utils.SuccessResponse(c, product, "Product fetched successfully") return utils.SuccessResponse(c, product, "Product fetched successfully")
} }
func (h *ProductHandler) UpdateProduct(c *fiber.Ctx) error {
userID, ok := c.Locals("userID").(string)
if !ok {
log.Println("User ID not found in Locals")
return utils.GenericResponse(c, fiber.StatusUnauthorized, "User ID not found")
}
productID := c.Params("product_id")
if productID == "" {
return utils.GenericResponse(c, fiber.StatusBadRequest, "Product ID is required")
}
var productDTO dto.RequestProductDTO
if err := c.BodyParser(&productDTO); err != nil {
log.Printf("Error parsing body: %v", err)
return utils.GenericResponse(c, fiber.StatusBadRequest, "Invalid request body")
}
productImages, err := c.MultipartForm()
if err != nil {
log.Printf("Error parsing form data: %v", err)
return utils.GenericResponse(c, fiber.StatusBadRequest, "Error parsing form data")
}
productDTO.ProductImages = productImages.File["product_images"]
product, err := h.ProductService.UpdateProduct(userID, productID, &productDTO)
if err != nil {
log.Printf("Error updating product: %v", err)
return utils.GenericResponse(c, fiber.StatusConflict, err.Error())
}
return utils.CreateResponse(c, product, "Product updated successfully")
}
func (h *ProductHandler) DeleteProduct(c *fiber.Ctx) error {
productID := c.Params("product_id")
if productID == "" {
return utils.GenericResponse(c, fiber.StatusBadRequest, "Product ID is required")
}
err := h.ProductService.DeleteProduct(productID)
if err != nil {
log.Printf("Error deleting product: %v", err)
return utils.GenericResponse(c, fiber.StatusConflict, fmt.Sprintf("Failed to delete product: %v", err))
}
return utils.GenericResponse(c, fiber.StatusOK, "Product deleted successfully")
}
func (h *ProductHandler) DeleteProducts(c *fiber.Ctx) error {
var productIDs []string
if err := c.BodyParser(&productIDs); err != nil {
log.Printf("Error parsing product IDs: %v", err)
return utils.GenericResponse(c, fiber.StatusBadRequest, "Invalid input for product IDs")
}
if len(productIDs) == 0 {
return utils.GenericResponse(c, fiber.StatusBadRequest, "No product IDs provided")
}
err := h.ProductService.DeleteProducts(productIDs)
if err != nil {
log.Printf("Error deleting products: %v", err)
return utils.GenericResponse(c, fiber.StatusConflict, fmt.Sprintf("Failed to delete products: %v", err))
}
return utils.GenericResponse(c, fiber.StatusOK, "Products deleted successfully")
}
func (h *ProductHandler) DeleteProductImage(c *fiber.Ctx) error {
imageID := c.Params("image_id")
if imageID == "" {
return utils.GenericResponse(c, fiber.StatusBadRequest, "Image ID is required")
}
err := h.ProductService.DeleteProductImage(imageID)
if err != nil {
log.Printf("Error deleting product image: %v", err)
return utils.GenericResponse(c, fiber.StatusConflict, fmt.Sprintf("Failed to delete product image: %v", err))
}
return utils.GenericResponse(c, fiber.StatusOK, "Product image deleted successfully")
}
func (h *ProductHandler) DeleteProductImages(c *fiber.Ctx) error {
var imageIDs []string
if err := c.BodyParser(&imageIDs); err != nil {
log.Printf("Error parsing image IDs: %v", err)
return utils.GenericResponse(c, fiber.StatusBadRequest, "Invalid input for image IDs")
}
if len(imageIDs) == 0 {
return utils.GenericResponse(c, fiber.StatusBadRequest, "No image IDs provided")
}
err := h.ProductService.DeleteProductImages(imageIDs)
if err != nil {
log.Printf("Error deleting product images: %v", err)
return utils.GenericResponse(c, fiber.StatusConflict, fmt.Sprintf("Failed to delete product images: %v", err))
}
return utils.GenericResponse(c, fiber.StatusOK, "Product images deleted successfully")
}

View File

@ -1,6 +1,8 @@
package repositories package repositories
import ( import (
"fmt"
"github.com/pahmiudahgede/senggoldong/model" "github.com/pahmiudahgede/senggoldong/model"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -12,11 +14,14 @@ type ProductRepository interface {
GetProductsByStoreID(storeID string) ([]model.Product, error) GetProductsByStoreID(storeID string) ([]model.Product, error)
FindProductsByStoreID(storeID string, page, limit int) ([]model.Product, error) FindProductsByStoreID(storeID string, page, limit int) ([]model.Product, error)
FindProductImagesByProductID(productID string) ([]model.ProductImage, error) FindProductImagesByProductID(productID string) ([]model.ProductImage, error)
GetProductImageByID(imageID string) (*model.ProductImage, error)
UpdateProduct(product *model.Product) error UpdateProduct(product *model.Product) error
DeleteProduct(productID string) error DeleteProduct(productID string) error
DeleteProductsByID(productIDs []string) error
AddProductImages(images []model.ProductImage) error AddProductImages(images []model.ProductImage) error
DeleteProductImagesByProductID(productID string) error DeleteProductImagesByProductID(productID string) error
DeleteProductImagesByID(imageIDs []string) error
DeleteProductImageByID(imageID string) error
} }
type productRepository struct { type productRepository struct {
@ -81,6 +86,17 @@ func (r *productRepository) FindProductImagesByProductID(productID string) ([]mo
return productImages, nil return productImages, nil
} }
func (r *productRepository) GetProductImageByID(imageID string) (*model.ProductImage, error) {
var productImage model.ProductImage
if err := r.DB.Where("id = ?", imageID).First(&productImage).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, err
}
return &productImage, nil
}
func (r *productRepository) UpdateProduct(product *model.Product) error { func (r *productRepository) UpdateProduct(product *model.Product) error {
return r.DB.Save(product).Error return r.DB.Save(product).Error
} }
@ -89,6 +105,13 @@ func (r *productRepository) DeleteProduct(productID string) error {
return r.DB.Delete(&model.Product{}, "id = ?", productID).Error return r.DB.Delete(&model.Product{}, "id = ?", productID).Error
} }
func (r *productRepository) DeleteProductsByID(productIDs []string) error {
if err := r.DB.Where("id IN ?", productIDs).Delete(&model.Product{}).Error; err != nil {
return fmt.Errorf("failed to delete products: %v", err)
}
return nil
}
func (r *productRepository) AddProductImages(images []model.ProductImage) error { func (r *productRepository) AddProductImages(images []model.ProductImage) error {
if len(images) == 0 { if len(images) == 0 {
return nil return nil
@ -99,3 +122,17 @@ func (r *productRepository) AddProductImages(images []model.ProductImage) error
func (r *productRepository) DeleteProductImagesByProductID(productID string) error { func (r *productRepository) DeleteProductImagesByProductID(productID string) error {
return r.DB.Where("product_id = ?", productID).Delete(&model.ProductImage{}).Error return r.DB.Where("product_id = ?", productID).Delete(&model.ProductImage{}).Error
} }
func (r *productRepository) DeleteProductImagesByID(imageIDs []string) error {
if err := r.DB.Where("id IN ?", imageIDs).Delete(&model.ProductImage{}).Error; err != nil {
return fmt.Errorf("failed to delete product images: %v", err)
}
return nil
}
func (r *productRepository) DeleteProductImageByID(imageID string) error {
if err := r.DB.Where("id = ?", imageID).Delete(&model.ProductImage{}).Error; err != nil {
return fmt.Errorf("failed to delete product image: %v", err)
}
return nil
}

View File

@ -19,6 +19,13 @@ type ProductService interface {
GetAllProductsByStoreID(userID string, page, limit int) ([]dto.ResponseProductDTO, int64, error) GetAllProductsByStoreID(userID string, page, limit int) ([]dto.ResponseProductDTO, int64, error)
GetProductByID(productID string) (*dto.ResponseProductDTO, error) GetProductByID(productID string) (*dto.ResponseProductDTO, error)
UpdateProduct(userID, productID string, productDTO *dto.RequestProductDTO) (*dto.ResponseProductDTO, error)
DeleteProduct(productID string) error
DeleteProducts(productIDs []string) error
DeleteProductImages(imageIDs []string) error
DeleteProductImage(imageID string) error
} }
type productService struct { type productService struct {
@ -191,8 +198,135 @@ func (s *productService) GetProductByID(productID string) (*dto.ResponseProductD
return productDTO, nil return productDTO, nil
} }
func (s *productService) UpdateProduct(userID, productID string, productDTO *dto.RequestProductDTO) (*dto.ResponseProductDTO, error) {
store, err := s.storeRepo.FindStoreByUserID(userID)
if err != nil {
return nil, fmt.Errorf("error retrieving store by user ID: %w", err)
}
if store == nil {
return nil, fmt.Errorf("store not found for user %s", userID)
}
product, err := s.productRepo.GetProductByID(productID)
if err != nil {
return nil, fmt.Errorf("failed to retrieve product: %v", err)
}
if product == nil {
return nil, fmt.Errorf("product not found")
}
if product.StoreID != store.ID {
return nil, fmt.Errorf("user does not own the store for this product")
}
if err := s.deleteProductImages(productID); err != nil {
return nil, fmt.Errorf("failed to delete old product images: %v", err)
}
var productImages []model.ProductImage
for _, file := range productDTO.ProductImages {
imagePath, err := s.SaveProductImage(file, "product")
if err != nil {
return nil, fmt.Errorf("failed to save product image: %w", err)
}
productImages = append(productImages, model.ProductImage{
ImageURL: imagePath,
})
}
product.ProductName = productDTO.ProductName
product.Quantity = productDTO.Quantity
product.ProductImages = productImages
if err := s.productRepo.UpdateProduct(product); err != nil {
return nil, fmt.Errorf("failed to update product: %w", err)
}
createdAt, _ := utils.FormatDateToIndonesianFormat(product.CreatedAt)
updatedAt, _ := utils.FormatDateToIndonesianFormat(product.UpdatedAt)
var productImagesDTO []dto.ResponseProductImageDTO
for _, img := range product.ProductImages {
productImagesDTO = append(productImagesDTO, dto.ResponseProductImageDTO{
ID: img.ID,
ProductID: img.ProductID,
ImageURL: img.ImageURL,
})
}
productDTOResponse := &dto.ResponseProductDTO{
ID: product.ID,
StoreID: product.StoreID,
ProductName: product.ProductName,
Quantity: product.Quantity,
ProductImages: productImagesDTO,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
}
return productDTOResponse, nil
}
func (s *productService) DeleteProduct(productID string) error {
if err := s.deleteProductImages(productID); err != nil {
return fmt.Errorf("failed to delete associated product images: %w", err)
}
if err := s.productRepo.DeleteProduct(productID); err != nil {
return fmt.Errorf("failed to delete product: %w", err)
}
return nil
}
func (s *productService) DeleteProducts(productIDs []string) error {
for _, productID := range productIDs {
if err := s.deleteProductImages(productID); err != nil {
return fmt.Errorf("failed to delete associated images for product %s: %w", productID, err)
}
}
if err := s.productRepo.DeleteProductsByID(productIDs); err != nil {
return fmt.Errorf("failed to delete products: %w", err)
}
return nil
}
func (s *productService) DeleteProductImages(imageIDs []string) error {
for _, imageID := range imageIDs {
if err := s.deleteImageFile(imageID); err != nil {
return fmt.Errorf("failed to delete image file with ID %s: %w", imageID, err)
}
}
if err := s.productRepo.DeleteProductImagesByID(imageIDs); err != nil {
return fmt.Errorf("failed to delete product images from database: %w", err)
}
return nil
}
func (s *productService) DeleteProductImage(imageID string) error {
if err := s.deleteImageFile(imageID); err != nil {
return fmt.Errorf("failed to delete image file with ID %s: %w", imageID, err)
}
if err := s.productRepo.DeleteProductImageByID(imageID); err != nil {
return fmt.Errorf("failed to delete product image from database: %w", err)
}
return nil
}
func (s *productService) SaveProductImage(file *multipart.FileHeader, imageType string) (string, error) { func (s *productService) SaveProductImage(file *multipart.FileHeader, imageType string) (string, error) {
imageDir := fmt.Sprintf("./public%s/uploads/store/%s", os.Getenv("BASE_URL"), imageType) imageDir := fmt.Sprintf("./public%s/uploads/store/%s", os.Getenv("BASE_URL"), imageType)
if _, err := os.Stat(imageDir); os.IsNotExist(err) { if _, err := os.Stat(imageDir); os.IsNotExist(err) {
if err := os.MkdirAll(imageDir, os.ModePerm); err != nil { if err := os.MkdirAll(imageDir, os.ModePerm); err != nil {
return "", fmt.Errorf("failed to create directory for %s image: %v", imageType, err) return "", fmt.Errorf("failed to create directory for %s image: %v", imageType, err)
@ -226,3 +360,45 @@ func (s *productService) SaveProductImage(file *multipart.FileHeader, imageType
return filepath.Join("/uploads/store/", imageType, fileName), nil return filepath.Join("/uploads/store/", imageType, fileName), nil
} }
func (s *productService) deleteProductImages(productID string) error {
productImages, err := s.productRepo.FindProductImagesByProductID(productID)
if err != nil {
return fmt.Errorf("failed to fetch product images: %w", err)
}
for _, img := range productImages {
if err := s.deleteImageFile(img.ID); err != nil {
return fmt.Errorf("failed to delete image file: %w", err)
}
}
if err := s.productRepo.DeleteProductImagesByProductID(productID); err != nil {
return fmt.Errorf("failed to delete product images in database: %w", err)
}
return nil
}
func (s *productService) deleteImageFile(imageID string) error {
productImage, err := s.productRepo.GetProductImageByID(imageID)
if err != nil {
return fmt.Errorf("failed to fetch product image: %w", err)
}
if productImage == nil {
return fmt.Errorf("product image with ID %s not found", imageID)
}
extension := filepath.Ext(productImage.ImageURL)
imagePath := fmt.Sprintf("./public/uploads/store/product/%s%s", imageID, extension)
if err := os.Remove(imagePath); err != nil {
return fmt.Errorf("failed to delete image file: %w", err)
}
return nil
}

View File

@ -19,6 +19,17 @@ func ProductRouter(api fiber.Router) {
productAPI := api.Group("/productinstore") productAPI := api.Group("/productinstore")
productAPI.Post("/add-product", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), productHandler.CreateProduct) productAPI.Post("/add-product", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), productHandler.CreateProduct)
productAPI.Get("/getproductbyuser", middleware.AuthMiddleware, productHandler.GetAllProductsByStoreID) productAPI.Get("/getproductbyuser", middleware.AuthMiddleware, productHandler.GetAllProductsByStoreID)
productAPI.Get("getproduct/:product_id", middleware.AuthMiddleware, productHandler.GetProductByID) productAPI.Get("getproduct/:product_id", middleware.AuthMiddleware, productHandler.GetProductByID)
productAPI.Put("updateproduct/:product_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), productHandler.UpdateProduct)
productAPI.Delete("/delete/:product_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), productHandler.DeleteProduct)
productAPI.Delete("/delete-products", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), productHandler.DeleteProducts)
productAPI.Delete("/delete-image/:image_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), productHandler.DeleteProductImage)
productAPI.Delete("/delete-images", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), productHandler.DeleteProductImages)
} }