fix: fixing data type and validation also fixing deleting icon in dir

This commit is contained in:
pahmiudahgede 2025-05-16 00:13:45 +07:00
parent fc54cbd118
commit 7fb899ac8b
5 changed files with 125 additions and 65 deletions

View File

@ -1,9 +1,12 @@
package dto package dto
import "strings" import (
"strings"
)
type RequestTrashCategoryDTO struct { type RequestTrashCategoryDTO struct {
Name string `json:"name"` Name string `json:"name"`
EstimatedPrice string `json:"estimatedprice"`
Icon string `json:"icon"` Icon string `json:"icon"`
} }
@ -11,6 +14,7 @@ type ResponseTrashCategoryDTO struct {
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Icon string `json:"icon,omitempty"` Icon string `json:"icon,omitempty"`
EstimatedPrice float64 `json:"estimatedprice"`
CreatedAt string `json:"createdAt,omitempty"` CreatedAt string `json:"createdAt,omitempty"`
UpdatedAt string `json:"updatedAt,omitempty"` UpdatedAt string `json:"updatedAt,omitempty"`
Details []ResponseTrashDetailDTO `json:"details,omitempty"` Details []ResponseTrashDetailDTO `json:"details,omitempty"`
@ -37,6 +41,11 @@ func (r *RequestTrashCategoryDTO) ValidateTrashCategoryInput() (map[string][]str
if strings.TrimSpace(r.Name) == "" { if strings.TrimSpace(r.Name) == "" {
errors["name"] = append(errors["name"], "name is required") errors["name"] = append(errors["name"], "name is required")
} }
// if valid, msg := utils.ValidateFloatPrice(fmt.Sprintf("%f", r.EstimatedPrice)); !valid {
// errors["estimated_price"] = append(errors["estimated_price"], msg)
// }
if len(errors) > 0 { if len(errors) > 0 {
return errors, false return errors, false
} }
@ -50,9 +59,11 @@ func (r *RequestTrashDetailDTO) ValidateTrashDetailInput() (map[string][]string,
if strings.TrimSpace(r.Description) == "" { if strings.TrimSpace(r.Description) == "" {
errors["description"] = append(errors["description"], "description is required") errors["description"] = append(errors["description"], "description is required")
} }
if r.Price <= 0 {
errors["price"] = append(errors["price"], "price must be greater than 0") // if valid, msg := utils.ValidateFloatPrice(fmt.Sprintf("%f", r.Price)); !valid {
} // errors["price"] = append(errors["price"], msg)
// }
if len(errors) > 0 { if len(errors) > 0 {
return errors, false return errors, false
} }

View File

@ -19,10 +19,16 @@ func NewTrashHandler(trashService services.TrashService) *TrashHandler {
func (h *TrashHandler) CreateCategory(c *fiber.Ctx) error { func (h *TrashHandler) CreateCategory(c *fiber.Ctx) error {
var request dto.RequestTrashCategoryDTO var request dto.RequestTrashCategoryDTO
if err := c.BodyParser(&request); err != nil { if err := c.BodyParser(&request); err != nil {
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}}) return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
} }
errors, valid := request.ValidateTrashCategoryInput()
if !valid {
return utils.ValidationErrorResponse(c, errors)
}
iconTrash, err := c.FormFile("icon") iconTrash, err := c.FormFile("icon")
if err != nil { if err != nil {
log.Printf("Error retrieving card photo from request: %v", err) log.Printf("Error retrieving card photo from request: %v", err)

View File

@ -6,6 +6,7 @@ import (
"mime/multipart" "mime/multipart"
"os" "os"
"path/filepath" "path/filepath"
"strconv"
"time" "time"
"rijig/dto" "rijig/dto"
@ -101,9 +102,13 @@ func deleteIconTrashFIle(imagePath string) error {
} }
func (s *trashService) CreateCategory(request dto.RequestTrashCategoryDTO, iconTrash *multipart.FileHeader) (*dto.ResponseTrashCategoryDTO, error) { func (s *trashService) CreateCategory(request dto.RequestTrashCategoryDTO, iconTrash *multipart.FileHeader) (*dto.ResponseTrashCategoryDTO, error) {
errors, valid := request.ValidateTrashCategoryInput()
if !valid { parsedPrice, err := strconv.ParseFloat(request.EstimatedPrice, 64)
return nil, fmt.Errorf("validation error: %v", errors) fmt.Println("Received estimatedprice:", request.EstimatedPrice)
if err != nil {
return nil, fmt.Errorf("gagal memvalidasi harga: %v", err)
} else {
fmt.Printf("hasil parsing%v", parsedPrice)
} }
icontrashPath, err := s.saveIconOfTrash(iconTrash) icontrashPath, err := s.saveIconOfTrash(iconTrash)
@ -113,6 +118,8 @@ func (s *trashService) CreateCategory(request dto.RequestTrashCategoryDTO, iconT
category := model.TrashCategory{ category := model.TrashCategory{
Name: request.Name, Name: request.Name,
EstimatedPrice: parsedPrice,
Icon: icontrashPath, Icon: icontrashPath,
} }
@ -126,6 +133,7 @@ func (s *trashService) CreateCategory(request dto.RequestTrashCategoryDTO, iconT
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{ categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
ID: category.ID, ID: category.ID,
Name: category.Name, Name: category.Name,
EstimatedPrice: float64(category.EstimatedPrice),
Icon: category.Icon, Icon: category.Icon,
CreatedAt: createdAt, CreatedAt: createdAt,
UpdatedAt: updatedAt, UpdatedAt: updatedAt,
@ -144,6 +152,7 @@ func (s *trashService) CreateCategory(request dto.RequestTrashCategoryDTO, iconT
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{ categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
ID: c.ID, ID: c.ID,
Name: c.Name, Name: c.Name,
EstimatedPrice: float64(c.EstimatedPrice),
Icon: c.Icon, Icon: c.Icon,
CreatedAt: ccreatedAt, CreatedAt: ccreatedAt,
UpdatedAt: cupdatedAt, UpdatedAt: cupdatedAt,
@ -229,6 +238,7 @@ func (s *trashService) GetCategories() ([]dto.ResponseTrashCategoryDTO, error) {
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{ categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
ID: categoryData["id"].(string), ID: categoryData["id"].(string),
Name: categoryData["name"].(string), Name: categoryData["name"].(string),
EstimatedPrice: categoryData["estimatedprice"].(float64),
Icon: categoryData["icon"].(string), Icon: categoryData["icon"].(string),
CreatedAt: categoryData["createdAt"].(string), CreatedAt: categoryData["createdAt"].(string),
UpdatedAt: categoryData["updatedAt"].(string), UpdatedAt: categoryData["updatedAt"].(string),
@ -244,19 +254,19 @@ func (s *trashService) GetCategories() ([]dto.ResponseTrashCategoryDTO, error) {
var categoriesDTO []dto.ResponseTrashCategoryDTO var categoriesDTO []dto.ResponseTrashCategoryDTO
for _, category := range categories { for _, category := range categories {
// path := os.Getenv("BASE_URL")
createdAt, _ := utils.FormatDateToIndonesianFormat(category.CreatedAt) createdAt, _ := utils.FormatDateToIndonesianFormat(category.CreatedAt)
updatedAt, _ := utils.FormatDateToIndonesianFormat(category.UpdatedAt) updatedAt, _ := utils.FormatDateToIndonesianFormat(category.UpdatedAt)
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{ categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
ID: category.ID, ID: category.ID,
Name: category.Name, Name: category.Name,
EstimatedPrice: category.EstimatedPrice,
Icon: category.Icon, Icon: category.Icon,
CreatedAt: createdAt, CreatedAt: createdAt,
UpdatedAt: updatedAt, UpdatedAt: updatedAt,
}) })
} }
cacheData := map[string]interface{}{ cacheData := map[string]interface{}{
"data": categoriesDTO, "data": categoriesDTO,
} }
@ -276,6 +286,7 @@ func (s *trashService) GetCategoryByID(id string) (*dto.ResponseTrashCategoryDTO
return &dto.ResponseTrashCategoryDTO{ return &dto.ResponseTrashCategoryDTO{
ID: categoryData["id"].(string), ID: categoryData["id"].(string),
Name: categoryData["name"].(string), Name: categoryData["name"].(string),
EstimatedPrice: categoryData["estimatedprice"].(float64),
Icon: categoryData["icon"].(string), Icon: categoryData["icon"].(string),
CreatedAt: categoryData["createdAt"].(string), CreatedAt: categoryData["createdAt"].(string),
UpdatedAt: categoryData["updatedAt"].(string), UpdatedAt: categoryData["updatedAt"].(string),
@ -294,6 +305,7 @@ func (s *trashService) GetCategoryByID(id string) (*dto.ResponseTrashCategoryDTO
categoryDTO := &dto.ResponseTrashCategoryDTO{ categoryDTO := &dto.ResponseTrashCategoryDTO{
ID: category.ID, ID: category.ID,
Name: category.Name, Name: category.Name,
EstimatedPrice: category.EstimatedPrice,
Icon: category.Icon, Icon: category.Icon,
CreatedAt: createdAt, CreatedAt: createdAt,
UpdatedAt: updatedAt, UpdatedAt: updatedAt,
@ -407,6 +419,7 @@ func (s *trashService) UpdateCategory(id string, request dto.RequestTrashCategor
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{ categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
ID: category.ID, ID: category.ID,
Name: category.Name, Name: category.Name,
EstimatedPrice: category.EstimatedPrice,
Icon: category.Icon, Icon: category.Icon,
CreatedAt: createdAt, CreatedAt: createdAt,
UpdatedAt: updatedAt, UpdatedAt: updatedAt,
@ -425,6 +438,7 @@ func (s *trashService) UpdateCategory(id string, request dto.RequestTrashCategor
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{ categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
ID: c.ID, ID: c.ID,
Name: c.Name, Name: c.Name,
EstimatedPrice: c.EstimatedPrice,
Icon: c.Icon, Icon: c.Icon,
CreatedAt: ccreatedAt, CreatedAt: ccreatedAt,
UpdatedAt: cupdatedAt, UpdatedAt: cupdatedAt,
@ -512,6 +526,15 @@ func (s *trashService) DeleteCategory(id string) error {
} }
} }
category, err := s.TrashRepo.GetCategoryByID(id)
if err != nil {
return fmt.Errorf("failed to fetch category for deletion: %v", err)
}
if err := deleteIconTrashFIle(category.Icon); err != nil {
return fmt.Errorf("error deleting icon for category %s: %v", id, err)
}
if err := s.TrashRepo.DeleteCategory(id); err != nil { if err := s.TrashRepo.DeleteCategory(id); err != nil {
return fmt.Errorf("failed to delete category: %v", err) return fmt.Errorf("failed to delete category: %v", err)
} }

View File

@ -6,6 +6,7 @@ type TrashCategory struct {
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"` ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
Name string `gorm:"not null" json:"name"` Name string `gorm:"not null" json:"name"`
Icon string `json:"icon,omitempty"` Icon string `json:"icon,omitempty"`
EstimatedPrice float64 `gorm:"not null" json:"estimated_price"`
Details []TrashDetail `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE;" json:"details"` Details []TrashDetail `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE;" json:"details"`
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"` CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"` UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`

View File

@ -1,7 +1,9 @@
package utils package utils
import ( import (
"fmt"
"regexp" "regexp"
"strconv"
"strings" "strings"
) )
@ -42,3 +44,20 @@ func isSpecialCharacter(char rune) bool {
specialChars := "!@#$%^&*()-_=+[]{}|;:'\",.<>?/`~" specialChars := "!@#$%^&*()-_=+[]{}|;:'\",.<>?/`~"
return strings.ContainsRune(specialChars, char) return strings.ContainsRune(specialChars, char)
} }
func ValidateFloatPrice(price string) (float64, error) {
// price = strings.Trim(price, `"`)
// price = strings.TrimSpace(price)
parsedPrice, err := strconv.ParseFloat(price, 64)
if err != nil {
return 0, fmt.Errorf("harga tidak valid. Format harga harus angka desimal.")
}
if parsedPrice <= 0 {
return 0, fmt.Errorf("harga harus lebih besar dari 0.")
}
return parsedPrice, nil
}