feat: add feature post and get ctegory category detail for trash domain
This commit is contained in:
parent
8945080477
commit
22b61ce44e
|
@ -58,6 +58,8 @@ func InitDatabase() {
|
||||||
&domain.PlatformHandle{},
|
&domain.PlatformHandle{},
|
||||||
&domain.Address{},
|
&domain.Address{},
|
||||||
&domain.Article{},
|
&domain.Article{},
|
||||||
|
&domain.TrashCategory{},
|
||||||
|
&domain.TrashDetail{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error: Failed to auto migrate domain:", err)
|
log.Fatal("Error: Failed to auto migrate domain:", err)
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package domain
|
||||||
|
|
||||||
|
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" 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 int `gorm:"not null" json:"price"`
|
||||||
|
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||||
|
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||||
|
}
|
|
@ -91,7 +91,3 @@ func (c *ArticleUpdateRequest) ValidateUpdateArticle() error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (ar *ArticleRequest) Validate() error {
|
|
||||||
// return validate.Struct(ar)
|
|
||||||
// }
|
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package dto
|
||||||
|
|
||||||
|
import "github.com/go-playground/validator/v10"
|
||||||
|
|
||||||
|
type TrashCategoryDTO struct {
|
||||||
|
Name string `json:"name" validate:"required,min=3,max=100"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TrashCategoryDTO) Validate() error {
|
||||||
|
validate := validator.New()
|
||||||
|
return validate.Struct(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
type TrashDetailDTO struct {
|
||||||
|
CategoryID string `json:"category_id" validate:"required,uuid4"`
|
||||||
|
Description string `json:"description" validate:"required,min=3,max=255"`
|
||||||
|
Price int `json:"price" validate:"required,min=0"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TrashDetailDTO) Validate() error {
|
||||||
|
validate := validator.New()
|
||||||
|
return validate.Struct(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
type TrashCategoryResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
CreatedAt string `json:"createdAt"`
|
||||||
|
UpdatedAt string `json:"updatedAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTrashCategoryResponse(id, name, createdAt, updatedAt string) TrashCategoryResponse {
|
||||||
|
return TrashCategoryResponse{
|
||||||
|
ID: id,
|
||||||
|
Name: name,
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type TrashDetailResponse struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Price int `json:"price"`
|
||||||
|
CreatedAt string `json:"createdAt"`
|
||||||
|
UpdatedAt string `json:"updatedAt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTrashDetailResponse(id, description string, price int, createdAt, updatedAt string) TrashDetailResponse {
|
||||||
|
return TrashDetailResponse{
|
||||||
|
ID: id,
|
||||||
|
Description: description,
|
||||||
|
Price: price,
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,4 +38,10 @@ func AppRouter(app *fiber.App) {
|
||||||
app.Get("/articles/:id", middleware.AuthMiddleware, controllers.GetArticleByID)
|
app.Get("/articles/:id", middleware.AuthMiddleware, controllers.GetArticleByID)
|
||||||
app.Put("/articles/:id", middleware.AuthMiddleware, controllers.UpdateArticle)
|
app.Put("/articles/:id", middleware.AuthMiddleware, controllers.UpdateArticle)
|
||||||
app.Delete("/articles/:id", middleware.AuthMiddleware, controllers.DeleteArticle)
|
app.Delete("/articles/:id", middleware.AuthMiddleware, controllers.DeleteArticle)
|
||||||
|
|
||||||
|
// # trash type
|
||||||
|
app.Get("/trash-category", controllers.GetTrashCategories)
|
||||||
|
app.Get("/trash-categorydetail/:id", controllers.GetTrashCategoryDetail)
|
||||||
|
app.Post("/addtrash-category", controllers.CreateTrashCategory)
|
||||||
|
app.Post("/addtrash-categorydetail", controllers.CreateTrashDetail)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/dto"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/internal/services"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTrashCategories(c *fiber.Ctx) error {
|
||||||
|
trashCategories, err := services.GetTrashCategories()
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusInternalServerError,
|
||||||
|
"Failed to fetch trash categories",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []dto.TrashCategoryResponse
|
||||||
|
for _, category := range trashCategories {
|
||||||
|
|
||||||
|
response = append(response, dto.NewTrashCategoryResponse(
|
||||||
|
category.ID,
|
||||||
|
category.Name,
|
||||||
|
utils.FormatDateToIndonesianFormat(category.CreatedAt),
|
||||||
|
utils.FormatDateToIndonesianFormat(category.UpdatedAt),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusOK,
|
||||||
|
"Trash categories fetched successfully",
|
||||||
|
response,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTrashCategoryDetail(c *fiber.Ctx) error {
|
||||||
|
id := c.Params("id")
|
||||||
|
|
||||||
|
trashCategoryDetail, err := services.GetTrashCategoryDetail(id)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusInternalServerError,
|
||||||
|
"Failed to fetch trash category detail",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
detailResponse := dto.NewTrashCategoryResponse(
|
||||||
|
trashCategoryDetail.ID,
|
||||||
|
trashCategoryDetail.Name,
|
||||||
|
utils.FormatDateToIndonesianFormat(trashCategoryDetail.CreatedAt),
|
||||||
|
utils.FormatDateToIndonesianFormat(trashCategoryDetail.UpdatedAt),
|
||||||
|
)
|
||||||
|
|
||||||
|
var detailResponseList []dto.TrashDetailResponse
|
||||||
|
if trashCategoryDetail.Details != nil {
|
||||||
|
for _, detail := range trashCategoryDetail.Details {
|
||||||
|
detailResponseList = append(detailResponseList, dto.NewTrashDetailResponse(
|
||||||
|
detail.ID,
|
||||||
|
detail.Description,
|
||||||
|
detail.Price,
|
||||||
|
utils.FormatDateToIndonesianFormat(detail.CreatedAt),
|
||||||
|
utils.FormatDateToIndonesianFormat(detail.UpdatedAt),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusOK,
|
||||||
|
"Trash category detail fetched successfully",
|
||||||
|
struct {
|
||||||
|
Category dto.TrashCategoryResponse `json:"category"`
|
||||||
|
Details []dto.TrashDetailResponse `json:"details,omitempty"`
|
||||||
|
}{
|
||||||
|
Category: detailResponse,
|
||||||
|
Details: detailResponseList,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateTrashCategory(c *fiber.Ctx) error {
|
||||||
|
var categoryInput dto.TrashCategoryDTO
|
||||||
|
|
||||||
|
if err := c.BodyParser(&categoryInput); err != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusBadRequest,
|
||||||
|
"Invalid input data",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := categoryInput.Validate(); err != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusBadRequest,
|
||||||
|
"Validation failed: "+err.Error(),
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
newCategory, err := services.CreateTrashCategory(categoryInput.Name)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusInternalServerError,
|
||||||
|
"Failed to create trash category",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
categoryResponse := map[string]interface{}{
|
||||||
|
"id": newCategory.ID,
|
||||||
|
"name": newCategory.Name,
|
||||||
|
"createdAt": newCategory.CreatedAt,
|
||||||
|
"updatedAt": newCategory.UpdatedAt,
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusCreated).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusCreated,
|
||||||
|
"Trash category created successfully",
|
||||||
|
categoryResponse,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateTrashDetail(c *fiber.Ctx) error {
|
||||||
|
var detailInput dto.TrashDetailDTO
|
||||||
|
|
||||||
|
if err := c.BodyParser(&detailInput); err != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusBadRequest,
|
||||||
|
"Invalid input data",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := detailInput.Validate(); err != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusBadRequest,
|
||||||
|
"Validation failed: "+err.Error(),
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
newDetail, err := services.CreateTrashDetail(detailInput.CategoryID, detailInput.Description, detailInput.Price)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusInternalServerError,
|
||||||
|
"Failed to create trash detail",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
detailResponse := map[string]interface{}{
|
||||||
|
"id": newDetail.ID,
|
||||||
|
"description": newDetail.Description,
|
||||||
|
"price": newDetail.Price,
|
||||||
|
"createdAt": newDetail.CreatedAt,
|
||||||
|
"updatedAt": newDetail.UpdatedAt,
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusCreated).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusCreated,
|
||||||
|
"Trash detail created successfully",
|
||||||
|
detailResponse,
|
||||||
|
))
|
||||||
|
}
|
|
@ -46,12 +46,10 @@ func CreatePin(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
formattedCreatedAt := utils.FormatDateToIndonesianFormat(pin.CreatedAt)
|
formattedCreatedAt := utils.FormatDateToIndonesianFormat(pin.CreatedAt)
|
||||||
// formattedUpdatedAt := utils.FormatDateToIndonesianFormat(pin.UpdatedAt)
|
|
||||||
|
|
||||||
pinResponse := dto.PinResponse{
|
pinResponse := dto.PinResponse{
|
||||||
// ID: pin.ID,
|
|
||||||
CreatedAt: formattedCreatedAt,
|
CreatedAt: formattedCreatedAt,
|
||||||
// UpdatedAt: formattedUpdatedAt,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
return c.Status(fiber.StatusOK).JSON(utils.FormatResponse(
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package repositories
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pahmiudahgede/senggoldong/config"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/domain"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTrashCategories() ([]domain.TrashCategory, error) {
|
||||||
|
var categories []domain.TrashCategory
|
||||||
|
|
||||||
|
if err := config.DB.Find(&categories).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return categories, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTrashCategoryDetail(id string) (domain.TrashCategory, error) {
|
||||||
|
var category domain.TrashCategory
|
||||||
|
if err := config.DB.Preload("Details").Where("id = ?", id).First(&category).Error; err != nil {
|
||||||
|
return category, err
|
||||||
|
}
|
||||||
|
return category, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateTrashCategory(category *domain.TrashCategory) error {
|
||||||
|
if err := config.DB.Create(category).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateTrashDetail(detail *domain.TrashDetail) error {
|
||||||
|
if err := config.DB.Create(detail).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pahmiudahgede/senggoldong/domain"
|
||||||
|
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTrashCategories() ([]domain.TrashCategory, error) {
|
||||||
|
|
||||||
|
return repositories.GetTrashCategories()
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTrashCategoryDetail(id string) (domain.TrashCategory, error) {
|
||||||
|
return repositories.GetTrashCategoryDetail(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateTrashCategory(name string) (domain.TrashCategory, error) {
|
||||||
|
category := domain.TrashCategory{Name: name}
|
||||||
|
|
||||||
|
err := repositories.CreateTrashCategory(&category)
|
||||||
|
if err != nil {
|
||||||
|
return category, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return category, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateTrashDetail(categoryID, description string, price int) (domain.TrashDetail, error) {
|
||||||
|
detail := domain.TrashDetail{
|
||||||
|
CategoryID: categoryID,
|
||||||
|
Description: description,
|
||||||
|
Price: price,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := repositories.CreateTrashDetail(&detail)
|
||||||
|
if err != nil {
|
||||||
|
return detail, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return detail, nil
|
||||||
|
}
|
Loading…
Reference in New Issue