feat: update new modules
This commit is contained in:
parent
b3c5a0228f
commit
3c4465f900
|
|
@ -2,24 +2,16 @@ stages:
|
|||
- build-image
|
||||
- deploy
|
||||
|
||||
#build-1:
|
||||
# stage: build-app
|
||||
# image: golang:alpine
|
||||
# script:
|
||||
# - go build -o main .
|
||||
# artifacts:
|
||||
# paths:
|
||||
# - main
|
||||
|
||||
build-2:
|
||||
build:
|
||||
stage: build-image
|
||||
image: docker/compose:latest
|
||||
image:
|
||||
name: docker:25.0.3-cli
|
||||
services:
|
||||
- name: docker:dind
|
||||
- name: docker:25.0.3-dind
|
||||
command: [ "--insecure-registry=103.82.242.92:8900" ]
|
||||
script:
|
||||
- docker login -u $DEPLOY_USERNAME -p $DEPLOY_TOKEN 103.82.242.92:8900
|
||||
- docker-compose build
|
||||
- docker compose build
|
||||
- docker tag registry.gitlab.com/hanifsalafi/jaecoo-be:dev 103.82.242.92:8900/medols/jaecoo-be:dev
|
||||
- docker push 103.82.242.92:8900/medols/jaecoo-be:dev
|
||||
|
||||
|
|
@ -30,4 +22,4 @@ deploy:
|
|||
services:
|
||||
- docker:dind
|
||||
script:
|
||||
- curl --user $JENKINS_USER:$JENKINS_PWD http://38.47.180.165:8080/job/autodeploy-campaignpool-be/build?token=autodeploycampaignpool
|
||||
- curl --user $JENKINS_USER:$JENKINS_PWD http://38.47.180.165:8080/job/autodeploy-jaecoo-be/build?token=autodeployjaecoo
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Banners struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
||||
Title string `json:"title" gorm:"type:varchar"`
|
||||
Description *string `json:"description" gorm:"type:text"`
|
||||
ThumbnailPath *string `json:"thumbnail_path" gorm:"type:varchar"`
|
||||
Position *string `json:"position" gorm:"type:varchar"`
|
||||
Status *string `json:"status" gorm:"type:varchar"`
|
||||
IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Galleries struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
||||
Title string `json:"title" gorm:"type:varchar"`
|
||||
Description *string `json:"description" gorm:"type:text"`
|
||||
ThumbnailPath *string `json:"thumbnail_path" gorm:"type:varchar"`
|
||||
IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type GalleryFiles struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
||||
GalleryID uint `json:"gallery_id" gorm:"type:int4"`
|
||||
Title *string `json:"title" gorm:"type:varchar"`
|
||||
ImagePath *string `json:"image_path" gorm:"type:varchar"`
|
||||
IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type ProductSpecifications struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
||||
ProductID uint `json:"product_id" gorm:"type:int4"`
|
||||
Title string `json:"title" gorm:"type:varchar"`
|
||||
ThumbnailPath *string `json:"thumbnail_path" gorm:"type:varchar"`
|
||||
IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Products struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
||||
Title string `json:"title" gorm:"type:varchar"`
|
||||
Variant *string `json:"variant" gorm:"type:varchar"`
|
||||
Price *float64 `json:"price" gorm:"type:decimal(10,2)"`
|
||||
ThumbnailPath *string `json:"thumbnail_path" gorm:"type:varchar"`
|
||||
Colors *string `json:"colors" gorm:"type:text"` // JSON array stored as text
|
||||
IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Promotions struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
||||
Title string `json:"title" gorm:"type:varchar"`
|
||||
Description *string `json:"description" gorm:"type:text"`
|
||||
ThumbnailPath *string `json:"thumbnail_path" gorm:"type:varchar"`
|
||||
IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type SalesAgents struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
||||
Name string `json:"name" gorm:"type:varchar"`
|
||||
JobTitle *string `json:"job_title" gorm:"type:varchar"`
|
||||
Phone *string `json:"phone" gorm:"type:varchar"`
|
||||
AgentType *string `json:"agent_type" gorm:"type:text"` // JSON array stored as text
|
||||
ProfilePicturePath *string `json:"profile_picture_path" gorm:"type:varchar"`
|
||||
IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||
}
|
||||
|
|
@ -94,15 +94,22 @@ func Models() []interface{} {
|
|||
entity.ArticleFiles{},
|
||||
entity.ArticleComments{},
|
||||
entity.AuditTrails{},
|
||||
entity.Banners{},
|
||||
entity.Cities{},
|
||||
entity.CsrfTokenRecords{},
|
||||
entity.CustomStaticPages{},
|
||||
entity.Districts{},
|
||||
entity.Feedbacks{},
|
||||
entity.ForgotPasswords{},
|
||||
entity.Galleries{},
|
||||
entity.GalleryFiles{},
|
||||
entity.MasterApprovalStatuses{},
|
||||
entity.ProductSpecifications{},
|
||||
entity.Products{},
|
||||
entity.Promotions{},
|
||||
entity.Provinces{},
|
||||
entity.OneTimePasswords{},
|
||||
entity.SalesAgents{},
|
||||
user_levels.UserLevels{},
|
||||
entity.UserRoles{},
|
||||
entity.UserRoleAccesses{},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
package banners
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/banners/controller"
|
||||
"jaecoo-be/app/module/banners/repository"
|
||||
"jaecoo-be/app/module/banners/service"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
// BannersRouter struct of BannersRouter
|
||||
type BannersRouter struct {
|
||||
App fiber.Router
|
||||
Controller *controller.Controller
|
||||
}
|
||||
|
||||
// NewBannersModule register bulky of Banners module
|
||||
var NewBannersModule = fx.Options(
|
||||
// register repository of Banners module
|
||||
fx.Provide(repository.NewBannersRepository),
|
||||
|
||||
// register service of Banners module
|
||||
fx.Provide(service.NewBannersService),
|
||||
|
||||
// register controller of Banners module
|
||||
fx.Provide(controller.NewController),
|
||||
|
||||
// register router of Banners module
|
||||
fx.Provide(NewBannersRouter),
|
||||
)
|
||||
|
||||
// NewBannersRouter init BannersRouter
|
||||
func NewBannersRouter(fiber *fiber.App, controller *controller.Controller) *BannersRouter {
|
||||
return &BannersRouter{
|
||||
App: fiber,
|
||||
Controller: controller,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterBannersRoutes register routes of Banners module
|
||||
func (_i *BannersRouter) RegisterBannersRoutes() {
|
||||
// define controllers
|
||||
bannersController := _i.Controller.Banners
|
||||
|
||||
// define routes
|
||||
_i.App.Route("/banners", func(router fiber.Router) {
|
||||
router.Get("/", bannersController.All)
|
||||
router.Get("/:id", bannersController.Show)
|
||||
router.Post("/", bannersController.Save)
|
||||
router.Put("/:id", bannersController.Update)
|
||||
router.Delete("/:id", bannersController.Delete)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/banners/request"
|
||||
"jaecoo-be/app/module/banners/service"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
utilRes "jaecoo-be/utils/response"
|
||||
utilVal "jaecoo-be/utils/validator"
|
||||
)
|
||||
|
||||
type bannersController struct {
|
||||
bannersService service.BannersService
|
||||
}
|
||||
|
||||
type BannersController interface {
|
||||
All(c *fiber.Ctx) error
|
||||
Show(c *fiber.Ctx) error
|
||||
Save(c *fiber.Ctx) error
|
||||
Update(c *fiber.Ctx) error
|
||||
Delete(c *fiber.Ctx) error
|
||||
}
|
||||
|
||||
func NewBannersController(bannersService service.BannersService) BannersController {
|
||||
return &bannersController{
|
||||
bannersService: bannersService,
|
||||
}
|
||||
}
|
||||
|
||||
// All Banners
|
||||
// @Summary Get all Banners
|
||||
// @Description API for getting all Banners
|
||||
// @Tags Banners
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param req query request.BannersQueryRequestContext false "query parameters"
|
||||
// @Param req query paginator.Pagination false "pagination parameters"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /banners [get]
|
||||
func (_i *bannersController) All(c *fiber.Ctx) error {
|
||||
paginate, err := paginator.Paginate(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reqContext := request.BannersQueryRequestContext{
|
||||
Title: c.Query("title"),
|
||||
Position: c.Query("position"),
|
||||
Status: c.Query("status"),
|
||||
}
|
||||
req := reqContext.ToParamRequest()
|
||||
req.Pagination = paginate
|
||||
|
||||
bannersData, paging, err := _i.bannersService.GetAll(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Banners list successfully retrieved"},
|
||||
Data: bannersData,
|
||||
Meta: paging,
|
||||
})
|
||||
}
|
||||
|
||||
// Show Banner
|
||||
// @Summary Get Banner by ID
|
||||
// @Description API for getting Banner by ID
|
||||
// @Tags Banners
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Banner ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /banners/{id} [get]
|
||||
func (_i *bannersController) Show(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bannerData, err := _i.bannersService.GetOne(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Banner successfully retrieved"},
|
||||
Data: bannerData,
|
||||
})
|
||||
}
|
||||
|
||||
// Save Banner
|
||||
// @Summary Create Banner
|
||||
// @Description API for creating Banner
|
||||
// @Tags Banners
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param payload body request.BannersCreateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /banners [post]
|
||||
func (_i *bannersController) Save(c *fiber.Ctx) error {
|
||||
req := new(request.BannersCreateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.bannersService.Create(*req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Banner successfully created"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Update Banner
|
||||
// @Summary Update Banner
|
||||
// @Description API for updating Banner
|
||||
// @Tags Banners
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Banner ID"
|
||||
// @Param payload body request.BannersUpdateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /banners/{id} [put]
|
||||
func (_i *bannersController) Update(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := new(request.BannersUpdateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.bannersService.Update(uint(id), *req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Banner successfully updated"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Delete Banner
|
||||
// @Summary Delete Banner
|
||||
// @Description API for deleting Banner (soft delete)
|
||||
// @Tags Banners
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Banner ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /banners/{id} [delete]
|
||||
func (_i *bannersController) Delete(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = _i.bannersService.Delete(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Banner successfully deleted"},
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package controller
|
||||
|
||||
import "jaecoo-be/app/module/banners/service"
|
||||
|
||||
type Controller struct {
|
||||
Banners BannersController
|
||||
}
|
||||
|
||||
func NewController(BannersService service.BannersService) *Controller {
|
||||
return &Controller{
|
||||
Banners: NewBannersController(BannersService),
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package mapper
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database/entity"
|
||||
res "jaecoo-be/app/module/banners/response"
|
||||
)
|
||||
|
||||
func BannersResponseMapper(banner *entity.Banners, host string) *res.BannersResponse {
|
||||
if banner == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
response := &res.BannersResponse{
|
||||
ID: banner.ID,
|
||||
Title: banner.Title,
|
||||
Description: banner.Description,
|
||||
ThumbnailPath: banner.ThumbnailPath,
|
||||
Position: banner.Position,
|
||||
Status: banner.Status,
|
||||
IsActive: banner.IsActive,
|
||||
CreatedAt: banner.CreatedAt,
|
||||
UpdatedAt: banner.UpdatedAt,
|
||||
}
|
||||
|
||||
if banner.ThumbnailPath != nil && *banner.ThumbnailPath != "" {
|
||||
thumbnailUrl := host + "/banners/thumbnail/viewer/" + *banner.ThumbnailPath
|
||||
response.ThumbnailUrl = &thumbnailUrl
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database"
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/app/module/banners/request"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type bannersRepository struct {
|
||||
DB *database.Database
|
||||
Log zerolog.Logger
|
||||
}
|
||||
|
||||
type BannersRepository interface {
|
||||
GetAll(req request.BannersQueryRequest) (banners []*entity.Banners, paging paginator.Pagination, err error)
|
||||
FindOne(id uint) (banner *entity.Banners, err error)
|
||||
Create(banner *entity.Banners) (bannerReturn *entity.Banners, err error)
|
||||
Update(id uint, banner *entity.Banners) (err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewBannersRepository(db *database.Database, log zerolog.Logger) BannersRepository {
|
||||
return &bannersRepository{
|
||||
DB: db,
|
||||
Log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *bannersRepository) GetAll(req request.BannersQueryRequest) (banners []*entity.Banners, paging paginator.Pagination, err error) {
|
||||
var count int64
|
||||
|
||||
query := _i.DB.DB.Model(&entity.Banners{})
|
||||
|
||||
if req.Title != nil && *req.Title != "" {
|
||||
title := strings.ToLower(*req.Title)
|
||||
query = query.Where("LOWER(title) LIKE ?", "%"+title+"%")
|
||||
}
|
||||
|
||||
if req.Position != nil && *req.Position != "" {
|
||||
query = query.Where("position = ?", *req.Position)
|
||||
}
|
||||
|
||||
if req.Status != nil && *req.Status != "" {
|
||||
query = query.Where("status = ?", *req.Status)
|
||||
}
|
||||
|
||||
query = query.Where("is_active = ?", true)
|
||||
|
||||
query.Count(&count)
|
||||
|
||||
req.Pagination.Count = count
|
||||
req.Pagination = paginator.Paging(req.Pagination)
|
||||
|
||||
query = query.Order("created_at DESC")
|
||||
|
||||
err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&banners).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
paging = *req.Pagination
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *bannersRepository) FindOne(id uint) (banner *entity.Banners, err error) {
|
||||
banner = &entity.Banners{}
|
||||
err = _i.DB.DB.Where("id = ? AND is_active = ?", id, true).First(banner).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *bannersRepository) Create(banner *entity.Banners) (bannerReturn *entity.Banners, err error) {
|
||||
if err = _i.DB.DB.Create(banner).Error; err != nil {
|
||||
return
|
||||
}
|
||||
bannerReturn = banner
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *bannersRepository) Update(id uint, banner *entity.Banners) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.Banners{}).Where("id = ?", id).Updates(banner).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *bannersRepository) Delete(id uint) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.Banners{}).Where("id = ?", id).Update("is_active", false).Error
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package request
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/utils/paginator"
|
||||
)
|
||||
|
||||
type BannersQueryRequest struct {
|
||||
Title *string `json:"title"`
|
||||
Position *string `json:"position"`
|
||||
Status *string `json:"status"`
|
||||
Pagination *paginator.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
type BannersQueryRequestContext struct {
|
||||
Title string `json:"title"`
|
||||
Position string `json:"position"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
func (req BannersQueryRequestContext) ToParamRequest() BannersQueryRequest {
|
||||
var request BannersQueryRequest
|
||||
|
||||
if title := req.Title; title != "" {
|
||||
request.Title = &title
|
||||
}
|
||||
if position := req.Position; position != "" {
|
||||
request.Position = &position
|
||||
}
|
||||
if status := req.Status; status != "" {
|
||||
request.Status = &status
|
||||
}
|
||||
|
||||
return request
|
||||
}
|
||||
|
||||
type BannersCreateRequest struct {
|
||||
Title string `json:"title" validate:"required"`
|
||||
Description *string `json:"description"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
Position *string `json:"position"`
|
||||
Status *string `json:"status"`
|
||||
}
|
||||
|
||||
func (req BannersCreateRequest) ToEntity() *entity.Banners {
|
||||
return &entity.Banners{
|
||||
Title: req.Title,
|
||||
Description: req.Description,
|
||||
ThumbnailPath: req.ThumbnailPath,
|
||||
Position: req.Position,
|
||||
Status: req.Status,
|
||||
}
|
||||
}
|
||||
|
||||
type BannersUpdateRequest struct {
|
||||
Title *string `json:"title"`
|
||||
Description *string `json:"description"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
Position *string `json:"position"`
|
||||
Status *string `json:"status"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
}
|
||||
|
||||
func (req BannersUpdateRequest) ToEntity() *entity.Banners {
|
||||
return &entity.Banners{
|
||||
Title: getStringValue(req.Title),
|
||||
Description: req.Description,
|
||||
ThumbnailPath: req.ThumbnailPath,
|
||||
Position: req.Position,
|
||||
Status: req.Status,
|
||||
IsActive: req.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
func getStringValue(s *string) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
return *s
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package response
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type BannersResponse struct {
|
||||
ID uint `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description *string `json:"description"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
ThumbnailUrl *string `json:"thumbnail_url"`
|
||||
Position *string `json:"position"`
|
||||
Status *string `json:"status"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"jaecoo-be/app/module/banners/mapper"
|
||||
"jaecoo-be/app/module/banners/repository"
|
||||
"jaecoo-be/app/module/banners/request"
|
||||
"jaecoo-be/app/module/banners/response"
|
||||
"jaecoo-be/config/config"
|
||||
"jaecoo-be/utils/paginator"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type bannersService struct {
|
||||
Repo repository.BannersRepository
|
||||
Log zerolog.Logger
|
||||
Cfg *config.Config
|
||||
}
|
||||
|
||||
type BannersService interface {
|
||||
GetAll(req request.BannersQueryRequest) (banners []*response.BannersResponse, paging paginator.Pagination, err error)
|
||||
GetOne(id uint) (banner *response.BannersResponse, err error)
|
||||
Create(req request.BannersCreateRequest) (banner *response.BannersResponse, err error)
|
||||
Update(id uint, req request.BannersUpdateRequest) (banner *response.BannersResponse, err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewBannersService(repo repository.BannersRepository, log zerolog.Logger, cfg *config.Config) BannersService {
|
||||
return &bannersService{
|
||||
Repo: repo,
|
||||
Log: log,
|
||||
Cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *bannersService) GetAll(req request.BannersQueryRequest) (banners []*response.BannersResponse, paging paginator.Pagination, err error) {
|
||||
bannersEntity, paging, err := _i.Repo.GetAll(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
for _, banner := range bannersEntity {
|
||||
banners = append(banners, mapper.BannersResponseMapper(banner, host))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *bannersService) GetOne(id uint) (banner *response.BannersResponse, err error) {
|
||||
bannerEntity, err := _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if bannerEntity == nil {
|
||||
err = errors.New("banner not found")
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
banner = mapper.BannersResponseMapper(bannerEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *bannersService) Create(req request.BannersCreateRequest) (banner *response.BannersResponse, err error) {
|
||||
bannerEntity := req.ToEntity()
|
||||
isActive := true
|
||||
bannerEntity.IsActive = &isActive
|
||||
|
||||
bannerEntity, err = _i.Repo.Create(bannerEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
banner = mapper.BannersResponseMapper(bannerEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *bannersService) Update(id uint, req request.BannersUpdateRequest) (banner *response.BannersResponse, err error) {
|
||||
bannerEntity := req.ToEntity()
|
||||
|
||||
err = _i.Repo.Update(id, bannerEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
bannerEntity, err = _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
banner = mapper.BannersResponseMapper(bannerEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *bannersService) Delete(id uint) (err error) {
|
||||
err = _i.Repo.Delete(id)
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package controller
|
||||
|
||||
import "jaecoo-be/app/module/galleries/service"
|
||||
|
||||
type Controller struct {
|
||||
Galleries GalleriesController
|
||||
}
|
||||
|
||||
func NewController(GalleriesService service.GalleriesService) *Controller {
|
||||
return &Controller{
|
||||
Galleries: NewGalleriesController(GalleriesService),
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/galleries/request"
|
||||
"jaecoo-be/app/module/galleries/service"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
utilRes "jaecoo-be/utils/response"
|
||||
utilVal "jaecoo-be/utils/validator"
|
||||
)
|
||||
|
||||
type galleriesController struct {
|
||||
galleriesService service.GalleriesService
|
||||
}
|
||||
|
||||
type GalleriesController interface {
|
||||
All(c *fiber.Ctx) error
|
||||
Show(c *fiber.Ctx) error
|
||||
Save(c *fiber.Ctx) error
|
||||
Update(c *fiber.Ctx) error
|
||||
Delete(c *fiber.Ctx) error
|
||||
}
|
||||
|
||||
func NewGalleriesController(galleriesService service.GalleriesService) GalleriesController {
|
||||
return &galleriesController{
|
||||
galleriesService: galleriesService,
|
||||
}
|
||||
}
|
||||
|
||||
// All Galleries
|
||||
// @Summary Get all Galleries
|
||||
// @Description API for getting all Galleries
|
||||
// @Tags Galleries
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param req query request.GalleriesQueryRequestContext false "query parameters"
|
||||
// @Param req query paginator.Pagination false "pagination parameters"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /galleries [get]
|
||||
func (_i *galleriesController) All(c *fiber.Ctx) error {
|
||||
paginate, err := paginator.Paginate(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reqContext := request.GalleriesQueryRequestContext{
|
||||
Title: c.Query("title"),
|
||||
}
|
||||
req := reqContext.ToParamRequest()
|
||||
req.Pagination = paginate
|
||||
|
||||
galleriesData, paging, err := _i.galleriesService.GetAll(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Galleries list successfully retrieved"},
|
||||
Data: galleriesData,
|
||||
Meta: paging,
|
||||
})
|
||||
}
|
||||
|
||||
// Show Gallery
|
||||
// @Summary Get Gallery by ID
|
||||
// @Description API for getting Gallery by ID
|
||||
// @Tags Galleries
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Gallery ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /galleries/{id} [get]
|
||||
func (_i *galleriesController) Show(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
galleryData, err := _i.galleriesService.GetOne(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Gallery successfully retrieved"},
|
||||
Data: galleryData,
|
||||
})
|
||||
}
|
||||
|
||||
// Save Gallery
|
||||
// @Summary Create Gallery
|
||||
// @Description API for creating Gallery
|
||||
// @Tags Galleries
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param payload body request.GalleriesCreateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /galleries [post]
|
||||
func (_i *galleriesController) Save(c *fiber.Ctx) error {
|
||||
req := new(request.GalleriesCreateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.galleriesService.Create(*req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Gallery successfully created"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Update Gallery
|
||||
// @Summary Update Gallery
|
||||
// @Description API for updating Gallery
|
||||
// @Tags Galleries
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Gallery ID"
|
||||
// @Param payload body request.GalleriesUpdateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /galleries/{id} [put]
|
||||
func (_i *galleriesController) Update(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := new(request.GalleriesUpdateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.galleriesService.Update(uint(id), *req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Gallery successfully updated"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Delete Gallery
|
||||
// @Summary Delete Gallery
|
||||
// @Description API for deleting Gallery (soft delete)
|
||||
// @Tags Galleries
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Gallery ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /galleries/{id} [delete]
|
||||
func (_i *galleriesController) Delete(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = _i.galleriesService.Delete(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Gallery successfully deleted"},
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package galleries
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/galleries/controller"
|
||||
"jaecoo-be/app/module/galleries/repository"
|
||||
"jaecoo-be/app/module/galleries/service"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
// GalleriesRouter struct of GalleriesRouter
|
||||
type GalleriesRouter struct {
|
||||
App fiber.Router
|
||||
Controller *controller.Controller
|
||||
}
|
||||
|
||||
// NewGalleriesModule register bulky of Galleries module
|
||||
var NewGalleriesModule = fx.Options(
|
||||
// register repository of Galleries module
|
||||
fx.Provide(repository.NewGalleriesRepository),
|
||||
|
||||
// register service of Galleries module
|
||||
fx.Provide(service.NewGalleriesService),
|
||||
|
||||
// register controller of Galleries module
|
||||
fx.Provide(controller.NewController),
|
||||
|
||||
// register router of Galleries module
|
||||
fx.Provide(NewGalleriesRouter),
|
||||
)
|
||||
|
||||
// NewGalleriesRouter init GalleriesRouter
|
||||
func NewGalleriesRouter(fiber *fiber.App, controller *controller.Controller) *GalleriesRouter {
|
||||
return &GalleriesRouter{
|
||||
App: fiber,
|
||||
Controller: controller,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterGalleriesRoutes register routes of Galleries module
|
||||
func (_i *GalleriesRouter) RegisterGalleriesRoutes() {
|
||||
// define controllers
|
||||
galleriesController := _i.Controller.Galleries
|
||||
|
||||
// define routes
|
||||
_i.App.Route("/galleries", func(router fiber.Router) {
|
||||
router.Get("/", galleriesController.All)
|
||||
router.Get("/:id", galleriesController.Show)
|
||||
router.Post("/", galleriesController.Save)
|
||||
router.Put("/:id", galleriesController.Update)
|
||||
router.Delete("/:id", galleriesController.Delete)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package mapper
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database/entity"
|
||||
res "jaecoo-be/app/module/galleries/response"
|
||||
)
|
||||
|
||||
func GalleriesResponseMapper(gallery *entity.Galleries, host string) *res.GalleriesResponse {
|
||||
if gallery == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
response := &res.GalleriesResponse{
|
||||
ID: gallery.ID,
|
||||
Title: gallery.Title,
|
||||
Description: gallery.Description,
|
||||
ThumbnailPath: gallery.ThumbnailPath,
|
||||
IsActive: gallery.IsActive,
|
||||
CreatedAt: gallery.CreatedAt,
|
||||
UpdatedAt: gallery.UpdatedAt,
|
||||
}
|
||||
|
||||
if gallery.ThumbnailPath != nil && *gallery.ThumbnailPath != "" {
|
||||
thumbnailUrl := host + "/galleries/thumbnail/viewer/" + *gallery.ThumbnailPath
|
||||
response.ThumbnailUrl = &thumbnailUrl
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database"
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/app/module/galleries/request"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type galleriesRepository struct {
|
||||
DB *database.Database
|
||||
Log zerolog.Logger
|
||||
}
|
||||
|
||||
type GalleriesRepository interface {
|
||||
GetAll(req request.GalleriesQueryRequest) (galleries []*entity.Galleries, paging paginator.Pagination, err error)
|
||||
FindOne(id uint) (gallery *entity.Galleries, err error)
|
||||
Create(gallery *entity.Galleries) (galleryReturn *entity.Galleries, err error)
|
||||
Update(id uint, gallery *entity.Galleries) (err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewGalleriesRepository(db *database.Database, log zerolog.Logger) GalleriesRepository {
|
||||
return &galleriesRepository{
|
||||
DB: db,
|
||||
Log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *galleriesRepository) GetAll(req request.GalleriesQueryRequest) (galleries []*entity.Galleries, paging paginator.Pagination, err error) {
|
||||
var count int64
|
||||
|
||||
query := _i.DB.DB.Model(&entity.Galleries{})
|
||||
|
||||
if req.Title != nil && *req.Title != "" {
|
||||
title := strings.ToLower(*req.Title)
|
||||
query = query.Where("LOWER(title) LIKE ?", "%"+title+"%")
|
||||
}
|
||||
|
||||
query = query.Where("is_active = ?", true)
|
||||
|
||||
query.Count(&count)
|
||||
|
||||
req.Pagination.Count = count
|
||||
req.Pagination = paginator.Paging(req.Pagination)
|
||||
|
||||
query = query.Order("created_at DESC")
|
||||
|
||||
err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&galleries).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
paging = *req.Pagination
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleriesRepository) FindOne(id uint) (gallery *entity.Galleries, err error) {
|
||||
gallery = &entity.Galleries{}
|
||||
err = _i.DB.DB.Where("id = ? AND is_active = ?", id, true).First(gallery).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleriesRepository) Create(gallery *entity.Galleries) (galleryReturn *entity.Galleries, err error) {
|
||||
if err = _i.DB.DB.Create(gallery).Error; err != nil {
|
||||
return
|
||||
}
|
||||
galleryReturn = gallery
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleriesRepository) Update(id uint, gallery *entity.Galleries) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.Galleries{}).Where("id = ?", id).Updates(gallery).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleriesRepository) Delete(id uint) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.Galleries{}).Where("id = ?", id).Update("is_active", false).Error
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package request
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/utils/paginator"
|
||||
)
|
||||
|
||||
type GalleriesQueryRequest struct {
|
||||
Title *string `json:"title"`
|
||||
Pagination *paginator.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
type GalleriesQueryRequestContext struct {
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
func (req GalleriesQueryRequestContext) ToParamRequest() GalleriesQueryRequest {
|
||||
var request GalleriesQueryRequest
|
||||
|
||||
if title := req.Title; title != "" {
|
||||
request.Title = &title
|
||||
}
|
||||
|
||||
return request
|
||||
}
|
||||
|
||||
type GalleriesCreateRequest struct {
|
||||
Title string `json:"title" validate:"required"`
|
||||
Description *string `json:"description"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
}
|
||||
|
||||
func (req GalleriesCreateRequest) ToEntity() *entity.Galleries {
|
||||
return &entity.Galleries{
|
||||
Title: req.Title,
|
||||
Description: req.Description,
|
||||
ThumbnailPath: req.ThumbnailPath,
|
||||
}
|
||||
}
|
||||
|
||||
type GalleriesUpdateRequest struct {
|
||||
Title *string `json:"title"`
|
||||
Description *string `json:"description"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
}
|
||||
|
||||
func (req GalleriesUpdateRequest) ToEntity() *entity.Galleries {
|
||||
return &entity.Galleries{
|
||||
Title: getStringValue(req.Title),
|
||||
Description: req.Description,
|
||||
ThumbnailPath: req.ThumbnailPath,
|
||||
IsActive: req.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
func getStringValue(s *string) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
return *s
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package response
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type GalleriesResponse struct {
|
||||
ID uint `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description *string `json:"description"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
ThumbnailUrl *string `json:"thumbnail_url"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"jaecoo-be/app/module/galleries/mapper"
|
||||
"jaecoo-be/app/module/galleries/repository"
|
||||
"jaecoo-be/app/module/galleries/request"
|
||||
"jaecoo-be/app/module/galleries/response"
|
||||
"jaecoo-be/config/config"
|
||||
"jaecoo-be/utils/paginator"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type galleriesService struct {
|
||||
Repo repository.GalleriesRepository
|
||||
Log zerolog.Logger
|
||||
Cfg *config.Config
|
||||
}
|
||||
|
||||
type GalleriesService interface {
|
||||
GetAll(req request.GalleriesQueryRequest) (galleries []*response.GalleriesResponse, paging paginator.Pagination, err error)
|
||||
GetOne(id uint) (gallery *response.GalleriesResponse, err error)
|
||||
Create(req request.GalleriesCreateRequest) (gallery *response.GalleriesResponse, err error)
|
||||
Update(id uint, req request.GalleriesUpdateRequest) (gallery *response.GalleriesResponse, err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewGalleriesService(repo repository.GalleriesRepository, log zerolog.Logger, cfg *config.Config) GalleriesService {
|
||||
return &galleriesService{
|
||||
Repo: repo,
|
||||
Log: log,
|
||||
Cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *galleriesService) GetAll(req request.GalleriesQueryRequest) (galleries []*response.GalleriesResponse, paging paginator.Pagination, err error) {
|
||||
galleriesEntity, paging, err := _i.Repo.GetAll(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
for _, gallery := range galleriesEntity {
|
||||
galleries = append(galleries, mapper.GalleriesResponseMapper(gallery, host))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleriesService) GetOne(id uint) (gallery *response.GalleriesResponse, err error) {
|
||||
galleryEntity, err := _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if galleryEntity == nil {
|
||||
err = errors.New("gallery not found")
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
gallery = mapper.GalleriesResponseMapper(galleryEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleriesService) Create(req request.GalleriesCreateRequest) (gallery *response.GalleriesResponse, err error) {
|
||||
galleryEntity := req.ToEntity()
|
||||
isActive := true
|
||||
galleryEntity.IsActive = &isActive
|
||||
|
||||
galleryEntity, err = _i.Repo.Create(galleryEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
gallery = mapper.GalleriesResponseMapper(galleryEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleriesService) Update(id uint, req request.GalleriesUpdateRequest) (gallery *response.GalleriesResponse, err error) {
|
||||
galleryEntity := req.ToEntity()
|
||||
|
||||
err = _i.Repo.Update(id, galleryEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
galleryEntity, err = _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
gallery = mapper.GalleriesResponseMapper(galleryEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleriesService) Delete(id uint) (err error) {
|
||||
err = _i.Repo.Delete(id)
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package controller
|
||||
|
||||
import "jaecoo-be/app/module/gallery_files/service"
|
||||
|
||||
type Controller struct {
|
||||
GalleryFiles GalleryFilesController
|
||||
}
|
||||
|
||||
func NewController(GalleryFilesService service.GalleryFilesService) *Controller {
|
||||
return &Controller{
|
||||
GalleryFiles: NewGalleryFilesController(GalleryFilesService),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/gallery_files/request"
|
||||
"jaecoo-be/app/module/gallery_files/service"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
utilRes "jaecoo-be/utils/response"
|
||||
utilVal "jaecoo-be/utils/validator"
|
||||
)
|
||||
|
||||
type galleryFilesController struct {
|
||||
galleryFilesService service.GalleryFilesService
|
||||
}
|
||||
|
||||
type GalleryFilesController interface {
|
||||
All(c *fiber.Ctx) error
|
||||
Show(c *fiber.Ctx) error
|
||||
Save(c *fiber.Ctx) error
|
||||
Update(c *fiber.Ctx) error
|
||||
Delete(c *fiber.Ctx) error
|
||||
}
|
||||
|
||||
func NewGalleryFilesController(galleryFilesService service.GalleryFilesService) GalleryFilesController {
|
||||
return &galleryFilesController{
|
||||
galleryFilesService: galleryFilesService,
|
||||
}
|
||||
}
|
||||
|
||||
// All GalleryFiles
|
||||
// @Summary Get all GalleryFiles
|
||||
// @Description API for getting all GalleryFiles
|
||||
// @Tags GalleryFiles
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param req query request.GalleryFilesQueryRequestContext false "query parameters"
|
||||
// @Param req query paginator.Pagination false "pagination parameters"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /gallery-files [get]
|
||||
func (_i *galleryFilesController) All(c *fiber.Ctx) error {
|
||||
paginate, err := paginator.Paginate(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reqContext := request.GalleryFilesQueryRequestContext{
|
||||
GalleryID: c.Query("gallery_id"),
|
||||
Title: c.Query("title"),
|
||||
}
|
||||
req := reqContext.ToParamRequest()
|
||||
req.Pagination = paginate
|
||||
|
||||
filesData, paging, err := _i.galleryFilesService.GetAll(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"GalleryFiles list successfully retrieved"},
|
||||
Data: filesData,
|
||||
Meta: paging,
|
||||
})
|
||||
}
|
||||
|
||||
// Show GalleryFile
|
||||
// @Summary Get GalleryFile by ID
|
||||
// @Description API for getting GalleryFile by ID
|
||||
// @Tags GalleryFiles
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "GalleryFile ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /gallery-files/{id} [get]
|
||||
func (_i *galleryFilesController) Show(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fileData, err := _i.galleryFilesService.GetOne(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"GalleryFile successfully retrieved"},
|
||||
Data: fileData,
|
||||
})
|
||||
}
|
||||
|
||||
// Save GalleryFile
|
||||
// @Summary Create GalleryFile
|
||||
// @Description API for creating GalleryFile
|
||||
// @Tags GalleryFiles
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param payload body request.GalleryFilesCreateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /gallery-files [post]
|
||||
func (_i *galleryFilesController) Save(c *fiber.Ctx) error {
|
||||
req := new(request.GalleryFilesCreateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.galleryFilesService.Create(*req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"GalleryFile successfully created"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Update GalleryFile
|
||||
// @Summary Update GalleryFile
|
||||
// @Description API for updating GalleryFile
|
||||
// @Tags GalleryFiles
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "GalleryFile ID"
|
||||
// @Param payload body request.GalleryFilesUpdateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /gallery-files/{id} [put]
|
||||
func (_i *galleryFilesController) Update(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := new(request.GalleryFilesUpdateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.galleryFilesService.Update(uint(id), *req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"GalleryFile successfully updated"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Delete GalleryFile
|
||||
// @Summary Delete GalleryFile
|
||||
// @Description API for deleting GalleryFile (soft delete)
|
||||
// @Tags GalleryFiles
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "GalleryFile ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /gallery-files/{id} [delete]
|
||||
func (_i *galleryFilesController) Delete(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = _i.galleryFilesService.Delete(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"GalleryFile successfully deleted"},
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package gallery_files
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/gallery_files/controller"
|
||||
"jaecoo-be/app/module/gallery_files/repository"
|
||||
"jaecoo-be/app/module/gallery_files/service"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
// GalleryFilesRouter struct of GalleryFilesRouter
|
||||
type GalleryFilesRouter struct {
|
||||
App fiber.Router
|
||||
Controller *controller.Controller
|
||||
}
|
||||
|
||||
// NewGalleryFilesModule register bulky of GalleryFiles module
|
||||
var NewGalleryFilesModule = fx.Options(
|
||||
// register repository of GalleryFiles module
|
||||
fx.Provide(repository.NewGalleryFilesRepository),
|
||||
|
||||
// register service of GalleryFiles module
|
||||
fx.Provide(service.NewGalleryFilesService),
|
||||
|
||||
// register controller of GalleryFiles module
|
||||
fx.Provide(controller.NewController),
|
||||
|
||||
// register router of GalleryFiles module
|
||||
fx.Provide(NewGalleryFilesRouter),
|
||||
)
|
||||
|
||||
// NewGalleryFilesRouter init GalleryFilesRouter
|
||||
func NewGalleryFilesRouter(fiber *fiber.App, controller *controller.Controller) *GalleryFilesRouter {
|
||||
return &GalleryFilesRouter{
|
||||
App: fiber,
|
||||
Controller: controller,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterGalleryFilesRoutes register routes of GalleryFiles module
|
||||
func (_i *GalleryFilesRouter) RegisterGalleryFilesRoutes() {
|
||||
// define controllers
|
||||
galleryFilesController := _i.Controller.GalleryFiles
|
||||
|
||||
// define routes
|
||||
_i.App.Route("/gallery-files", func(router fiber.Router) {
|
||||
router.Get("/", galleryFilesController.All)
|
||||
router.Get("/:id", galleryFilesController.Show)
|
||||
router.Post("/", galleryFilesController.Save)
|
||||
router.Put("/:id", galleryFilesController.Update)
|
||||
router.Delete("/:id", galleryFilesController.Delete)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package mapper
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database/entity"
|
||||
res "jaecoo-be/app/module/gallery_files/response"
|
||||
)
|
||||
|
||||
func GalleryFilesResponseMapper(file *entity.GalleryFiles, host string) *res.GalleryFilesResponse {
|
||||
if file == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
response := &res.GalleryFilesResponse{
|
||||
ID: file.ID,
|
||||
GalleryID: file.GalleryID,
|
||||
Title: file.Title,
|
||||
ImagePath: file.ImagePath,
|
||||
IsActive: file.IsActive,
|
||||
CreatedAt: file.CreatedAt,
|
||||
UpdatedAt: file.UpdatedAt,
|
||||
}
|
||||
|
||||
if file.ImagePath != nil && *file.ImagePath != "" {
|
||||
imageUrl := host + "/gallery-files/image/viewer/" + *file.ImagePath
|
||||
response.ImageUrl = &imageUrl
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database"
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/app/module/gallery_files/request"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type galleryFilesRepository struct {
|
||||
DB *database.Database
|
||||
Log zerolog.Logger
|
||||
}
|
||||
|
||||
type GalleryFilesRepository interface {
|
||||
GetAll(req request.GalleryFilesQueryRequest) (files []*entity.GalleryFiles, paging paginator.Pagination, err error)
|
||||
FindOne(id uint) (file *entity.GalleryFiles, err error)
|
||||
Create(file *entity.GalleryFiles) (fileReturn *entity.GalleryFiles, err error)
|
||||
Update(id uint, file *entity.GalleryFiles) (err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewGalleryFilesRepository(db *database.Database, log zerolog.Logger) GalleryFilesRepository {
|
||||
return &galleryFilesRepository{
|
||||
DB: db,
|
||||
Log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *galleryFilesRepository) GetAll(req request.GalleryFilesQueryRequest) (files []*entity.GalleryFiles, paging paginator.Pagination, err error) {
|
||||
var count int64
|
||||
|
||||
query := _i.DB.DB.Model(&entity.GalleryFiles{})
|
||||
|
||||
if req.GalleryID != nil {
|
||||
query = query.Where("gallery_id = ?", *req.GalleryID)
|
||||
}
|
||||
|
||||
if req.Title != nil && *req.Title != "" {
|
||||
title := strings.ToLower(*req.Title)
|
||||
query = query.Where("LOWER(title) LIKE ?", "%"+title+"%")
|
||||
}
|
||||
|
||||
query = query.Where("is_active = ?", true)
|
||||
|
||||
query.Count(&count)
|
||||
|
||||
req.Pagination.Count = count
|
||||
req.Pagination = paginator.Paging(req.Pagination)
|
||||
|
||||
query = query.Order("created_at DESC")
|
||||
|
||||
err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&files).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
paging = *req.Pagination
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleryFilesRepository) FindOne(id uint) (file *entity.GalleryFiles, err error) {
|
||||
file = &entity.GalleryFiles{}
|
||||
err = _i.DB.DB.Where("id = ? AND is_active = ?", id, true).First(file).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleryFilesRepository) Create(file *entity.GalleryFiles) (fileReturn *entity.GalleryFiles, err error) {
|
||||
if err = _i.DB.DB.Create(file).Error; err != nil {
|
||||
return
|
||||
}
|
||||
fileReturn = file
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleryFilesRepository) Update(id uint, file *entity.GalleryFiles) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.GalleryFiles{}).Where("id = ?", id).Updates(file).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleryFilesRepository) Delete(id uint) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.GalleryFiles{}).Where("id = ?", id).Update("is_active", false).Error
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package request
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type GalleryFilesQueryRequest struct {
|
||||
GalleryID *uint `json:"gallery_id"`
|
||||
Title *string `json:"title"`
|
||||
Pagination *paginator.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
type GalleryFilesQueryRequestContext struct {
|
||||
GalleryID string `json:"gallery_id"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
func (req GalleryFilesQueryRequestContext) ToParamRequest() GalleryFilesQueryRequest {
|
||||
var request GalleryFilesQueryRequest
|
||||
|
||||
if galleryIDStr := req.GalleryID; galleryIDStr != "" {
|
||||
galleryID, err := strconv.Atoi(galleryIDStr)
|
||||
if err == nil {
|
||||
galleryIDUint := uint(galleryID)
|
||||
request.GalleryID = &galleryIDUint
|
||||
}
|
||||
}
|
||||
if title := req.Title; title != "" {
|
||||
request.Title = &title
|
||||
}
|
||||
|
||||
return request
|
||||
}
|
||||
|
||||
type GalleryFilesCreateRequest struct {
|
||||
GalleryID uint `json:"gallery_id" validate:"required"`
|
||||
Title *string `json:"title"`
|
||||
ImagePath *string `json:"image_path"`
|
||||
}
|
||||
|
||||
func (req GalleryFilesCreateRequest) ToEntity() *entity.GalleryFiles {
|
||||
return &entity.GalleryFiles{
|
||||
GalleryID: req.GalleryID,
|
||||
Title: req.Title,
|
||||
ImagePath: req.ImagePath,
|
||||
}
|
||||
}
|
||||
|
||||
type GalleryFilesUpdateRequest struct {
|
||||
GalleryID *uint `json:"gallery_id"`
|
||||
Title *string `json:"title"`
|
||||
ImagePath *string `json:"image_path"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
}
|
||||
|
||||
func (req GalleryFilesUpdateRequest) ToEntity() *entity.GalleryFiles {
|
||||
return &entity.GalleryFiles{
|
||||
GalleryID: getUintValue(req.GalleryID),
|
||||
Title: req.Title,
|
||||
ImagePath: req.ImagePath,
|
||||
IsActive: req.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
func getUintValue(u *uint) uint {
|
||||
if u == nil {
|
||||
return 0
|
||||
}
|
||||
return *u
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package response
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type GalleryFilesResponse struct {
|
||||
ID uint `json:"id"`
|
||||
GalleryID uint `json:"gallery_id"`
|
||||
Title *string `json:"title"`
|
||||
ImagePath *string `json:"image_path"`
|
||||
ImageUrl *string `json:"image_url"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"jaecoo-be/app/module/gallery_files/mapper"
|
||||
"jaecoo-be/app/module/gallery_files/repository"
|
||||
"jaecoo-be/app/module/gallery_files/request"
|
||||
"jaecoo-be/app/module/gallery_files/response"
|
||||
"jaecoo-be/config/config"
|
||||
"jaecoo-be/utils/paginator"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type galleryFilesService struct {
|
||||
Repo repository.GalleryFilesRepository
|
||||
Log zerolog.Logger
|
||||
Cfg *config.Config
|
||||
}
|
||||
|
||||
type GalleryFilesService interface {
|
||||
GetAll(req request.GalleryFilesQueryRequest) (files []*response.GalleryFilesResponse, paging paginator.Pagination, err error)
|
||||
GetOne(id uint) (file *response.GalleryFilesResponse, err error)
|
||||
Create(req request.GalleryFilesCreateRequest) (file *response.GalleryFilesResponse, err error)
|
||||
Update(id uint, req request.GalleryFilesUpdateRequest) (file *response.GalleryFilesResponse, err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewGalleryFilesService(repo repository.GalleryFilesRepository, log zerolog.Logger, cfg *config.Config) GalleryFilesService {
|
||||
return &galleryFilesService{
|
||||
Repo: repo,
|
||||
Log: log,
|
||||
Cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *galleryFilesService) GetAll(req request.GalleryFilesQueryRequest) (files []*response.GalleryFilesResponse, paging paginator.Pagination, err error) {
|
||||
filesEntity, paging, err := _i.Repo.GetAll(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
for _, file := range filesEntity {
|
||||
files = append(files, mapper.GalleryFilesResponseMapper(file, host))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleryFilesService) GetOne(id uint) (file *response.GalleryFilesResponse, err error) {
|
||||
fileEntity, err := _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if fileEntity == nil {
|
||||
err = errors.New("gallery file not found")
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
file = mapper.GalleryFilesResponseMapper(fileEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleryFilesService) Create(req request.GalleryFilesCreateRequest) (file *response.GalleryFilesResponse, err error) {
|
||||
fileEntity := req.ToEntity()
|
||||
isActive := true
|
||||
fileEntity.IsActive = &isActive
|
||||
|
||||
fileEntity, err = _i.Repo.Create(fileEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
file = mapper.GalleryFilesResponseMapper(fileEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleryFilesService) Update(id uint, req request.GalleryFilesUpdateRequest) (file *response.GalleryFilesResponse, err error) {
|
||||
fileEntity := req.ToEntity()
|
||||
|
||||
err = _i.Repo.Update(id, fileEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fileEntity, err = _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
file = mapper.GalleryFilesResponseMapper(fileEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *galleryFilesService) Delete(id uint) (err error) {
|
||||
err = _i.Repo.Delete(id)
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package controller
|
||||
|
||||
import "jaecoo-be/app/module/product_specifications/service"
|
||||
|
||||
type Controller struct {
|
||||
ProductSpecifications ProductSpecificationsController
|
||||
}
|
||||
|
||||
func NewController(ProductSpecificationsService service.ProductSpecificationsService) *Controller {
|
||||
return &Controller{
|
||||
ProductSpecifications: NewProductSpecificationsController(ProductSpecificationsService),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/product_specifications/request"
|
||||
"jaecoo-be/app/module/product_specifications/service"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
utilRes "jaecoo-be/utils/response"
|
||||
utilVal "jaecoo-be/utils/validator"
|
||||
)
|
||||
|
||||
type productSpecificationsController struct {
|
||||
productSpecificationsService service.ProductSpecificationsService
|
||||
}
|
||||
|
||||
type ProductSpecificationsController interface {
|
||||
All(c *fiber.Ctx) error
|
||||
Show(c *fiber.Ctx) error
|
||||
Save(c *fiber.Ctx) error
|
||||
Update(c *fiber.Ctx) error
|
||||
Delete(c *fiber.Ctx) error
|
||||
}
|
||||
|
||||
func NewProductSpecificationsController(productSpecificationsService service.ProductSpecificationsService) ProductSpecificationsController {
|
||||
return &productSpecificationsController{
|
||||
productSpecificationsService: productSpecificationsService,
|
||||
}
|
||||
}
|
||||
|
||||
// All ProductSpecifications
|
||||
// @Summary Get all ProductSpecifications
|
||||
// @Description API for getting all ProductSpecifications
|
||||
// @Tags ProductSpecifications
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param req query request.ProductSpecificationsQueryRequestContext false "query parameters"
|
||||
// @Param req query paginator.Pagination false "pagination parameters"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /product-specifications [get]
|
||||
func (_i *productSpecificationsController) All(c *fiber.Ctx) error {
|
||||
paginate, err := paginator.Paginate(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reqContext := request.ProductSpecificationsQueryRequestContext{
|
||||
ProductID: c.Query("product_id"),
|
||||
Title: c.Query("title"),
|
||||
}
|
||||
req := reqContext.ToParamRequest()
|
||||
req.Pagination = paginate
|
||||
|
||||
specsData, paging, err := _i.productSpecificationsService.GetAll(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"ProductSpecifications list successfully retrieved"},
|
||||
Data: specsData,
|
||||
Meta: paging,
|
||||
})
|
||||
}
|
||||
|
||||
// Show ProductSpecification
|
||||
// @Summary Get ProductSpecification by ID
|
||||
// @Description API for getting ProductSpecification by ID
|
||||
// @Tags ProductSpecifications
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "ProductSpecification ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /product-specifications/{id} [get]
|
||||
func (_i *productSpecificationsController) Show(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
specData, err := _i.productSpecificationsService.GetOne(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"ProductSpecification successfully retrieved"},
|
||||
Data: specData,
|
||||
})
|
||||
}
|
||||
|
||||
// Save ProductSpecification
|
||||
// @Summary Create ProductSpecification
|
||||
// @Description API for creating ProductSpecification
|
||||
// @Tags ProductSpecifications
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param payload body request.ProductSpecificationsCreateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /product-specifications [post]
|
||||
func (_i *productSpecificationsController) Save(c *fiber.Ctx) error {
|
||||
req := new(request.ProductSpecificationsCreateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.productSpecificationsService.Create(*req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"ProductSpecification successfully created"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Update ProductSpecification
|
||||
// @Summary Update ProductSpecification
|
||||
// @Description API for updating ProductSpecification
|
||||
// @Tags ProductSpecifications
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "ProductSpecification ID"
|
||||
// @Param payload body request.ProductSpecificationsUpdateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /product-specifications/{id} [put]
|
||||
func (_i *productSpecificationsController) Update(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := new(request.ProductSpecificationsUpdateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.productSpecificationsService.Update(uint(id), *req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"ProductSpecification successfully updated"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Delete ProductSpecification
|
||||
// @Summary Delete ProductSpecification
|
||||
// @Description API for deleting ProductSpecification (soft delete)
|
||||
// @Tags ProductSpecifications
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "ProductSpecification ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /product-specifications/{id} [delete]
|
||||
func (_i *productSpecificationsController) Delete(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = _i.productSpecificationsService.Delete(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"ProductSpecification successfully deleted"},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package mapper
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database/entity"
|
||||
res "jaecoo-be/app/module/product_specifications/response"
|
||||
)
|
||||
|
||||
func ProductSpecificationsResponseMapper(spec *entity.ProductSpecifications, host string) *res.ProductSpecificationsResponse {
|
||||
if spec == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
response := &res.ProductSpecificationsResponse{
|
||||
ID: spec.ID,
|
||||
ProductID: spec.ProductID,
|
||||
Title: spec.Title,
|
||||
ThumbnailPath: spec.ThumbnailPath,
|
||||
IsActive: spec.IsActive,
|
||||
CreatedAt: spec.CreatedAt,
|
||||
UpdatedAt: spec.UpdatedAt,
|
||||
}
|
||||
|
||||
if spec.ThumbnailPath != nil && *spec.ThumbnailPath != "" {
|
||||
thumbnailUrl := host + "/product-specifications/thumbnail/viewer/" + *spec.ThumbnailPath
|
||||
response.ThumbnailUrl = &thumbnailUrl
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package product_specifications
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/product_specifications/controller"
|
||||
"jaecoo-be/app/module/product_specifications/repository"
|
||||
"jaecoo-be/app/module/product_specifications/service"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
// ProductSpecificationsRouter struct of ProductSpecificationsRouter
|
||||
type ProductSpecificationsRouter struct {
|
||||
App fiber.Router
|
||||
Controller *controller.Controller
|
||||
}
|
||||
|
||||
// NewProductSpecificationsModule register bulky of ProductSpecifications module
|
||||
var NewProductSpecificationsModule = fx.Options(
|
||||
// register repository of ProductSpecifications module
|
||||
fx.Provide(repository.NewProductSpecificationsRepository),
|
||||
|
||||
// register service of ProductSpecifications module
|
||||
fx.Provide(service.NewProductSpecificationsService),
|
||||
|
||||
// register controller of ProductSpecifications module
|
||||
fx.Provide(controller.NewController),
|
||||
|
||||
// register router of ProductSpecifications module
|
||||
fx.Provide(NewProductSpecificationsRouter),
|
||||
)
|
||||
|
||||
// NewProductSpecificationsRouter init ProductSpecificationsRouter
|
||||
func NewProductSpecificationsRouter(fiber *fiber.App, controller *controller.Controller) *ProductSpecificationsRouter {
|
||||
return &ProductSpecificationsRouter{
|
||||
App: fiber,
|
||||
Controller: controller,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterProductSpecificationsRoutes register routes of ProductSpecifications module
|
||||
func (_i *ProductSpecificationsRouter) RegisterProductSpecificationsRoutes() {
|
||||
// define controllers
|
||||
productSpecificationsController := _i.Controller.ProductSpecifications
|
||||
|
||||
// define routes
|
||||
_i.App.Route("/product-specifications", func(router fiber.Router) {
|
||||
router.Get("/", productSpecificationsController.All)
|
||||
router.Get("/:id", productSpecificationsController.Show)
|
||||
router.Post("/", productSpecificationsController.Save)
|
||||
router.Put("/:id", productSpecificationsController.Update)
|
||||
router.Delete("/:id", productSpecificationsController.Delete)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database"
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/app/module/product_specifications/request"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type productSpecificationsRepository struct {
|
||||
DB *database.Database
|
||||
Log zerolog.Logger
|
||||
}
|
||||
|
||||
type ProductSpecificationsRepository interface {
|
||||
GetAll(req request.ProductSpecificationsQueryRequest) (specs []*entity.ProductSpecifications, paging paginator.Pagination, err error)
|
||||
FindOne(id uint) (spec *entity.ProductSpecifications, err error)
|
||||
Create(spec *entity.ProductSpecifications) (specReturn *entity.ProductSpecifications, err error)
|
||||
Update(id uint, spec *entity.ProductSpecifications) (err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewProductSpecificationsRepository(db *database.Database, log zerolog.Logger) ProductSpecificationsRepository {
|
||||
return &productSpecificationsRepository{
|
||||
DB: db,
|
||||
Log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *productSpecificationsRepository) GetAll(req request.ProductSpecificationsQueryRequest) (specs []*entity.ProductSpecifications, paging paginator.Pagination, err error) {
|
||||
var count int64
|
||||
|
||||
query := _i.DB.DB.Model(&entity.ProductSpecifications{})
|
||||
|
||||
if req.ProductID != nil {
|
||||
query = query.Where("product_id = ?", *req.ProductID)
|
||||
}
|
||||
|
||||
if req.Title != nil && *req.Title != "" {
|
||||
title := strings.ToLower(*req.Title)
|
||||
query = query.Where("LOWER(title) LIKE ?", "%"+title+"%")
|
||||
}
|
||||
|
||||
query = query.Where("is_active = ?", true)
|
||||
|
||||
query.Count(&count)
|
||||
|
||||
req.Pagination.Count = count
|
||||
req.Pagination = paginator.Paging(req.Pagination)
|
||||
|
||||
query = query.Order("created_at DESC")
|
||||
|
||||
err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&specs).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
paging = *req.Pagination
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productSpecificationsRepository) FindOne(id uint) (spec *entity.ProductSpecifications, err error) {
|
||||
spec = &entity.ProductSpecifications{}
|
||||
err = _i.DB.DB.Where("id = ? AND is_active = ?", id, true).First(spec).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productSpecificationsRepository) Create(spec *entity.ProductSpecifications) (specReturn *entity.ProductSpecifications, err error) {
|
||||
if err = _i.DB.DB.Create(spec).Error; err != nil {
|
||||
return
|
||||
}
|
||||
specReturn = spec
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productSpecificationsRepository) Update(id uint, spec *entity.ProductSpecifications) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.ProductSpecifications{}).Where("id = ?", id).Updates(spec).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productSpecificationsRepository) Delete(id uint) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.ProductSpecifications{}).Where("id = ?", id).Update("is_active", false).Error
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package request
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type ProductSpecificationsQueryRequest struct {
|
||||
ProductID *uint `json:"product_id"`
|
||||
Title *string `json:"title"`
|
||||
Pagination *paginator.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
type ProductSpecificationsQueryRequestContext struct {
|
||||
ProductID string `json:"product_id"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
func (req ProductSpecificationsQueryRequestContext) ToParamRequest() ProductSpecificationsQueryRequest {
|
||||
var request ProductSpecificationsQueryRequest
|
||||
|
||||
if productIDStr := req.ProductID; productIDStr != "" {
|
||||
productID, err := strconv.Atoi(productIDStr)
|
||||
if err == nil {
|
||||
productIDUint := uint(productID)
|
||||
request.ProductID = &productIDUint
|
||||
}
|
||||
}
|
||||
if title := req.Title; title != "" {
|
||||
request.Title = &title
|
||||
}
|
||||
|
||||
return request
|
||||
}
|
||||
|
||||
type ProductSpecificationsCreateRequest struct {
|
||||
ProductID uint `json:"product_id" validate:"required"`
|
||||
Title string `json:"title" validate:"required"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
}
|
||||
|
||||
func (req ProductSpecificationsCreateRequest) ToEntity() *entity.ProductSpecifications {
|
||||
return &entity.ProductSpecifications{
|
||||
ProductID: req.ProductID,
|
||||
Title: req.Title,
|
||||
ThumbnailPath: req.ThumbnailPath,
|
||||
}
|
||||
}
|
||||
|
||||
type ProductSpecificationsUpdateRequest struct {
|
||||
ProductID *uint `json:"product_id"`
|
||||
Title *string `json:"title"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
}
|
||||
|
||||
func (req ProductSpecificationsUpdateRequest) ToEntity() *entity.ProductSpecifications {
|
||||
return &entity.ProductSpecifications{
|
||||
ProductID: getUintValue(req.ProductID),
|
||||
Title: getStringValue(req.Title),
|
||||
ThumbnailPath: req.ThumbnailPath,
|
||||
IsActive: req.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
func getStringValue(s *string) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
return *s
|
||||
}
|
||||
|
||||
func getUintValue(u *uint) uint {
|
||||
if u == nil {
|
||||
return 0
|
||||
}
|
||||
return *u
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package response
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type ProductSpecificationsResponse struct {
|
||||
ID uint `json:"id"`
|
||||
ProductID uint `json:"product_id"`
|
||||
Title string `json:"title"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
ThumbnailUrl *string `json:"thumbnail_url"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"jaecoo-be/app/module/product_specifications/mapper"
|
||||
"jaecoo-be/app/module/product_specifications/repository"
|
||||
"jaecoo-be/app/module/product_specifications/request"
|
||||
"jaecoo-be/app/module/product_specifications/response"
|
||||
"jaecoo-be/config/config"
|
||||
"jaecoo-be/utils/paginator"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type productSpecificationsService struct {
|
||||
Repo repository.ProductSpecificationsRepository
|
||||
Log zerolog.Logger
|
||||
Cfg *config.Config
|
||||
}
|
||||
|
||||
type ProductSpecificationsService interface {
|
||||
GetAll(req request.ProductSpecificationsQueryRequest) (specs []*response.ProductSpecificationsResponse, paging paginator.Pagination, err error)
|
||||
GetOne(id uint) (spec *response.ProductSpecificationsResponse, err error)
|
||||
Create(req request.ProductSpecificationsCreateRequest) (spec *response.ProductSpecificationsResponse, err error)
|
||||
Update(id uint, req request.ProductSpecificationsUpdateRequest) (spec *response.ProductSpecificationsResponse, err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewProductSpecificationsService(repo repository.ProductSpecificationsRepository, log zerolog.Logger, cfg *config.Config) ProductSpecificationsService {
|
||||
return &productSpecificationsService{
|
||||
Repo: repo,
|
||||
Log: log,
|
||||
Cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *productSpecificationsService) GetAll(req request.ProductSpecificationsQueryRequest) (specs []*response.ProductSpecificationsResponse, paging paginator.Pagination, err error) {
|
||||
specsEntity, paging, err := _i.Repo.GetAll(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
for _, spec := range specsEntity {
|
||||
specs = append(specs, mapper.ProductSpecificationsResponseMapper(spec, host))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productSpecificationsService) GetOne(id uint) (spec *response.ProductSpecificationsResponse, err error) {
|
||||
specEntity, err := _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if specEntity == nil {
|
||||
err = errors.New("product specification not found")
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
spec = mapper.ProductSpecificationsResponseMapper(specEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productSpecificationsService) Create(req request.ProductSpecificationsCreateRequest) (spec *response.ProductSpecificationsResponse, err error) {
|
||||
specEntity := req.ToEntity()
|
||||
isActive := true
|
||||
specEntity.IsActive = &isActive
|
||||
|
||||
specEntity, err = _i.Repo.Create(specEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
spec = mapper.ProductSpecificationsResponseMapper(specEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productSpecificationsService) Update(id uint, req request.ProductSpecificationsUpdateRequest) (spec *response.ProductSpecificationsResponse, err error) {
|
||||
specEntity := req.ToEntity()
|
||||
|
||||
err = _i.Repo.Update(id, specEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
specEntity, err = _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
spec = mapper.ProductSpecificationsResponseMapper(specEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productSpecificationsService) Delete(id uint) (err error) {
|
||||
err = _i.Repo.Delete(id)
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package controller
|
||||
|
||||
import "jaecoo-be/app/module/products/service"
|
||||
|
||||
type Controller struct {
|
||||
Products ProductsController
|
||||
}
|
||||
|
||||
func NewController(ProductsService service.ProductsService) *Controller {
|
||||
return &Controller{
|
||||
Products: NewProductsController(ProductsService),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/products/request"
|
||||
"jaecoo-be/app/module/products/service"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
utilRes "jaecoo-be/utils/response"
|
||||
utilVal "jaecoo-be/utils/validator"
|
||||
)
|
||||
|
||||
type productsController struct {
|
||||
productsService service.ProductsService
|
||||
}
|
||||
|
||||
type ProductsController interface {
|
||||
All(c *fiber.Ctx) error
|
||||
Show(c *fiber.Ctx) error
|
||||
Save(c *fiber.Ctx) error
|
||||
Update(c *fiber.Ctx) error
|
||||
Delete(c *fiber.Ctx) error
|
||||
}
|
||||
|
||||
func NewProductsController(productsService service.ProductsService) ProductsController {
|
||||
return &productsController{
|
||||
productsService: productsService,
|
||||
}
|
||||
}
|
||||
|
||||
// All Products
|
||||
// @Summary Get all Products
|
||||
// @Description API for getting all Products
|
||||
// @Tags Products
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param req query request.ProductsQueryRequestContext false "query parameters"
|
||||
// @Param req query paginator.Pagination false "pagination parameters"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /products [get]
|
||||
func (_i *productsController) All(c *fiber.Ctx) error {
|
||||
paginate, err := paginator.Paginate(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reqContext := request.ProductsQueryRequestContext{
|
||||
Title: c.Query("title"),
|
||||
Variant: c.Query("variant"),
|
||||
}
|
||||
req := reqContext.ToParamRequest()
|
||||
req.Pagination = paginate
|
||||
|
||||
productsData, paging, err := _i.productsService.GetAll(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Products list successfully retrieved"},
|
||||
Data: productsData,
|
||||
Meta: paging,
|
||||
})
|
||||
}
|
||||
|
||||
// Show Product
|
||||
// @Summary Get Product by ID
|
||||
// @Description API for getting Product by ID
|
||||
// @Tags Products
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Product ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /products/{id} [get]
|
||||
func (_i *productsController) Show(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
productData, err := _i.productsService.GetOne(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Product successfully retrieved"},
|
||||
Data: productData,
|
||||
})
|
||||
}
|
||||
|
||||
// Save Product
|
||||
// @Summary Create Product
|
||||
// @Description API for creating Product
|
||||
// @Tags Products
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param payload body request.ProductsCreateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /products [post]
|
||||
func (_i *productsController) Save(c *fiber.Ctx) error {
|
||||
req := new(request.ProductsCreateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.productsService.Create(*req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Product successfully created"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Update Product
|
||||
// @Summary Update Product
|
||||
// @Description API for updating Product
|
||||
// @Tags Products
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Product ID"
|
||||
// @Param payload body request.ProductsUpdateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /products/{id} [put]
|
||||
func (_i *productsController) Update(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := new(request.ProductsUpdateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.productsService.Update(uint(id), *req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Product successfully updated"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Delete Product
|
||||
// @Summary Delete Product
|
||||
// @Description API for deleting Product (soft delete)
|
||||
// @Tags Products
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Product ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /products/{id} [delete]
|
||||
func (_i *productsController) Delete(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = _i.productsService.Delete(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Product successfully deleted"},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package mapper
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"jaecoo-be/app/database/entity"
|
||||
res "jaecoo-be/app/module/products/response"
|
||||
)
|
||||
|
||||
func ProductsResponseMapper(product *entity.Products, host string) *res.ProductsResponse {
|
||||
if product == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var colors []string
|
||||
if product.Colors != nil && *product.Colors != "" {
|
||||
json.Unmarshal([]byte(*product.Colors), &colors)
|
||||
}
|
||||
|
||||
response := &res.ProductsResponse{
|
||||
ID: product.ID,
|
||||
Title: product.Title,
|
||||
Variant: product.Variant,
|
||||
Price: product.Price,
|
||||
ThumbnailPath: product.ThumbnailPath,
|
||||
Colors: colors,
|
||||
IsActive: product.IsActive,
|
||||
CreatedAt: product.CreatedAt,
|
||||
UpdatedAt: product.UpdatedAt,
|
||||
}
|
||||
|
||||
if product.ThumbnailPath != nil && *product.ThumbnailPath != "" {
|
||||
thumbnailUrl := host + "/products/thumbnail/viewer/" + *product.ThumbnailPath
|
||||
response.ThumbnailUrl = &thumbnailUrl
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package products
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/products/controller"
|
||||
"jaecoo-be/app/module/products/repository"
|
||||
"jaecoo-be/app/module/products/service"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
// ProductsRouter struct of ProductsRouter
|
||||
type ProductsRouter struct {
|
||||
App fiber.Router
|
||||
Controller *controller.Controller
|
||||
}
|
||||
|
||||
// NewProductsModule register bulky of Products module
|
||||
var NewProductsModule = fx.Options(
|
||||
// register repository of Products module
|
||||
fx.Provide(repository.NewProductsRepository),
|
||||
|
||||
// register service of Products module
|
||||
fx.Provide(service.NewProductsService),
|
||||
|
||||
// register controller of Products module
|
||||
fx.Provide(controller.NewController),
|
||||
|
||||
// register router of Products module
|
||||
fx.Provide(NewProductsRouter),
|
||||
)
|
||||
|
||||
// NewProductsRouter init ProductsRouter
|
||||
func NewProductsRouter(fiber *fiber.App, controller *controller.Controller) *ProductsRouter {
|
||||
return &ProductsRouter{
|
||||
App: fiber,
|
||||
Controller: controller,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterProductsRoutes register routes of Products module
|
||||
func (_i *ProductsRouter) RegisterProductsRoutes() {
|
||||
// define controllers
|
||||
productsController := _i.Controller.Products
|
||||
|
||||
// define routes
|
||||
_i.App.Route("/products", func(router fiber.Router) {
|
||||
router.Get("/", productsController.All)
|
||||
router.Get("/:id", productsController.Show)
|
||||
router.Post("/", productsController.Save)
|
||||
router.Put("/:id", productsController.Update)
|
||||
router.Delete("/:id", productsController.Delete)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database"
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/app/module/products/request"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type productsRepository struct {
|
||||
DB *database.Database
|
||||
Log zerolog.Logger
|
||||
}
|
||||
|
||||
type ProductsRepository interface {
|
||||
GetAll(req request.ProductsQueryRequest) (products []*entity.Products, paging paginator.Pagination, err error)
|
||||
FindOne(id uint) (product *entity.Products, err error)
|
||||
Create(product *entity.Products) (productReturn *entity.Products, err error)
|
||||
Update(id uint, product *entity.Products) (err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewProductsRepository(db *database.Database, log zerolog.Logger) ProductsRepository {
|
||||
return &productsRepository{
|
||||
DB: db,
|
||||
Log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *productsRepository) GetAll(req request.ProductsQueryRequest) (products []*entity.Products, paging paginator.Pagination, err error) {
|
||||
var count int64
|
||||
|
||||
query := _i.DB.DB.Model(&entity.Products{})
|
||||
|
||||
if req.Title != nil && *req.Title != "" {
|
||||
title := strings.ToLower(*req.Title)
|
||||
query = query.Where("LOWER(title) LIKE ?", "%"+title+"%")
|
||||
}
|
||||
|
||||
if req.Variant != nil && *req.Variant != "" {
|
||||
query = query.Where("variant = ?", *req.Variant)
|
||||
}
|
||||
|
||||
query = query.Where("is_active = ?", true)
|
||||
|
||||
query.Count(&count)
|
||||
|
||||
req.Pagination.Count = count
|
||||
req.Pagination = paginator.Paging(req.Pagination)
|
||||
|
||||
query = query.Order("created_at DESC")
|
||||
|
||||
err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&products).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
paging = *req.Pagination
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productsRepository) FindOne(id uint) (product *entity.Products, err error) {
|
||||
product = &entity.Products{}
|
||||
err = _i.DB.DB.Where("id = ? AND is_active = ?", id, true).First(product).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productsRepository) Create(product *entity.Products) (productReturn *entity.Products, err error) {
|
||||
if err = _i.DB.DB.Create(product).Error; err != nil {
|
||||
return
|
||||
}
|
||||
productReturn = product
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productsRepository) Update(id uint, product *entity.Products) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.Products{}).Where("id = ?", id).Updates(product).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productsRepository) Delete(id uint) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.Products{}).Where("id = ?", id).Update("is_active", false).Error
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package request
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/utils/paginator"
|
||||
)
|
||||
|
||||
type ProductsQueryRequest struct {
|
||||
Title *string `json:"title"`
|
||||
Variant *string `json:"variant"`
|
||||
Pagination *paginator.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
type ProductsQueryRequestContext struct {
|
||||
Title string `json:"title"`
|
||||
Variant string `json:"variant"`
|
||||
}
|
||||
|
||||
func (req ProductsQueryRequestContext) ToParamRequest() ProductsQueryRequest {
|
||||
var request ProductsQueryRequest
|
||||
|
||||
if title := req.Title; title != "" {
|
||||
request.Title = &title
|
||||
}
|
||||
if variant := req.Variant; variant != "" {
|
||||
request.Variant = &variant
|
||||
}
|
||||
|
||||
return request
|
||||
}
|
||||
|
||||
type ProductsCreateRequest struct {
|
||||
Title string `json:"title" validate:"required"`
|
||||
Variant *string `json:"variant"`
|
||||
Price *float64 `json:"price"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
Colors []string `json:"colors"`
|
||||
}
|
||||
|
||||
func (req ProductsCreateRequest) ToEntity() *entity.Products {
|
||||
colorsJSON, _ := json.Marshal(req.Colors)
|
||||
colorsStr := string(colorsJSON)
|
||||
if colorsStr == "null" {
|
||||
colorsStr = ""
|
||||
}
|
||||
|
||||
return &entity.Products{
|
||||
Title: req.Title,
|
||||
Variant: req.Variant,
|
||||
Price: req.Price,
|
||||
ThumbnailPath: req.ThumbnailPath,
|
||||
Colors: &colorsStr,
|
||||
}
|
||||
}
|
||||
|
||||
type ProductsUpdateRequest struct {
|
||||
Title *string `json:"title"`
|
||||
Variant *string `json:"variant"`
|
||||
Price *float64 `json:"price"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
Colors []string `json:"colors"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
}
|
||||
|
||||
func (req ProductsUpdateRequest) ToEntity() *entity.Products {
|
||||
colorsJSON, _ := json.Marshal(req.Colors)
|
||||
colorsStr := string(colorsJSON)
|
||||
if colorsStr == "null" {
|
||||
colorsStr = ""
|
||||
}
|
||||
|
||||
return &entity.Products{
|
||||
Title: getStringValue(req.Title),
|
||||
Variant: req.Variant,
|
||||
Price: req.Price,
|
||||
ThumbnailPath: req.ThumbnailPath,
|
||||
Colors: &colorsStr,
|
||||
IsActive: req.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
func getStringValue(s *string) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
return *s
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package response
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type ProductsResponse struct {
|
||||
ID uint `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Variant *string `json:"variant"`
|
||||
Price *float64 `json:"price"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
ThumbnailUrl *string `json:"thumbnail_url"`
|
||||
Colors []string `json:"colors"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"jaecoo-be/app/module/products/mapper"
|
||||
"jaecoo-be/app/module/products/repository"
|
||||
"jaecoo-be/app/module/products/request"
|
||||
"jaecoo-be/app/module/products/response"
|
||||
"jaecoo-be/config/config"
|
||||
"jaecoo-be/utils/paginator"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type productsService struct {
|
||||
Repo repository.ProductsRepository
|
||||
Log zerolog.Logger
|
||||
Cfg *config.Config
|
||||
}
|
||||
|
||||
type ProductsService interface {
|
||||
GetAll(req request.ProductsQueryRequest) (products []*response.ProductsResponse, paging paginator.Pagination, err error)
|
||||
GetOne(id uint) (product *response.ProductsResponse, err error)
|
||||
Create(req request.ProductsCreateRequest) (product *response.ProductsResponse, err error)
|
||||
Update(id uint, req request.ProductsUpdateRequest) (product *response.ProductsResponse, err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewProductsService(repo repository.ProductsRepository, log zerolog.Logger, cfg *config.Config) ProductsService {
|
||||
return &productsService{
|
||||
Repo: repo,
|
||||
Log: log,
|
||||
Cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *productsService) GetAll(req request.ProductsQueryRequest) (products []*response.ProductsResponse, paging paginator.Pagination, err error) {
|
||||
productsEntity, paging, err := _i.Repo.GetAll(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
for _, product := range productsEntity {
|
||||
products = append(products, mapper.ProductsResponseMapper(product, host))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productsService) GetOne(id uint) (product *response.ProductsResponse, err error) {
|
||||
productEntity, err := _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if productEntity == nil {
|
||||
err = errors.New("product not found")
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
product = mapper.ProductsResponseMapper(productEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productsService) Create(req request.ProductsCreateRequest) (product *response.ProductsResponse, err error) {
|
||||
productEntity := req.ToEntity()
|
||||
isActive := true
|
||||
productEntity.IsActive = &isActive
|
||||
|
||||
productEntity, err = _i.Repo.Create(productEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
product = mapper.ProductsResponseMapper(productEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productsService) Update(id uint, req request.ProductsUpdateRequest) (product *response.ProductsResponse, err error) {
|
||||
productEntity := req.ToEntity()
|
||||
|
||||
err = _i.Repo.Update(id, productEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
productEntity, err = _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
product = mapper.ProductsResponseMapper(productEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *productsService) Delete(id uint) (err error) {
|
||||
err = _i.Repo.Delete(id)
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package controller
|
||||
|
||||
import "jaecoo-be/app/module/promotions/service"
|
||||
|
||||
type Controller struct {
|
||||
Promotions PromotionsController
|
||||
}
|
||||
|
||||
func NewController(PromotionsService service.PromotionsService) *Controller {
|
||||
return &Controller{
|
||||
Promotions: NewPromotionsController(PromotionsService),
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/promotions/request"
|
||||
"jaecoo-be/app/module/promotions/service"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
utilRes "jaecoo-be/utils/response"
|
||||
utilVal "jaecoo-be/utils/validator"
|
||||
)
|
||||
|
||||
type promotionsController struct {
|
||||
promotionsService service.PromotionsService
|
||||
}
|
||||
|
||||
type PromotionsController interface {
|
||||
All(c *fiber.Ctx) error
|
||||
Show(c *fiber.Ctx) error
|
||||
Save(c *fiber.Ctx) error
|
||||
Update(c *fiber.Ctx) error
|
||||
Delete(c *fiber.Ctx) error
|
||||
}
|
||||
|
||||
func NewPromotionsController(promotionsService service.PromotionsService) PromotionsController {
|
||||
return &promotionsController{
|
||||
promotionsService: promotionsService,
|
||||
}
|
||||
}
|
||||
|
||||
// All Promotions
|
||||
// @Summary Get all Promotions
|
||||
// @Description API for getting all Promotions
|
||||
// @Tags Promotions
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param req query request.PromotionsQueryRequestContext false "query parameters"
|
||||
// @Param req query paginator.Pagination false "pagination parameters"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /promotions [get]
|
||||
func (_i *promotionsController) All(c *fiber.Ctx) error {
|
||||
paginate, err := paginator.Paginate(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reqContext := request.PromotionsQueryRequestContext{
|
||||
Title: c.Query("title"),
|
||||
}
|
||||
req := reqContext.ToParamRequest()
|
||||
req.Pagination = paginate
|
||||
|
||||
promotionsData, paging, err := _i.promotionsService.GetAll(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Promotions list successfully retrieved"},
|
||||
Data: promotionsData,
|
||||
Meta: paging,
|
||||
})
|
||||
}
|
||||
|
||||
// Show Promotion
|
||||
// @Summary Get Promotion by ID
|
||||
// @Description API for getting Promotion by ID
|
||||
// @Tags Promotions
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Promotion ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /promotions/{id} [get]
|
||||
func (_i *promotionsController) Show(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
promotionData, err := _i.promotionsService.GetOne(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Promotion successfully retrieved"},
|
||||
Data: promotionData,
|
||||
})
|
||||
}
|
||||
|
||||
// Save Promotion
|
||||
// @Summary Create Promotion
|
||||
// @Description API for creating Promotion
|
||||
// @Tags Promotions
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param payload body request.PromotionsCreateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /promotions [post]
|
||||
func (_i *promotionsController) Save(c *fiber.Ctx) error {
|
||||
req := new(request.PromotionsCreateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.promotionsService.Create(*req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Promotion successfully created"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Update Promotion
|
||||
// @Summary Update Promotion
|
||||
// @Description API for updating Promotion
|
||||
// @Tags Promotions
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Promotion ID"
|
||||
// @Param payload body request.PromotionsUpdateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /promotions/{id} [put]
|
||||
func (_i *promotionsController) Update(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := new(request.PromotionsUpdateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.promotionsService.Update(uint(id), *req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Promotion successfully updated"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Delete Promotion
|
||||
// @Summary Delete Promotion
|
||||
// @Description API for deleting Promotion (soft delete)
|
||||
// @Tags Promotions
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "Promotion ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /promotions/{id} [delete]
|
||||
func (_i *promotionsController) Delete(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = _i.promotionsService.Delete(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"Promotion successfully deleted"},
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package mapper
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database/entity"
|
||||
res "jaecoo-be/app/module/promotions/response"
|
||||
)
|
||||
|
||||
func PromotionsResponseMapper(promotion *entity.Promotions, host string) *res.PromotionsResponse {
|
||||
if promotion == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
response := &res.PromotionsResponse{
|
||||
ID: promotion.ID,
|
||||
Title: promotion.Title,
|
||||
Description: promotion.Description,
|
||||
ThumbnailPath: promotion.ThumbnailPath,
|
||||
IsActive: promotion.IsActive,
|
||||
CreatedAt: promotion.CreatedAt,
|
||||
UpdatedAt: promotion.UpdatedAt,
|
||||
}
|
||||
|
||||
if promotion.ThumbnailPath != nil && *promotion.ThumbnailPath != "" {
|
||||
thumbnailUrl := host + "/promotions/thumbnail/viewer/" + *promotion.ThumbnailPath
|
||||
response.ThumbnailUrl = &thumbnailUrl
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package promotions
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/promotions/controller"
|
||||
"jaecoo-be/app/module/promotions/repository"
|
||||
"jaecoo-be/app/module/promotions/service"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
// PromotionsRouter struct of PromotionsRouter
|
||||
type PromotionsRouter struct {
|
||||
App fiber.Router
|
||||
Controller *controller.Controller
|
||||
}
|
||||
|
||||
// NewPromotionsModule register bulky of Promotions module
|
||||
var NewPromotionsModule = fx.Options(
|
||||
// register repository of Promotions module
|
||||
fx.Provide(repository.NewPromotionsRepository),
|
||||
|
||||
// register service of Promotions module
|
||||
fx.Provide(service.NewPromotionsService),
|
||||
|
||||
// register controller of Promotions module
|
||||
fx.Provide(controller.NewController),
|
||||
|
||||
// register router of Promotions module
|
||||
fx.Provide(NewPromotionsRouter),
|
||||
)
|
||||
|
||||
// NewPromotionsRouter init PromotionsRouter
|
||||
func NewPromotionsRouter(fiber *fiber.App, controller *controller.Controller) *PromotionsRouter {
|
||||
return &PromotionsRouter{
|
||||
App: fiber,
|
||||
Controller: controller,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterPromotionsRoutes register routes of Promotions module
|
||||
func (_i *PromotionsRouter) RegisterPromotionsRoutes() {
|
||||
// define controllers
|
||||
promotionsController := _i.Controller.Promotions
|
||||
|
||||
// define routes
|
||||
_i.App.Route("/promotions", func(router fiber.Router) {
|
||||
router.Get("/", promotionsController.All)
|
||||
router.Get("/:id", promotionsController.Show)
|
||||
router.Post("/", promotionsController.Save)
|
||||
router.Put("/:id", promotionsController.Update)
|
||||
router.Delete("/:id", promotionsController.Delete)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database"
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/app/module/promotions/request"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type promotionsRepository struct {
|
||||
DB *database.Database
|
||||
Log zerolog.Logger
|
||||
}
|
||||
|
||||
type PromotionsRepository interface {
|
||||
GetAll(req request.PromotionsQueryRequest) (promotions []*entity.Promotions, paging paginator.Pagination, err error)
|
||||
FindOne(id uint) (promotion *entity.Promotions, err error)
|
||||
Create(promotion *entity.Promotions) (promotionReturn *entity.Promotions, err error)
|
||||
Update(id uint, promotion *entity.Promotions) (err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewPromotionsRepository(db *database.Database, log zerolog.Logger) PromotionsRepository {
|
||||
return &promotionsRepository{
|
||||
DB: db,
|
||||
Log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *promotionsRepository) GetAll(req request.PromotionsQueryRequest) (promotions []*entity.Promotions, paging paginator.Pagination, err error) {
|
||||
var count int64
|
||||
|
||||
query := _i.DB.DB.Model(&entity.Promotions{})
|
||||
|
||||
if req.Title != nil && *req.Title != "" {
|
||||
title := strings.ToLower(*req.Title)
|
||||
query = query.Where("LOWER(title) LIKE ?", "%"+title+"%")
|
||||
}
|
||||
|
||||
query = query.Where("is_active = ?", true)
|
||||
|
||||
query.Count(&count)
|
||||
|
||||
req.Pagination.Count = count
|
||||
req.Pagination = paginator.Paging(req.Pagination)
|
||||
|
||||
query = query.Order("created_at DESC")
|
||||
|
||||
err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&promotions).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
paging = *req.Pagination
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *promotionsRepository) FindOne(id uint) (promotion *entity.Promotions, err error) {
|
||||
promotion = &entity.Promotions{}
|
||||
err = _i.DB.DB.Where("id = ? AND is_active = ?", id, true).First(promotion).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *promotionsRepository) Create(promotion *entity.Promotions) (promotionReturn *entity.Promotions, err error) {
|
||||
if err = _i.DB.DB.Create(promotion).Error; err != nil {
|
||||
return
|
||||
}
|
||||
promotionReturn = promotion
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *promotionsRepository) Update(id uint, promotion *entity.Promotions) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.Promotions{}).Where("id = ?", id).Updates(promotion).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *promotionsRepository) Delete(id uint) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.Promotions{}).Where("id = ?", id).Update("is_active", false).Error
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package request
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/utils/paginator"
|
||||
)
|
||||
|
||||
type PromotionsQueryRequest struct {
|
||||
Title *string `json:"title"`
|
||||
Pagination *paginator.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
type PromotionsQueryRequestContext struct {
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
func (req PromotionsQueryRequestContext) ToParamRequest() PromotionsQueryRequest {
|
||||
var request PromotionsQueryRequest
|
||||
|
||||
if title := req.Title; title != "" {
|
||||
request.Title = &title
|
||||
}
|
||||
|
||||
return request
|
||||
}
|
||||
|
||||
type PromotionsCreateRequest struct {
|
||||
Title string `json:"title" validate:"required"`
|
||||
Description *string `json:"description"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
}
|
||||
|
||||
func (req PromotionsCreateRequest) ToEntity() *entity.Promotions {
|
||||
return &entity.Promotions{
|
||||
Title: req.Title,
|
||||
Description: req.Description,
|
||||
ThumbnailPath: req.ThumbnailPath,
|
||||
}
|
||||
}
|
||||
|
||||
type PromotionsUpdateRequest struct {
|
||||
Title *string `json:"title"`
|
||||
Description *string `json:"description"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
}
|
||||
|
||||
func (req PromotionsUpdateRequest) ToEntity() *entity.Promotions {
|
||||
return &entity.Promotions{
|
||||
Title: getStringValue(req.Title),
|
||||
Description: req.Description,
|
||||
ThumbnailPath: req.ThumbnailPath,
|
||||
IsActive: req.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
func getStringValue(s *string) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
return *s
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package response
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type PromotionsResponse struct {
|
||||
ID uint `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description *string `json:"description"`
|
||||
ThumbnailPath *string `json:"thumbnail_path"`
|
||||
ThumbnailUrl *string `json:"thumbnail_url"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"jaecoo-be/app/module/promotions/mapper"
|
||||
"jaecoo-be/app/module/promotions/repository"
|
||||
"jaecoo-be/app/module/promotions/request"
|
||||
"jaecoo-be/app/module/promotions/response"
|
||||
"jaecoo-be/config/config"
|
||||
"jaecoo-be/utils/paginator"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type promotionsService struct {
|
||||
Repo repository.PromotionsRepository
|
||||
Log zerolog.Logger
|
||||
Cfg *config.Config
|
||||
}
|
||||
|
||||
type PromotionsService interface {
|
||||
GetAll(req request.PromotionsQueryRequest) (promotions []*response.PromotionsResponse, paging paginator.Pagination, err error)
|
||||
GetOne(id uint) (promotion *response.PromotionsResponse, err error)
|
||||
Create(req request.PromotionsCreateRequest) (promotion *response.PromotionsResponse, err error)
|
||||
Update(id uint, req request.PromotionsUpdateRequest) (promotion *response.PromotionsResponse, err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewPromotionsService(repo repository.PromotionsRepository, log zerolog.Logger, cfg *config.Config) PromotionsService {
|
||||
return &promotionsService{
|
||||
Repo: repo,
|
||||
Log: log,
|
||||
Cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *promotionsService) GetAll(req request.PromotionsQueryRequest) (promotions []*response.PromotionsResponse, paging paginator.Pagination, err error) {
|
||||
promotionsEntity, paging, err := _i.Repo.GetAll(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
for _, promotion := range promotionsEntity {
|
||||
promotions = append(promotions, mapper.PromotionsResponseMapper(promotion, host))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *promotionsService) GetOne(id uint) (promotion *response.PromotionsResponse, err error) {
|
||||
promotionEntity, err := _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if promotionEntity == nil {
|
||||
err = errors.New("promotion not found")
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
promotion = mapper.PromotionsResponseMapper(promotionEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *promotionsService) Create(req request.PromotionsCreateRequest) (promotion *response.PromotionsResponse, err error) {
|
||||
promotionEntity := req.ToEntity()
|
||||
isActive := true
|
||||
promotionEntity.IsActive = &isActive
|
||||
|
||||
promotionEntity, err = _i.Repo.Create(promotionEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
promotion = mapper.PromotionsResponseMapper(promotionEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *promotionsService) Update(id uint, req request.PromotionsUpdateRequest) (promotion *response.PromotionsResponse, err error) {
|
||||
promotionEntity := req.ToEntity()
|
||||
|
||||
err = _i.Repo.Update(id, promotionEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
promotionEntity, err = _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
promotion = mapper.PromotionsResponseMapper(promotionEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *promotionsService) Delete(id uint) (err error) {
|
||||
err = _i.Repo.Delete(id)
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package controller
|
||||
|
||||
import "jaecoo-be/app/module/sales_agents/service"
|
||||
|
||||
type Controller struct {
|
||||
SalesAgents SalesAgentsController
|
||||
}
|
||||
|
||||
func NewController(SalesAgentsService service.SalesAgentsService) *Controller {
|
||||
return &Controller{
|
||||
SalesAgents: NewSalesAgentsController(SalesAgentsService),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/sales_agents/request"
|
||||
"jaecoo-be/app/module/sales_agents/service"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
utilRes "jaecoo-be/utils/response"
|
||||
utilVal "jaecoo-be/utils/validator"
|
||||
)
|
||||
|
||||
type salesAgentsController struct {
|
||||
salesAgentsService service.SalesAgentsService
|
||||
}
|
||||
|
||||
type SalesAgentsController interface {
|
||||
All(c *fiber.Ctx) error
|
||||
Show(c *fiber.Ctx) error
|
||||
Save(c *fiber.Ctx) error
|
||||
Update(c *fiber.Ctx) error
|
||||
Delete(c *fiber.Ctx) error
|
||||
}
|
||||
|
||||
func NewSalesAgentsController(salesAgentsService service.SalesAgentsService) SalesAgentsController {
|
||||
return &salesAgentsController{
|
||||
salesAgentsService: salesAgentsService,
|
||||
}
|
||||
}
|
||||
|
||||
// All SalesAgents
|
||||
// @Summary Get all SalesAgents
|
||||
// @Description API for getting all SalesAgents
|
||||
// @Tags SalesAgents
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param req query request.SalesAgentsQueryRequestContext false "query parameters"
|
||||
// @Param req query paginator.Pagination false "pagination parameters"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /sales-agents [get]
|
||||
func (_i *salesAgentsController) All(c *fiber.Ctx) error {
|
||||
paginate, err := paginator.Paginate(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reqContext := request.SalesAgentsQueryRequestContext{
|
||||
Name: c.Query("name"),
|
||||
JobTitle: c.Query("job_title"),
|
||||
AgentType: c.Query("agent_type"),
|
||||
}
|
||||
req := reqContext.ToParamRequest()
|
||||
req.Pagination = paginate
|
||||
|
||||
agentsData, paging, err := _i.salesAgentsService.GetAll(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"SalesAgents list successfully retrieved"},
|
||||
Data: agentsData,
|
||||
Meta: paging,
|
||||
})
|
||||
}
|
||||
|
||||
// Show SalesAgent
|
||||
// @Summary Get SalesAgent by ID
|
||||
// @Description API for getting SalesAgent by ID
|
||||
// @Tags SalesAgents
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "SalesAgent ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /sales-agents/{id} [get]
|
||||
func (_i *salesAgentsController) Show(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
agentData, err := _i.salesAgentsService.GetOne(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"SalesAgent successfully retrieved"},
|
||||
Data: agentData,
|
||||
})
|
||||
}
|
||||
|
||||
// Save SalesAgent
|
||||
// @Summary Create SalesAgent
|
||||
// @Description API for creating SalesAgent
|
||||
// @Tags SalesAgents
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param payload body request.SalesAgentsCreateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /sales-agents [post]
|
||||
func (_i *salesAgentsController) Save(c *fiber.Ctx) error {
|
||||
req := new(request.SalesAgentsCreateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.salesAgentsService.Create(*req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"SalesAgent successfully created"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Update SalesAgent
|
||||
// @Summary Update SalesAgent
|
||||
// @Description API for updating SalesAgent
|
||||
// @Tags SalesAgents
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "SalesAgent ID"
|
||||
// @Param payload body request.SalesAgentsUpdateRequest true "Required payload"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /sales-agents/{id} [put]
|
||||
func (_i *salesAgentsController) Update(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := new(request.SalesAgentsUpdateRequest)
|
||||
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dataResult, err := _i.salesAgentsService.Update(uint(id), *req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"SalesAgent successfully updated"},
|
||||
Data: dataResult,
|
||||
})
|
||||
}
|
||||
|
||||
// Delete SalesAgent
|
||||
// @Summary Delete SalesAgent
|
||||
// @Description API for deleting SalesAgent (soft delete)
|
||||
// @Tags SalesAgents
|
||||
// @Security Bearer
|
||||
// @Param X-Client-Key header string true "Insert the X-Client-Key"
|
||||
// @Param id path int true "SalesAgent ID"
|
||||
// @Success 200 {object} response.Response
|
||||
// @Failure 400 {object} response.BadRequestError
|
||||
// @Failure 401 {object} response.UnauthorizedError
|
||||
// @Failure 500 {object} response.InternalServerError
|
||||
// @Router /sales-agents/{id} [delete]
|
||||
func (_i *salesAgentsController) Delete(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = _i.salesAgentsService.Delete(uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utilRes.Resp(c, utilRes.Response{
|
||||
Success: true,
|
||||
Messages: utilRes.Messages{"SalesAgent successfully deleted"},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package mapper
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"jaecoo-be/app/database/entity"
|
||||
res "jaecoo-be/app/module/sales_agents/response"
|
||||
)
|
||||
|
||||
func SalesAgentsResponseMapper(agent *entity.SalesAgents, host string) *res.SalesAgentsResponse {
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var agentType []string
|
||||
if agent.AgentType != nil && *agent.AgentType != "" {
|
||||
json.Unmarshal([]byte(*agent.AgentType), &agentType)
|
||||
}
|
||||
|
||||
response := &res.SalesAgentsResponse{
|
||||
ID: agent.ID,
|
||||
Name: agent.Name,
|
||||
JobTitle: agent.JobTitle,
|
||||
Phone: agent.Phone,
|
||||
AgentType: agentType,
|
||||
ProfilePicturePath: agent.ProfilePicturePath,
|
||||
IsActive: agent.IsActive,
|
||||
CreatedAt: agent.CreatedAt,
|
||||
UpdatedAt: agent.UpdatedAt,
|
||||
}
|
||||
|
||||
if agent.ProfilePicturePath != nil && *agent.ProfilePicturePath != "" {
|
||||
profilePictureUrl := host + "/sales-agents/profile-picture/viewer/" + *agent.ProfilePicturePath
|
||||
response.ProfilePictureUrl = &profilePictureUrl
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/database"
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/app/module/sales_agents/request"
|
||||
"jaecoo-be/utils/paginator"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type salesAgentsRepository struct {
|
||||
DB *database.Database
|
||||
Log zerolog.Logger
|
||||
}
|
||||
|
||||
type SalesAgentsRepository interface {
|
||||
GetAll(req request.SalesAgentsQueryRequest) (agents []*entity.SalesAgents, paging paginator.Pagination, err error)
|
||||
FindOne(id uint) (agent *entity.SalesAgents, err error)
|
||||
Create(agent *entity.SalesAgents) (agentReturn *entity.SalesAgents, err error)
|
||||
Update(id uint, agent *entity.SalesAgents) (err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewSalesAgentsRepository(db *database.Database, log zerolog.Logger) SalesAgentsRepository {
|
||||
return &salesAgentsRepository{
|
||||
DB: db,
|
||||
Log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *salesAgentsRepository) GetAll(req request.SalesAgentsQueryRequest) (agents []*entity.SalesAgents, paging paginator.Pagination, err error) {
|
||||
var count int64
|
||||
|
||||
query := _i.DB.DB.Model(&entity.SalesAgents{})
|
||||
|
||||
if req.Name != nil && *req.Name != "" {
|
||||
name := strings.ToLower(*req.Name)
|
||||
query = query.Where("LOWER(name) LIKE ?", "%"+name+"%")
|
||||
}
|
||||
|
||||
if req.JobTitle != nil && *req.JobTitle != "" {
|
||||
query = query.Where("job_title = ?", *req.JobTitle)
|
||||
}
|
||||
|
||||
if req.AgentType != nil && *req.AgentType != "" {
|
||||
query = query.Where("agent_type LIKE ?", "%"+*req.AgentType+"%")
|
||||
}
|
||||
|
||||
query = query.Where("is_active = ?", true)
|
||||
|
||||
query.Count(&count)
|
||||
|
||||
req.Pagination.Count = count
|
||||
req.Pagination = paginator.Paging(req.Pagination)
|
||||
|
||||
query = query.Order("created_at DESC")
|
||||
|
||||
err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&agents).Error
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
paging = *req.Pagination
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *salesAgentsRepository) FindOne(id uint) (agent *entity.SalesAgents, err error) {
|
||||
agent = &entity.SalesAgents{}
|
||||
err = _i.DB.DB.Where("id = ? AND is_active = ?", id, true).First(agent).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *salesAgentsRepository) Create(agent *entity.SalesAgents) (agentReturn *entity.SalesAgents, err error) {
|
||||
if err = _i.DB.DB.Create(agent).Error; err != nil {
|
||||
return
|
||||
}
|
||||
agentReturn = agent
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *salesAgentsRepository) Update(id uint, agent *entity.SalesAgents) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.SalesAgents{}).Where("id = ?", id).Updates(agent).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *salesAgentsRepository) Delete(id uint) (err error) {
|
||||
err = _i.DB.DB.Model(&entity.SalesAgents{}).Where("id = ?", id).Update("is_active", false).Error
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package request
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"jaecoo-be/app/database/entity"
|
||||
"jaecoo-be/utils/paginator"
|
||||
)
|
||||
|
||||
type SalesAgentsQueryRequest struct {
|
||||
Name *string `json:"name"`
|
||||
JobTitle *string `json:"job_title"`
|
||||
AgentType *string `json:"agent_type"`
|
||||
Pagination *paginator.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
type SalesAgentsQueryRequestContext struct {
|
||||
Name string `json:"name"`
|
||||
JobTitle string `json:"job_title"`
|
||||
AgentType string `json:"agent_type"`
|
||||
}
|
||||
|
||||
func (req SalesAgentsQueryRequestContext) ToParamRequest() SalesAgentsQueryRequest {
|
||||
var request SalesAgentsQueryRequest
|
||||
|
||||
if name := req.Name; name != "" {
|
||||
request.Name = &name
|
||||
}
|
||||
if jobTitle := req.JobTitle; jobTitle != "" {
|
||||
request.JobTitle = &jobTitle
|
||||
}
|
||||
if agentType := req.AgentType; agentType != "" {
|
||||
request.AgentType = &agentType
|
||||
}
|
||||
|
||||
return request
|
||||
}
|
||||
|
||||
type SalesAgentsCreateRequest struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
JobTitle *string `json:"job_title"`
|
||||
Phone *string `json:"phone"`
|
||||
AgentType []string `json:"agent_type"`
|
||||
ProfilePicturePath *string `json:"profile_picture_path"`
|
||||
}
|
||||
|
||||
func (req SalesAgentsCreateRequest) ToEntity() *entity.SalesAgents {
|
||||
agentTypeJSON, _ := json.Marshal(req.AgentType)
|
||||
agentTypeStr := string(agentTypeJSON)
|
||||
if agentTypeStr == "null" {
|
||||
agentTypeStr = ""
|
||||
}
|
||||
|
||||
return &entity.SalesAgents{
|
||||
Name: req.Name,
|
||||
JobTitle: req.JobTitle,
|
||||
Phone: req.Phone,
|
||||
AgentType: &agentTypeStr,
|
||||
ProfilePicturePath: req.ProfilePicturePath,
|
||||
}
|
||||
}
|
||||
|
||||
type SalesAgentsUpdateRequest struct {
|
||||
Name *string `json:"name"`
|
||||
JobTitle *string `json:"job_title"`
|
||||
Phone *string `json:"phone"`
|
||||
AgentType []string `json:"agent_type"`
|
||||
ProfilePicturePath *string `json:"profile_picture_path"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
}
|
||||
|
||||
func (req SalesAgentsUpdateRequest) ToEntity() *entity.SalesAgents {
|
||||
agentTypeJSON, _ := json.Marshal(req.AgentType)
|
||||
agentTypeStr := string(agentTypeJSON)
|
||||
if agentTypeStr == "null" {
|
||||
agentTypeStr = ""
|
||||
}
|
||||
|
||||
return &entity.SalesAgents{
|
||||
Name: getStringValue(req.Name),
|
||||
JobTitle: req.JobTitle,
|
||||
Phone: req.Phone,
|
||||
AgentType: &agentTypeStr,
|
||||
ProfilePicturePath: req.ProfilePicturePath,
|
||||
IsActive: req.IsActive,
|
||||
}
|
||||
}
|
||||
|
||||
func getStringValue(s *string) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
return *s
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package response
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type SalesAgentsResponse struct {
|
||||
ID uint `json:"id"`
|
||||
Name string `json:"name"`
|
||||
JobTitle *string `json:"job_title"`
|
||||
Phone *string `json:"phone"`
|
||||
AgentType []string `json:"agent_type"`
|
||||
ProfilePicturePath *string `json:"profile_picture_path"`
|
||||
ProfilePictureUrl *string `json:"profile_picture_url"`
|
||||
IsActive *bool `json:"is_active"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package sales_agents
|
||||
|
||||
import (
|
||||
"jaecoo-be/app/module/sales_agents/controller"
|
||||
"jaecoo-be/app/module/sales_agents/repository"
|
||||
"jaecoo-be/app/module/sales_agents/service"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
// SalesAgentsRouter struct of SalesAgentsRouter
|
||||
type SalesAgentsRouter struct {
|
||||
App fiber.Router
|
||||
Controller *controller.Controller
|
||||
}
|
||||
|
||||
// NewSalesAgentsModule register bulky of SalesAgents module
|
||||
var NewSalesAgentsModule = fx.Options(
|
||||
// register repository of SalesAgents module
|
||||
fx.Provide(repository.NewSalesAgentsRepository),
|
||||
|
||||
// register service of SalesAgents module
|
||||
fx.Provide(service.NewSalesAgentsService),
|
||||
|
||||
// register controller of SalesAgents module
|
||||
fx.Provide(controller.NewController),
|
||||
|
||||
// register router of SalesAgents module
|
||||
fx.Provide(NewSalesAgentsRouter),
|
||||
)
|
||||
|
||||
// NewSalesAgentsRouter init SalesAgentsRouter
|
||||
func NewSalesAgentsRouter(fiber *fiber.App, controller *controller.Controller) *SalesAgentsRouter {
|
||||
return &SalesAgentsRouter{
|
||||
App: fiber,
|
||||
Controller: controller,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterSalesAgentsRoutes register routes of SalesAgents module
|
||||
func (_i *SalesAgentsRouter) RegisterSalesAgentsRoutes() {
|
||||
// define controllers
|
||||
salesAgentsController := _i.Controller.SalesAgents
|
||||
|
||||
// define routes
|
||||
_i.App.Route("/sales-agents", func(router fiber.Router) {
|
||||
router.Get("/", salesAgentsController.All)
|
||||
router.Get("/:id", salesAgentsController.Show)
|
||||
router.Post("/", salesAgentsController.Save)
|
||||
router.Put("/:id", salesAgentsController.Update)
|
||||
router.Delete("/:id", salesAgentsController.Delete)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"jaecoo-be/app/module/sales_agents/mapper"
|
||||
"jaecoo-be/app/module/sales_agents/repository"
|
||||
"jaecoo-be/app/module/sales_agents/request"
|
||||
"jaecoo-be/app/module/sales_agents/response"
|
||||
"jaecoo-be/config/config"
|
||||
"jaecoo-be/utils/paginator"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type salesAgentsService struct {
|
||||
Repo repository.SalesAgentsRepository
|
||||
Log zerolog.Logger
|
||||
Cfg *config.Config
|
||||
}
|
||||
|
||||
type SalesAgentsService interface {
|
||||
GetAll(req request.SalesAgentsQueryRequest) (agents []*response.SalesAgentsResponse, paging paginator.Pagination, err error)
|
||||
GetOne(id uint) (agent *response.SalesAgentsResponse, err error)
|
||||
Create(req request.SalesAgentsCreateRequest) (agent *response.SalesAgentsResponse, err error)
|
||||
Update(id uint, req request.SalesAgentsUpdateRequest) (agent *response.SalesAgentsResponse, err error)
|
||||
Delete(id uint) (err error)
|
||||
}
|
||||
|
||||
func NewSalesAgentsService(repo repository.SalesAgentsRepository, log zerolog.Logger, cfg *config.Config) SalesAgentsService {
|
||||
return &salesAgentsService{
|
||||
Repo: repo,
|
||||
Log: log,
|
||||
Cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (_i *salesAgentsService) GetAll(req request.SalesAgentsQueryRequest) (agents []*response.SalesAgentsResponse, paging paginator.Pagination, err error) {
|
||||
agentsEntity, paging, err := _i.Repo.GetAll(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
for _, agent := range agentsEntity {
|
||||
agents = append(agents, mapper.SalesAgentsResponseMapper(agent, host))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *salesAgentsService) GetOne(id uint) (agent *response.SalesAgentsResponse, err error) {
|
||||
agentEntity, err := _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if agentEntity == nil {
|
||||
err = errors.New("sales agent not found")
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
agent = mapper.SalesAgentsResponseMapper(agentEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *salesAgentsService) Create(req request.SalesAgentsCreateRequest) (agent *response.SalesAgentsResponse, err error) {
|
||||
agentEntity := req.ToEntity()
|
||||
isActive := true
|
||||
agentEntity.IsActive = &isActive
|
||||
|
||||
agentEntity, err = _i.Repo.Create(agentEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
agent = mapper.SalesAgentsResponseMapper(agentEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *salesAgentsService) Update(id uint, req request.SalesAgentsUpdateRequest) (agent *response.SalesAgentsResponse, err error) {
|
||||
agentEntity := req.ToEntity()
|
||||
|
||||
err = _i.Repo.Update(id, agentEntity)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
agentEntity, err = _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
host := _i.Cfg.App.Domain
|
||||
|
||||
agent = mapper.SalesAgentsResponseMapper(agentEntity, host)
|
||||
return
|
||||
}
|
||||
|
||||
func (_i *salesAgentsService) Delete(id uint) (err error) {
|
||||
err = _i.Repo.Delete(id)
|
||||
return
|
||||
}
|
||||
|
|
@ -8,11 +8,18 @@ import (
|
|||
"jaecoo-be/app/module/article_comments"
|
||||
"jaecoo-be/app/module/article_files"
|
||||
"jaecoo-be/app/module/articles"
|
||||
"jaecoo-be/app/module/banners"
|
||||
"jaecoo-be/app/module/cities"
|
||||
"jaecoo-be/app/module/custom_static_pages"
|
||||
"jaecoo-be/app/module/districts"
|
||||
"jaecoo-be/app/module/feedbacks"
|
||||
"jaecoo-be/app/module/galleries"
|
||||
"jaecoo-be/app/module/gallery_files"
|
||||
"jaecoo-be/app/module/product_specifications"
|
||||
"jaecoo-be/app/module/products"
|
||||
"jaecoo-be/app/module/promotions"
|
||||
"jaecoo-be/app/module/provinces"
|
||||
"jaecoo-be/app/module/sales_agents"
|
||||
"jaecoo-be/app/module/user_levels"
|
||||
"jaecoo-be/app/module/user_role_accesses"
|
||||
"jaecoo-be/app/module/user_roles"
|
||||
|
|
@ -35,11 +42,18 @@ type Router struct {
|
|||
ArticleCommentsRouter *article_comments.ArticleCommentsRouter
|
||||
ArticleApprovalsRouter *article_approvals.ArticleApprovalsRouter
|
||||
ArticlesRouter *articles.ArticlesRouter
|
||||
BannersRouter *banners.BannersRouter
|
||||
CitiesRouter *cities.CitiesRouter
|
||||
CustomStaticPagesRouter *custom_static_pages.CustomStaticPagesRouter
|
||||
DistrictsRouter *districts.DistrictsRouter
|
||||
FeedbacksRouter *feedbacks.FeedbacksRouter
|
||||
GalleriesRouter *galleries.GalleriesRouter
|
||||
GalleryFilesRouter *gallery_files.GalleryFilesRouter
|
||||
ProductSpecificationsRouter *product_specifications.ProductSpecificationsRouter
|
||||
ProductsRouter *products.ProductsRouter
|
||||
PromotionsRouter *promotions.PromotionsRouter
|
||||
ProvincesRouter *provinces.ProvincesRouter
|
||||
SalesAgentsRouter *sales_agents.SalesAgentsRouter
|
||||
UserLevelsRouter *user_levels.UserLevelsRouter
|
||||
UserRoleAccessesRouter *user_role_accesses.UserRoleAccessesRouter
|
||||
UserRolesRouter *user_roles.UserRolesRouter
|
||||
|
|
@ -57,11 +71,18 @@ func NewRouter(
|
|||
articleCommentsRouter *article_comments.ArticleCommentsRouter,
|
||||
articleApprovalsRouter *article_approvals.ArticleApprovalsRouter,
|
||||
articlesRouter *articles.ArticlesRouter,
|
||||
bannersRouter *banners.BannersRouter,
|
||||
citiesRouter *cities.CitiesRouter,
|
||||
customStaticPagesRouter *custom_static_pages.CustomStaticPagesRouter,
|
||||
districtsRouter *districts.DistrictsRouter,
|
||||
feedbacksRouter *feedbacks.FeedbacksRouter,
|
||||
galleriesRouter *galleries.GalleriesRouter,
|
||||
galleryFilesRouter *gallery_files.GalleryFilesRouter,
|
||||
productSpecificationsRouter *product_specifications.ProductSpecificationsRouter,
|
||||
productsRouter *products.ProductsRouter,
|
||||
promotionsRouter *promotions.PromotionsRouter,
|
||||
provincesRouter *provinces.ProvincesRouter,
|
||||
salesAgentsRouter *sales_agents.SalesAgentsRouter,
|
||||
userLevelsRouter *user_levels.UserLevelsRouter,
|
||||
userRoleAccessesRouter *user_role_accesses.UserRoleAccessesRouter,
|
||||
userRolesRouter *user_roles.UserRolesRouter,
|
||||
|
|
@ -77,11 +98,18 @@ func NewRouter(
|
|||
ArticleCommentsRouter: articleCommentsRouter,
|
||||
ArticleApprovalsRouter: articleApprovalsRouter,
|
||||
ArticlesRouter: articlesRouter,
|
||||
BannersRouter: bannersRouter,
|
||||
CitiesRouter: citiesRouter,
|
||||
CustomStaticPagesRouter: customStaticPagesRouter,
|
||||
DistrictsRouter: districtsRouter,
|
||||
FeedbacksRouter: feedbacksRouter,
|
||||
GalleriesRouter: galleriesRouter,
|
||||
GalleryFilesRouter: galleryFilesRouter,
|
||||
ProductSpecificationsRouter: productSpecificationsRouter,
|
||||
ProductsRouter: productsRouter,
|
||||
PromotionsRouter: promotionsRouter,
|
||||
ProvincesRouter: provincesRouter,
|
||||
SalesAgentsRouter: salesAgentsRouter,
|
||||
UserLevelsRouter: userLevelsRouter,
|
||||
UserRoleAccessesRouter: userRoleAccessesRouter,
|
||||
UserRolesRouter: userRolesRouter,
|
||||
|
|
@ -107,11 +135,18 @@ func (r *Router) Register() {
|
|||
r.ArticleApprovalsRouter.RegisterArticleApprovalsRoutes()
|
||||
r.ArticlesRouter.RegisterArticlesRoutes()
|
||||
r.ArticleCommentsRouter.RegisterArticleCommentsRoutes()
|
||||
r.BannersRouter.RegisterBannersRoutes()
|
||||
r.CitiesRouter.RegisterCitiesRoutes()
|
||||
r.CustomStaticPagesRouter.RegisterCustomStaticPagesRoutes()
|
||||
r.DistrictsRouter.RegisterDistrictsRoutes()
|
||||
r.FeedbacksRouter.RegisterFeedbacksRoutes()
|
||||
r.GalleriesRouter.RegisterGalleriesRoutes()
|
||||
r.GalleryFilesRouter.RegisterGalleryFilesRoutes()
|
||||
r.ProductSpecificationsRouter.RegisterProductSpecificationsRoutes()
|
||||
r.ProductsRouter.RegisterProductsRoutes()
|
||||
r.PromotionsRouter.RegisterPromotionsRoutes()
|
||||
r.ProvincesRouter.RegisterProvincesRoutes()
|
||||
r.SalesAgentsRouter.RegisterSalesAgentsRoutes()
|
||||
r.UserLevelsRouter.RegisterUserLevelsRoutes()
|
||||
r.UserRoleAccessesRouter.RegisterUserRoleAccessesRoutes()
|
||||
r.UsersRouter.RegisterUsersRoutes()
|
||||
|
|
|
|||
2583
docs/swagger/docs.go
2583
docs/swagger/docs.go
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
14
main.go
14
main.go
|
|
@ -10,11 +10,18 @@ import (
|
|||
"jaecoo-be/app/module/article_comments"
|
||||
"jaecoo-be/app/module/article_files"
|
||||
"jaecoo-be/app/module/articles"
|
||||
"jaecoo-be/app/module/banners"
|
||||
"jaecoo-be/app/module/cities"
|
||||
"jaecoo-be/app/module/custom_static_pages"
|
||||
"jaecoo-be/app/module/districts"
|
||||
"jaecoo-be/app/module/feedbacks"
|
||||
"jaecoo-be/app/module/galleries"
|
||||
"jaecoo-be/app/module/gallery_files"
|
||||
"jaecoo-be/app/module/product_specifications"
|
||||
"jaecoo-be/app/module/products"
|
||||
"jaecoo-be/app/module/promotions"
|
||||
"jaecoo-be/app/module/provinces"
|
||||
"jaecoo-be/app/module/sales_agents"
|
||||
"jaecoo-be/app/module/user_levels"
|
||||
"jaecoo-be/app/module/user_role_accesses"
|
||||
"jaecoo-be/app/module/user_role_level_details"
|
||||
|
|
@ -61,11 +68,18 @@ func main() {
|
|||
article_approvals.NewArticleApprovalsModule,
|
||||
articles.NewArticlesModule,
|
||||
article_comments.NewArticleCommentsModule,
|
||||
banners.NewBannersModule,
|
||||
cities.NewCitiesModule,
|
||||
custom_static_pages.NewCustomStaticPagesModule,
|
||||
districts.NewDistrictsModule,
|
||||
feedbacks.NewFeedbacksModule,
|
||||
galleries.NewGalleriesModule,
|
||||
gallery_files.NewGalleryFilesModule,
|
||||
product_specifications.NewProductSpecificationsModule,
|
||||
products.NewProductsModule,
|
||||
promotions.NewPromotionsModule,
|
||||
provinces.NewProvincesModule,
|
||||
sales_agents.NewSalesAgentsModule,
|
||||
user_levels.NewUserLevelsModule,
|
||||
user_roles.NewUserRolesModule,
|
||||
user_role_accesses.NewUserRoleAccessesModule,
|
||||
|
|
|
|||
Loading…
Reference in New Issue