fix: code and statemnt and add update delete products(yet)
This commit is contained in:
parent
4f586076e7
commit
3de0d9c101
|
@ -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")
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue