feat: add feature trash data

This commit is contained in:
pahmiudahgede 2025-02-21 01:41:20 +07:00
parent 8f475d1a0b
commit 36595caebb
8 changed files with 803 additions and 1 deletions

View File

@ -46,6 +46,8 @@ func ConnectDatabase() {
&model.Article{},
&model.Banner{},
&model.InitialCoint{},
&model.TrashCategory{},
&model.TrashDetail{},
// ==main feature==
)
if err != nil {

59
dto/trash_dto.go Normal file
View File

@ -0,0 +1,59 @@
package dto
import "strings"
type RequestTrashCategoryDTO struct {
Name string `json:"name"`
}
type ResponseTrashCategoryDTO struct {
ID string `json:"id"`
Name string `json:"name"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Details []ResponseTrashDetailDTO `json:"details,omitempty"`
}
type ResponseTrashDetailDTO struct {
ID string `json:"id"`
CategoryID string `json:"category_id"`
Description string `json:"description"`
Price float64 `json:"price"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
type RequestTrashDetailDTO struct {
CategoryID string `json:"category_id"`
Description string `json:"description"`
Price float64 `json:"price"`
}
func (r *RequestTrashCategoryDTO) ValidateTrashCategoryInput() (map[string][]string, bool) {
errors := make(map[string][]string)
if strings.TrimSpace(r.Name) == "" {
errors["name"] = append(errors["name"], "name is required")
}
if len(errors) > 0 {
return errors, false
}
return nil, true
}
func (r *RequestTrashDetailDTO) ValidateTrashDetailInput() (map[string][]string, bool) {
errors := make(map[string][]string)
if strings.TrimSpace(r.Description) == "" {
errors["description"] = append(errors["description"], "description is required")
}
if r.Price <= 0 {
errors["price"] = append(errors["price"], "price must be greater than 0")
}
if len(errors) > 0 {
return errors, false
}
return nil, true
}

View File

@ -0,0 +1,128 @@
package handler
import (
"github.com/gofiber/fiber/v2"
"github.com/pahmiudahgede/senggoldong/dto"
"github.com/pahmiudahgede/senggoldong/internal/services"
"github.com/pahmiudahgede/senggoldong/utils"
)
type TrashHandler struct {
TrashService services.TrashService
}
func NewTrashHandler(trashService services.TrashService) *TrashHandler {
return &TrashHandler{TrashService: trashService}
}
func (h *TrashHandler) CreateCategory(c *fiber.Ctx) error {
var request dto.RequestTrashCategoryDTO
if err := c.BodyParser(&request); err != nil {
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
}
categoryResponse, err := h.TrashService.CreateCategory(request)
if err != nil {
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Failed to create category: "+err.Error())
}
return utils.CreateResponse(c, categoryResponse, "Category created successfully")
}
func (h *TrashHandler) AddDetailToCategory(c *fiber.Ctx) error {
var request dto.RequestTrashDetailDTO
if err := c.BodyParser(&request); err != nil {
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
}
detailResponse, err := h.TrashService.AddDetailToCategory(request)
if err != nil {
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Failed to add detail to category: "+err.Error())
}
return utils.CreateResponse(c, detailResponse, "Trash detail added successfully")
}
func (h *TrashHandler) GetCategories(c *fiber.Ctx) error {
categories, err := h.TrashService.GetCategories()
if err != nil {
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Failed to fetch categories: "+err.Error())
}
return utils.NonPaginatedResponse(c, categories, len(categories), "Categories retrieved successfully")
}
func (h *TrashHandler) GetCategoryByID(c *fiber.Ctx) error {
id := c.Params("category_id")
category, err := h.TrashService.GetCategoryByID(id)
if err != nil {
return utils.GenericResponse(c, fiber.StatusNotFound, "Category not found: "+err.Error())
}
return utils.SuccessResponse(c, category, "Category retrieved successfully")
}
func (h *TrashHandler) GetTrashDetailByID(c *fiber.Ctx) error {
id := c.Params("detail_id")
detail, err := h.TrashService.GetTrashDetailByID(id)
if err != nil {
return utils.GenericResponse(c, fiber.StatusNotFound, "Trash detail not found: "+err.Error())
}
return utils.SuccessResponse(c, detail, "Trash detail retrieved successfully")
}
func (h *TrashHandler) UpdateCategory(c *fiber.Ctx) error {
id := c.Params("category_id")
var request dto.RequestTrashCategoryDTO
if err := c.BodyParser(&request); err != nil {
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid request body"}})
}
updatedCategory, err := h.TrashService.UpdateCategory(id, request)
if err != nil {
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Error updating category: "+err.Error())
}
return utils.SuccessResponse(c, updatedCategory, "Category updated successfully")
}
func (h *TrashHandler) UpdateDetail(c *fiber.Ctx) error {
id := c.Params("detail_id")
var request dto.RequestTrashDetailDTO
if err := c.BodyParser(&request); err != nil {
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid request body"}})
}
updatedDetail, err := h.TrashService.UpdateDetail(id, request)
if err != nil {
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Error updating detail: "+err.Error())
}
return utils.SuccessResponse(c, updatedDetail, "Trash detail updated successfully")
}
func (h *TrashHandler) DeleteCategory(c *fiber.Ctx) error {
id := c.Params("category_id")
if err := h.TrashService.DeleteCategory(id); err != nil {
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Error deleting category: "+err.Error())
}
return utils.GenericResponse(c, fiber.StatusOK, "Category deleted successfully")
}
func (h *TrashHandler) DeleteDetail(c *fiber.Ctx) error {
id := c.Params("detail_id")
if err := h.TrashService.DeleteDetail(id); err != nil {
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Error deleting detail: "+err.Error())
}
return utils.GenericResponse(c, fiber.StatusOK, "Trash detail deleted successfully")
}

View File

@ -0,0 +1,95 @@
package repositories
import (
"fmt"
"github.com/pahmiudahgede/senggoldong/model"
"gorm.io/gorm"
)
type TrashRepository interface {
CreateCategory(category *model.TrashCategory) error
AddDetailToCategory(detail *model.TrashDetail) error
GetCategories() ([]model.TrashCategory, error)
GetCategoryByID(id string) (*model.TrashCategory, error)
GetTrashDetailByID(id string) (*model.TrashDetail, error)
UpdateCategoryName(id string, newName string) error
UpdateTrashDetail(id string, description string, price float64) error
DeleteCategory(id string) error
DeleteTrashDetail(id string) error
}
type trashRepository struct {
DB *gorm.DB
}
func NewTrashRepository(db *gorm.DB) TrashRepository {
return &trashRepository{DB: db}
}
func (r *trashRepository) CreateCategory(category *model.TrashCategory) error {
if err := r.DB.Create(category).Error; err != nil {
return fmt.Errorf("failed to create category: %v", err)
}
return nil
}
func (r *trashRepository) AddDetailToCategory(detail *model.TrashDetail) error {
if err := r.DB.Create(detail).Error; err != nil {
return fmt.Errorf("failed to add detail to category: %v", err)
}
return nil
}
func (r *trashRepository) GetCategories() ([]model.TrashCategory, error) {
var categories []model.TrashCategory
if err := r.DB.Preload("Details").Find(&categories).Error; err != nil {
return nil, fmt.Errorf("failed to fetch categories: %v", err)
}
return categories, nil
}
func (r *trashRepository) GetCategoryByID(id string) (*model.TrashCategory, error) {
var category model.TrashCategory
if err := r.DB.Preload("Details").First(&category, "id = ?", id).Error; err != nil {
return nil, fmt.Errorf("category not found: %v", err)
}
return &category, nil
}
func (r *trashRepository) GetTrashDetailByID(id string) (*model.TrashDetail, error) {
var detail model.TrashDetail
if err := r.DB.First(&detail, "id = ?", id).Error; err != nil {
return nil, fmt.Errorf("trash detail not found: %v", err)
}
return &detail, nil
}
func (r *trashRepository) UpdateCategoryName(id string, newName string) error {
if err := r.DB.Model(&model.TrashCategory{}).Where("id = ?", id).Update("name", newName).Error; err != nil {
return fmt.Errorf("failed to update category name: %v", err)
}
return nil
}
func (r *trashRepository) UpdateTrashDetail(id string, description string, price float64) error {
if err := r.DB.Model(&model.TrashDetail{}).Where("id = ?", id).Updates(model.TrashDetail{Description: description, Price: price}).Error; err != nil {
return fmt.Errorf("failed to update trash detail: %v", err)
}
return nil
}
func (r *trashRepository) DeleteCategory(id string) error {
if err := r.DB.Delete(&model.TrashCategory{}, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to delete category: %v", err)
}
return nil
}
func (r *trashRepository) DeleteTrashDetail(id string) error {
if err := r.DB.Delete(&model.TrashDetail{}, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to delete trash detail: %v", err)
}
return nil
}

View File

@ -0,0 +1,465 @@
package services
import (
"fmt"
"time"
"github.com/pahmiudahgede/senggoldong/dto"
"github.com/pahmiudahgede/senggoldong/internal/repositories"
"github.com/pahmiudahgede/senggoldong/model"
"github.com/pahmiudahgede/senggoldong/utils"
)
type TrashService interface {
CreateCategory(request dto.RequestTrashCategoryDTO) (*dto.ResponseTrashCategoryDTO, error)
AddDetailToCategory(request dto.RequestTrashDetailDTO) (*dto.ResponseTrashDetailDTO, error)
GetCategories() ([]dto.ResponseTrashCategoryDTO, error)
GetCategoryByID(id string) (*dto.ResponseTrashCategoryDTO, error)
GetTrashDetailByID(id string) (*dto.ResponseTrashDetailDTO, error)
UpdateCategory(id string, request dto.RequestTrashCategoryDTO) (*dto.ResponseTrashCategoryDTO, error)
UpdateDetail(id string, request dto.RequestTrashDetailDTO) (*dto.ResponseTrashDetailDTO, error)
DeleteCategory(id string) error
DeleteDetail(id string) error
}
type trashService struct {
TrashRepo repositories.TrashRepository
}
func NewTrashService(trashRepo repositories.TrashRepository) TrashService {
return &trashService{TrashRepo: trashRepo}
}
func (s *trashService) CreateCategory(request dto.RequestTrashCategoryDTO) (*dto.ResponseTrashCategoryDTO, error) {
errors, valid := request.ValidateTrashCategoryInput()
if !valid {
return nil, fmt.Errorf("validation error: %v", errors)
}
category := model.TrashCategory{
Name: request.Name,
}
if err := s.TrashRepo.CreateCategory(&category); err != nil {
return nil, fmt.Errorf("failed to create category: %v", err)
}
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
ID: category.ID,
Name: category.Name,
CreatedAt: category.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: category.UpdatedAt.Format("2006-01-02 15:04:05"),
}
if err := s.CacheCategoryAndDetails(category.ID, categoryResponseDTO, category.Details, time.Hour*6); err != nil {
fmt.Printf("Error caching category: %v\n", err)
}
categories, err := s.TrashRepo.GetCategories()
if err == nil {
var categoriesDTO []dto.ResponseTrashCategoryDTO
for _, c := range categories {
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
ID: c.ID,
Name: c.Name,
CreatedAt: c.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: c.UpdatedAt.Format("2006-01-02 15:04:05"),
})
}
if err := s.CacheCategoryList(categoriesDTO, time.Hour*6); err != nil {
fmt.Printf("Error caching all categories: %v\n", err)
}
}
return categoryResponseDTO, nil
}
func (s *trashService) AddDetailToCategory(request dto.RequestTrashDetailDTO) (*dto.ResponseTrashDetailDTO, error) {
errors, valid := request.ValidateTrashDetailInput()
if !valid {
return nil, fmt.Errorf("validation error: %v", errors)
}
detail := model.TrashDetail{
CategoryID: request.CategoryID,
Description: request.Description,
Price: request.Price,
}
if err := s.TrashRepo.AddDetailToCategory(&detail); err != nil {
return nil, fmt.Errorf("failed to add detail to category: %v", err)
}
detailResponseDTO := &dto.ResponseTrashDetailDTO{
ID: detail.ID,
CategoryID: detail.CategoryID,
Description: detail.Description,
Price: detail.Price,
CreatedAt: detail.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: detail.UpdatedAt.Format("2006-01-02 15:04:05"),
}
cacheKey := fmt.Sprintf("detail:%s", detail.ID)
cacheData := map[string]interface{}{
"data": detailResponseDTO,
}
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*6); err != nil {
fmt.Printf("Error caching detail: %v\n", err)
}
category, err := s.TrashRepo.GetCategoryByID(detail.CategoryID)
if err == nil {
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
ID: category.ID,
Name: category.Name,
CreatedAt: category.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: category.UpdatedAt.Format("2006-01-02 15:04:05"),
}
if err := s.CacheCategoryAndDetails(detail.CategoryID, categoryResponseDTO, category.Details, time.Hour*6); err != nil {
fmt.Printf("Error caching updated category: %v\n", err)
}
} else {
fmt.Printf("Error fetching category for cache update: %v\n", err)
}
return detailResponseDTO, nil
}
func (s *trashService) GetCategories() ([]dto.ResponseTrashCategoryDTO, error) {
cacheKey := "categories:all"
cachedCategories, err := utils.GetJSONData(cacheKey)
if err == nil && cachedCategories != nil {
var categoriesDTO []dto.ResponseTrashCategoryDTO
for _, category := range cachedCategories["data"].([]interface{}) {
categoryData := category.(map[string]interface{})
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
ID: categoryData["id"].(string),
Name: categoryData["name"].(string),
CreatedAt: categoryData["createdAt"].(string),
UpdatedAt: categoryData["updatedAt"].(string),
})
}
return categoriesDTO, nil
}
categories, err := s.TrashRepo.GetCategories()
if err != nil {
return nil, fmt.Errorf("failed to fetch categories: %v", err)
}
var categoriesDTO []dto.ResponseTrashCategoryDTO
for _, category := range categories {
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
ID: category.ID,
Name: category.Name,
CreatedAt: category.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: category.UpdatedAt.Format("2006-01-02 15:04:05"),
})
}
cacheData := map[string]interface{}{
"data": categoriesDTO,
}
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*6); err != nil {
fmt.Printf("Error caching categories: %v\n", err)
}
return categoriesDTO, nil
}
func (s *trashService) GetCategoryByID(id string) (*dto.ResponseTrashCategoryDTO, error) {
cacheKey := fmt.Sprintf("category:%s", id)
cachedCategory, err := utils.GetJSONData(cacheKey)
if err == nil && cachedCategory != nil {
categoryData := cachedCategory["data"].(map[string]interface{})
return &dto.ResponseTrashCategoryDTO{
ID: categoryData["id"].(string),
Name: categoryData["name"].(string),
CreatedAt: categoryData["createdAt"].(string),
UpdatedAt: categoryData["updatedAt"].(string),
Details: mapDetails(cachedCategory["details"]),
}, nil
}
category, err := s.TrashRepo.GetCategoryByID(id)
if err != nil {
return nil, fmt.Errorf("category not found: %v", err)
}
categoryDTO := &dto.ResponseTrashCategoryDTO{
ID: category.ID,
Name: category.Name,
CreatedAt: category.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: category.UpdatedAt.Format("2006-01-02 15:04:05"),
}
if category.Details != nil {
var detailsDTO []dto.ResponseTrashDetailDTO
for _, detail := range category.Details {
detailsDTO = append(detailsDTO, dto.ResponseTrashDetailDTO{
ID: detail.ID,
CategoryID: detail.CategoryID,
Description: detail.Description,
Price: detail.Price,
CreatedAt: detail.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: detail.UpdatedAt.Format("2006-01-02 15:04:05"),
})
}
categoryDTO.Details = detailsDTO
}
if err := s.CacheCategoryAndDetails(category.ID, categoryDTO, categoryDTO.Details, time.Hour*6); err != nil {
fmt.Printf("Error caching category and details: %v\n", err)
}
return categoryDTO, nil
}
func (s *trashService) GetTrashDetailByID(id string) (*dto.ResponseTrashDetailDTO, error) {
cacheKey := fmt.Sprintf("detail:%s", id)
cachedDetail, err := utils.GetJSONData(cacheKey)
if err == nil && cachedDetail != nil {
detailData := cachedDetail["data"].(map[string]interface{})
return &dto.ResponseTrashDetailDTO{
ID: detailData["id"].(string),
CategoryID: detailData["category_id"].(string),
Description: detailData["description"].(string),
Price: detailData["price"].(float64),
CreatedAt: detailData["createdAt"].(string),
UpdatedAt: detailData["updatedAt"].(string),
}, nil
}
detail, err := s.TrashRepo.GetTrashDetailByID(id)
if err != nil {
return nil, fmt.Errorf("trash detail not found: %v", err)
}
detailDTO := &dto.ResponseTrashDetailDTO{
ID: detail.ID,
CategoryID: detail.CategoryID,
Description: detail.Description,
Price: detail.Price,
CreatedAt: detail.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: detail.UpdatedAt.Format("2006-01-02 15:04:05"),
}
cacheData := map[string]interface{}{
"data": detailDTO,
}
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*24); err != nil {
fmt.Printf("Error caching detail: %v\n", err)
}
return detailDTO, nil
}
func (s *trashService) UpdateCategory(id string, request dto.RequestTrashCategoryDTO) (*dto.ResponseTrashCategoryDTO, error) {
errors, valid := request.ValidateTrashCategoryInput()
if !valid {
return nil, fmt.Errorf("validation error: %v", errors)
}
if err := s.TrashRepo.UpdateCategoryName(id, request.Name); err != nil {
return nil, fmt.Errorf("failed to update category: %v", err)
}
category, err := s.TrashRepo.GetCategoryByID(id)
if err != nil {
return nil, fmt.Errorf("category not found: %v", err)
}
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
ID: category.ID,
Name: category.Name,
CreatedAt: category.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: category.UpdatedAt.Format("2006-01-02 15:04:05"),
}
if err := s.CacheCategoryAndDetails(category.ID, categoryResponseDTO, category.Details, time.Hour*6); err != nil {
fmt.Printf("Error caching updated category: %v\n", err)
}
allCategories, err := s.TrashRepo.GetCategories()
if err == nil {
var categoriesDTO []dto.ResponseTrashCategoryDTO
for _, c := range allCategories {
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
ID: c.ID,
Name: c.Name,
CreatedAt: c.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: c.UpdatedAt.Format("2006-01-02 15:04:05"),
})
}
if err := s.CacheCategoryList(categoriesDTO, time.Hour*6); err != nil {
fmt.Printf("Error caching all categories: %v\n", err)
}
}
return categoryResponseDTO, nil
}
func (s *trashService) UpdateDetail(id string, request dto.RequestTrashDetailDTO) (*dto.ResponseTrashDetailDTO, error) {
errors, valid := request.ValidateTrashDetailInput()
if !valid {
return nil, fmt.Errorf("validation error: %v", errors)
}
if err := s.TrashRepo.UpdateTrashDetail(id, request.Description, request.Price); err != nil {
return nil, fmt.Errorf("failed to update detail: %v", err)
}
detail, err := s.TrashRepo.GetTrashDetailByID(id)
if err != nil {
return nil, fmt.Errorf("trash detail not found: %v", err)
}
detailResponseDTO := &dto.ResponseTrashDetailDTO{
ID: detail.ID,
CategoryID: detail.CategoryID,
Description: detail.Description,
Price: detail.Price,
CreatedAt: detail.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: detail.UpdatedAt.Format("2006-01-02 15:04:05"),
}
cacheKey := fmt.Sprintf("detail:%s", detail.ID)
cacheData := map[string]interface{}{
"data": detailResponseDTO,
}
if err := utils.SetJSONData(cacheKey, cacheData, time.Hour*6); err != nil {
fmt.Printf("Error caching updated detail: %v\n", err)
}
category, err := s.TrashRepo.GetCategoryByID(detail.CategoryID)
if err == nil {
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
ID: category.ID,
Name: category.Name,
CreatedAt: category.CreatedAt.Format("2006-01-02 15:04:05"),
UpdatedAt: category.UpdatedAt.Format("2006-01-02 15:04:05"),
}
if err := s.CacheCategoryAndDetails(detail.CategoryID, categoryResponseDTO, category.Details, time.Hour*6); err != nil {
fmt.Printf("Error caching updated category: %v\n", err)
}
} else {
fmt.Printf("Error fetching category for cache update: %v\n", err)
}
return detailResponseDTO, nil
}
func (s *trashService) DeleteCategory(id string) error {
if err := s.TrashRepo.DeleteCategory(id); err != nil {
return fmt.Errorf("failed to delete category: %v", err)
}
cacheKey := fmt.Sprintf("category:%s", id)
if err := utils.DeleteData(cacheKey); err != nil {
fmt.Printf("Error clearing cache for deleted category: %v\n", err)
}
allCategoriesCacheKey := "categories:all"
if err := utils.DeleteData(allCategoriesCacheKey); err != nil {
fmt.Printf("Error clearing categories list cache: %v\n", err)
}
category, err := s.TrashRepo.GetCategoryByID(id)
if err != nil {
return fmt.Errorf("category not found after deletion: %v", err)
}
if category.Details != nil {
for _, detail := range category.Details {
detailCacheKey := fmt.Sprintf("detail:%s", detail.ID)
if err := utils.DeleteData(detailCacheKey); err != nil {
fmt.Printf("Error clearing cache for deleted detail: %v\n", err)
}
}
}
return nil
}
func (s *trashService) DeleteDetail(id string) error {
detail, err := s.TrashRepo.GetTrashDetailByID(id)
if err != nil {
return fmt.Errorf("trash detail not found: %v", err)
}
if err := s.TrashRepo.DeleteTrashDetail(id); err != nil {
return fmt.Errorf("failed to delete detail: %v", err)
}
cacheKey := fmt.Sprintf("detail:%s", id)
if err := utils.DeleteData(cacheKey); err != nil {
fmt.Printf("Error clearing cache for deleted detail: %v\n", err)
}
categoryCacheKey := fmt.Sprintf("category:%s", detail.CategoryID)
if err := utils.DeleteData(categoryCacheKey); err != nil {
fmt.Printf("Error clearing cache for category after detail deletion: %v\n", err)
}
return nil
}
func mapDetails(details interface{}) []dto.ResponseTrashDetailDTO {
var detailsDTO []dto.ResponseTrashDetailDTO
if details != nil {
for _, detail := range details.([]interface{}) {
detailData := detail.(map[string]interface{})
detailsDTO = append(detailsDTO, dto.ResponseTrashDetailDTO{
ID: detailData["id"].(string),
CategoryID: detailData["category_id"].(string),
Description: detailData["description"].(string),
Price: detailData["price"].(float64),
CreatedAt: detailData["createdAt"].(string),
UpdatedAt: detailData["updatedAt"].(string),
})
}
}
return detailsDTO
}
func (s *trashService) CacheCategoryAndDetails(categoryID string, categoryData interface{}, detailsData interface{}, expiration time.Duration) error {
cacheKey := fmt.Sprintf("category:%s", categoryID)
cacheData := map[string]interface{}{
"data": categoryData,
"details": detailsData,
}
err := utils.SetJSONData(cacheKey, cacheData, expiration)
if err != nil {
return fmt.Errorf("error caching category and details: %v", err)
}
return nil
}
func (s *trashService) CacheCategoryList(categoriesData interface{}, expiration time.Duration) error {
cacheKey := "categories:all"
cacheData := map[string]interface{}{
"data": categoriesData,
}
err := utils.SetJSONData(cacheKey, cacheData, expiration)
if err != nil {
return fmt.Errorf("error caching categories list: %v", err)
}
return nil
}

20
model/trash_model.go Normal file
View File

@ -0,0 +1,20 @@
package model
import "time"
type TrashCategory struct {
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
Name string `gorm:"not null" json:"name"`
Details []TrashDetail `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE;" json:"details"`
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
}
type TrashDetail struct {
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
CategoryID string `gorm:"type:uuid;not null" json:"category_id"`
Description string `gorm:"not null" json:"description"`
Price float64 `gorm:"not null" json:"price"`
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
}

View File

@ -0,0 +1,32 @@
package presentation
import (
"github.com/gofiber/fiber/v2"
"github.com/pahmiudahgede/senggoldong/config"
"github.com/pahmiudahgede/senggoldong/internal/handler"
"github.com/pahmiudahgede/senggoldong/internal/repositories"
"github.com/pahmiudahgede/senggoldong/internal/services"
"github.com/pahmiudahgede/senggoldong/middleware"
"github.com/pahmiudahgede/senggoldong/utils"
)
func TrashRouter(api fiber.Router) {
trashRepo := repositories.NewTrashRepository(config.DB)
trashService := services.NewTrashService(trashRepo)
trashHandler := handler.NewTrashHandler(trashService)
trashAPI := api.Group("/trash")
trashAPI.Post("/createcategory-with-details", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.CreateCategory)
trashAPI.Post("/add-detailinexistingcategory", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.AddDetailToCategory)
trashAPI.Get("/allcategory", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), trashHandler.GetCategories)
trashAPI.Get("/category/:category_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), trashHandler.GetCategoryByID)
trashAPI.Get("/detail/:detail_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), trashHandler.GetTrashDetailByID)
trashAPI.Patch("/update-category/:category_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.UpdateCategory)
trashAPI.Put("/update-detail/:detail_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.UpdateDetail)
trashAPI.Delete("delete-category/:category_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.DeleteCategory)
trashAPI.Delete("delete-detail/:detail_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.DeleteDetail)
}

View File

@ -7,7 +7,7 @@ import (
)
func SetupRoutes(app *fiber.App) {
api := app.Group("/apirijikid")
api := app.Group("/apirijikid/v2")
api.Use(middleware.APIKeyMiddleware)
presentation.AuthRouter(api)
@ -19,4 +19,5 @@ func SetupRoutes(app *fiber.App) {
presentation.ArticleRouter(api)
presentation.BannerRouter(api)
presentation.InitialCointRoute(api)
presentation.TrashRouter(api)
}