diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e5ded44..ec1a2bc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -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 \ No newline at end of file + - curl --user $JENKINS_USER:$JENKINS_PWD http://38.47.180.165:8080/job/autodeploy-jaecoo-be/build?token=autodeployjaecoo \ No newline at end of file diff --git a/app/database/entity/banners.entity.go b/app/database/entity/banners.entity.go new file mode 100644 index 0000000..e1a7005 --- /dev/null +++ b/app/database/entity/banners.entity.go @@ -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()"` +} + diff --git a/app/database/entity/galleries.entity.go b/app/database/entity/galleries.entity.go new file mode 100644 index 0000000..6a34dcb --- /dev/null +++ b/app/database/entity/galleries.entity.go @@ -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()"` +} + diff --git a/app/database/entity/gallery_files.entity.go b/app/database/entity/gallery_files.entity.go new file mode 100644 index 0000000..f75cde2 --- /dev/null +++ b/app/database/entity/gallery_files.entity.go @@ -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()"` +} + diff --git a/app/database/entity/product_specifications.entity.go b/app/database/entity/product_specifications.entity.go new file mode 100644 index 0000000..0aa0680 --- /dev/null +++ b/app/database/entity/product_specifications.entity.go @@ -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()"` +} + diff --git a/app/database/entity/products.entity.go b/app/database/entity/products.entity.go new file mode 100644 index 0000000..74d11d2 --- /dev/null +++ b/app/database/entity/products.entity.go @@ -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()"` +} + diff --git a/app/database/entity/promotions.entity.go b/app/database/entity/promotions.entity.go new file mode 100644 index 0000000..73b6cb4 --- /dev/null +++ b/app/database/entity/promotions.entity.go @@ -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()"` +} diff --git a/app/database/entity/sales_agents.entity.go b/app/database/entity/sales_agents.entity.go new file mode 100644 index 0000000..c0d056d --- /dev/null +++ b/app/database/entity/sales_agents.entity.go @@ -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()"` +} diff --git a/app/database/index.database.go b/app/database/index.database.go index 1ff2bb2..982fe7b 100644 --- a/app/database/index.database.go +++ b/app/database/index.database.go @@ -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{}, diff --git a/app/module/banners/banners.module.go b/app/module/banners/banners.module.go new file mode 100644 index 0000000..6c25bd8 --- /dev/null +++ b/app/module/banners/banners.module.go @@ -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) + }) +} + diff --git a/app/module/banners/controller/banners.controller.go b/app/module/banners/controller/banners.controller.go new file mode 100644 index 0000000..ea1515a --- /dev/null +++ b/app/module/banners/controller/banners.controller.go @@ -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"}, + }) +} diff --git a/app/module/banners/controller/controller.go b/app/module/banners/controller/controller.go new file mode 100644 index 0000000..9699010 --- /dev/null +++ b/app/module/banners/controller/controller.go @@ -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), + } +} diff --git a/app/module/banners/mapper/banners.mapper.go b/app/module/banners/mapper/banners.mapper.go new file mode 100644 index 0000000..bc4d1f6 --- /dev/null +++ b/app/module/banners/mapper/banners.mapper.go @@ -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 +} + diff --git a/app/module/banners/repository/banners.repository.go b/app/module/banners/repository/banners.repository.go new file mode 100644 index 0000000..5293b94 --- /dev/null +++ b/app/module/banners/repository/banners.repository.go @@ -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 +} diff --git a/app/module/banners/request/banners.request.go b/app/module/banners/request/banners.request.go new file mode 100644 index 0000000..37ece48 --- /dev/null +++ b/app/module/banners/request/banners.request.go @@ -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 +} + diff --git a/app/module/banners/response/banners.response.go b/app/module/banners/response/banners.response.go new file mode 100644 index 0000000..d328636 --- /dev/null +++ b/app/module/banners/response/banners.response.go @@ -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"` +} + diff --git a/app/module/banners/service/banners.service.go b/app/module/banners/service/banners.service.go new file mode 100644 index 0000000..2f17a38 --- /dev/null +++ b/app/module/banners/service/banners.service.go @@ -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 +} diff --git a/app/module/galleries/controller/controller.go b/app/module/galleries/controller/controller.go new file mode 100644 index 0000000..dbf64af --- /dev/null +++ b/app/module/galleries/controller/controller.go @@ -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), + } +} diff --git a/app/module/galleries/controller/galleries.controller.go b/app/module/galleries/controller/galleries.controller.go new file mode 100644 index 0000000..2c3bb46 --- /dev/null +++ b/app/module/galleries/controller/galleries.controller.go @@ -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"}, + }) +} diff --git a/app/module/galleries/galleries.module.go b/app/module/galleries/galleries.module.go new file mode 100644 index 0000000..ea76591 --- /dev/null +++ b/app/module/galleries/galleries.module.go @@ -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) + }) +} + diff --git a/app/module/galleries/mapper/galleries.mapper.go b/app/module/galleries/mapper/galleries.mapper.go new file mode 100644 index 0000000..b436dfd --- /dev/null +++ b/app/module/galleries/mapper/galleries.mapper.go @@ -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 +} + diff --git a/app/module/galleries/repository/galleries.repository.go b/app/module/galleries/repository/galleries.repository.go new file mode 100644 index 0000000..e542723 --- /dev/null +++ b/app/module/galleries/repository/galleries.repository.go @@ -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 +} diff --git a/app/module/galleries/request/galleries.request.go b/app/module/galleries/request/galleries.request.go new file mode 100644 index 0000000..270a4e7 --- /dev/null +++ b/app/module/galleries/request/galleries.request.go @@ -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 +} + diff --git a/app/module/galleries/response/galleries.response.go b/app/module/galleries/response/galleries.response.go new file mode 100644 index 0000000..a245792 --- /dev/null +++ b/app/module/galleries/response/galleries.response.go @@ -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"` +} + diff --git a/app/module/galleries/service/galleries.service.go b/app/module/galleries/service/galleries.service.go new file mode 100644 index 0000000..c52179f --- /dev/null +++ b/app/module/galleries/service/galleries.service.go @@ -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 +} diff --git a/app/module/gallery_files/controller/controller.go b/app/module/gallery_files/controller/controller.go new file mode 100644 index 0000000..84df0f0 --- /dev/null +++ b/app/module/gallery_files/controller/controller.go @@ -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), + } +} + diff --git a/app/module/gallery_files/controller/gallery_files.controller.go b/app/module/gallery_files/controller/gallery_files.controller.go new file mode 100644 index 0000000..55014c0 --- /dev/null +++ b/app/module/gallery_files/controller/gallery_files.controller.go @@ -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"}, + }) +} diff --git a/app/module/gallery_files/gallery_files.module.go b/app/module/gallery_files/gallery_files.module.go new file mode 100644 index 0000000..5efb8ad --- /dev/null +++ b/app/module/gallery_files/gallery_files.module.go @@ -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) + }) +} + diff --git a/app/module/gallery_files/mapper/gallery_files.mapper.go b/app/module/gallery_files/mapper/gallery_files.mapper.go new file mode 100644 index 0000000..a29c8e5 --- /dev/null +++ b/app/module/gallery_files/mapper/gallery_files.mapper.go @@ -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 +} + diff --git a/app/module/gallery_files/repository/gallery_files.repository.go b/app/module/gallery_files/repository/gallery_files.repository.go new file mode 100644 index 0000000..4292cda --- /dev/null +++ b/app/module/gallery_files/repository/gallery_files.repository.go @@ -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 +} + diff --git a/app/module/gallery_files/request/gallery_files.request.go b/app/module/gallery_files/request/gallery_files.request.go new file mode 100644 index 0000000..bd53ea3 --- /dev/null +++ b/app/module/gallery_files/request/gallery_files.request.go @@ -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 +} + diff --git a/app/module/gallery_files/response/gallery_files.response.go b/app/module/gallery_files/response/gallery_files.response.go new file mode 100644 index 0000000..2e38572 --- /dev/null +++ b/app/module/gallery_files/response/gallery_files.response.go @@ -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"` +} + diff --git a/app/module/gallery_files/service/gallery_files.service.go b/app/module/gallery_files/service/gallery_files.service.go new file mode 100644 index 0000000..f620596 --- /dev/null +++ b/app/module/gallery_files/service/gallery_files.service.go @@ -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 +} diff --git a/app/module/product_specifications/controller/controller.go b/app/module/product_specifications/controller/controller.go new file mode 100644 index 0000000..437340a --- /dev/null +++ b/app/module/product_specifications/controller/controller.go @@ -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), + } +} + diff --git a/app/module/product_specifications/controller/product_specifications.controller.go b/app/module/product_specifications/controller/product_specifications.controller.go new file mode 100644 index 0000000..d065081 --- /dev/null +++ b/app/module/product_specifications/controller/product_specifications.controller.go @@ -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"}, + }) +} + diff --git a/app/module/product_specifications/mapper/product_specifications.mapper.go b/app/module/product_specifications/mapper/product_specifications.mapper.go new file mode 100644 index 0000000..9472fab --- /dev/null +++ b/app/module/product_specifications/mapper/product_specifications.mapper.go @@ -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 +} + diff --git a/app/module/product_specifications/product_specifications.module.go b/app/module/product_specifications/product_specifications.module.go new file mode 100644 index 0000000..a1c77ec --- /dev/null +++ b/app/module/product_specifications/product_specifications.module.go @@ -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) + }) +} + diff --git a/app/module/product_specifications/repository/product_specifications.repository.go b/app/module/product_specifications/repository/product_specifications.repository.go new file mode 100644 index 0000000..995af74 --- /dev/null +++ b/app/module/product_specifications/repository/product_specifications.repository.go @@ -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 +} + diff --git a/app/module/product_specifications/request/product_specifications.request.go b/app/module/product_specifications/request/product_specifications.request.go new file mode 100644 index 0000000..c382bb1 --- /dev/null +++ b/app/module/product_specifications/request/product_specifications.request.go @@ -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 +} + diff --git a/app/module/product_specifications/response/product_specifications.response.go b/app/module/product_specifications/response/product_specifications.response.go new file mode 100644 index 0000000..1609aa5 --- /dev/null +++ b/app/module/product_specifications/response/product_specifications.response.go @@ -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"` +} + diff --git a/app/module/product_specifications/service/product_specifications.service.go b/app/module/product_specifications/service/product_specifications.service.go new file mode 100644 index 0000000..fb2bbde --- /dev/null +++ b/app/module/product_specifications/service/product_specifications.service.go @@ -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 +} diff --git a/app/module/products/controller/controller.go b/app/module/products/controller/controller.go new file mode 100644 index 0000000..f001c4f --- /dev/null +++ b/app/module/products/controller/controller.go @@ -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), + } +} + diff --git a/app/module/products/controller/products.controller.go b/app/module/products/controller/products.controller.go new file mode 100644 index 0000000..0a4cf77 --- /dev/null +++ b/app/module/products/controller/products.controller.go @@ -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"}, + }) +} + diff --git a/app/module/products/mapper/products.mapper.go b/app/module/products/mapper/products.mapper.go new file mode 100644 index 0000000..e17d736 --- /dev/null +++ b/app/module/products/mapper/products.mapper.go @@ -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 +} + diff --git a/app/module/products/products.module.go b/app/module/products/products.module.go new file mode 100644 index 0000000..3365dff --- /dev/null +++ b/app/module/products/products.module.go @@ -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) + }) +} + diff --git a/app/module/products/repository/products.repository.go b/app/module/products/repository/products.repository.go new file mode 100644 index 0000000..4c72756 --- /dev/null +++ b/app/module/products/repository/products.repository.go @@ -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 +} + diff --git a/app/module/products/request/products.request.go b/app/module/products/request/products.request.go new file mode 100644 index 0000000..4f31591 --- /dev/null +++ b/app/module/products/request/products.request.go @@ -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 +} + diff --git a/app/module/products/response/products.response.go b/app/module/products/response/products.response.go new file mode 100644 index 0000000..675a1e7 --- /dev/null +++ b/app/module/products/response/products.response.go @@ -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"` +} + diff --git a/app/module/products/service/products.service.go b/app/module/products/service/products.service.go new file mode 100644 index 0000000..ee51bf9 --- /dev/null +++ b/app/module/products/service/products.service.go @@ -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 +} diff --git a/app/module/promotions/controller/controller.go b/app/module/promotions/controller/controller.go new file mode 100644 index 0000000..4cee9fa --- /dev/null +++ b/app/module/promotions/controller/controller.go @@ -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), + } +} diff --git a/app/module/promotions/controller/promotions.controller.go b/app/module/promotions/controller/promotions.controller.go new file mode 100644 index 0000000..c2e7678 --- /dev/null +++ b/app/module/promotions/controller/promotions.controller.go @@ -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"}, + }) +} diff --git a/app/module/promotions/mapper/promotions.mapper.go b/app/module/promotions/mapper/promotions.mapper.go new file mode 100644 index 0000000..e1500c7 --- /dev/null +++ b/app/module/promotions/mapper/promotions.mapper.go @@ -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 +} + diff --git a/app/module/promotions/promotions.module.go b/app/module/promotions/promotions.module.go new file mode 100644 index 0000000..9daba31 --- /dev/null +++ b/app/module/promotions/promotions.module.go @@ -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) + }) +} + diff --git a/app/module/promotions/repository/promotions.repository.go b/app/module/promotions/repository/promotions.repository.go new file mode 100644 index 0000000..a04ac4e --- /dev/null +++ b/app/module/promotions/repository/promotions.repository.go @@ -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 +} + diff --git a/app/module/promotions/request/promotions.request.go b/app/module/promotions/request/promotions.request.go new file mode 100644 index 0000000..063f898 --- /dev/null +++ b/app/module/promotions/request/promotions.request.go @@ -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 +} diff --git a/app/module/promotions/response/promotions.response.go b/app/module/promotions/response/promotions.response.go new file mode 100644 index 0000000..f2dfb6b --- /dev/null +++ b/app/module/promotions/response/promotions.response.go @@ -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"` +} + diff --git a/app/module/promotions/service/promotions.service.go b/app/module/promotions/service/promotions.service.go new file mode 100644 index 0000000..b528a5a --- /dev/null +++ b/app/module/promotions/service/promotions.service.go @@ -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 +} diff --git a/app/module/sales_agents/controller/controller.go b/app/module/sales_agents/controller/controller.go new file mode 100644 index 0000000..0cf1711 --- /dev/null +++ b/app/module/sales_agents/controller/controller.go @@ -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), + } +} + diff --git a/app/module/sales_agents/controller/sales_agents.controller.go b/app/module/sales_agents/controller/sales_agents.controller.go new file mode 100644 index 0000000..fcb718f --- /dev/null +++ b/app/module/sales_agents/controller/sales_agents.controller.go @@ -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"}, + }) +} + diff --git a/app/module/sales_agents/mapper/sales_agents.mapper.go b/app/module/sales_agents/mapper/sales_agents.mapper.go new file mode 100644 index 0000000..6e95d03 --- /dev/null +++ b/app/module/sales_agents/mapper/sales_agents.mapper.go @@ -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 +} + diff --git a/app/module/sales_agents/repository/sales_agents.repository.go b/app/module/sales_agents/repository/sales_agents.repository.go new file mode 100644 index 0000000..b709d70 --- /dev/null +++ b/app/module/sales_agents/repository/sales_agents.repository.go @@ -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 +} + diff --git a/app/module/sales_agents/request/sales_agents.request.go b/app/module/sales_agents/request/sales_agents.request.go new file mode 100644 index 0000000..8381e86 --- /dev/null +++ b/app/module/sales_agents/request/sales_agents.request.go @@ -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 +} + diff --git a/app/module/sales_agents/response/sales_agents.response.go b/app/module/sales_agents/response/sales_agents.response.go new file mode 100644 index 0000000..59707c0 --- /dev/null +++ b/app/module/sales_agents/response/sales_agents.response.go @@ -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"` +} + diff --git a/app/module/sales_agents/sales_agents.module.go b/app/module/sales_agents/sales_agents.module.go new file mode 100644 index 0000000..a993bc5 --- /dev/null +++ b/app/module/sales_agents/sales_agents.module.go @@ -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) + }) +} + diff --git a/app/module/sales_agents/service/sales_agents.service.go b/app/module/sales_agents/service/sales_agents.service.go new file mode 100644 index 0000000..36818cf --- /dev/null +++ b/app/module/sales_agents/service/sales_agents.service.go @@ -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 +} diff --git a/app/router/api.go b/app/router/api.go index 28ed7ce..6bc4184 100644 --- a/app/router/api.go +++ b/app/router/api.go @@ -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() diff --git a/docs/swagger/docs.go b/docs/swagger/docs.go index ab0e77c..4546f46 100644 --- a/docs/swagger/docs.go +++ b/docs/swagger/docs.go @@ -3222,6 +3222,339 @@ const docTemplate = `{ } } }, + "/banners": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all Banners", + "tags": [ + "Banners" + ], + "summary": "Get all Banners", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "position", + "in": "query" + }, + { + "type": "string", + "name": "status", + "in": "query" + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating Banner", + "tags": [ + "Banners" + ], + "summary": "Create Banner", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.BannersCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/banners/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting Banner by ID", + "tags": [ + "Banners" + ], + "summary": "Get Banner by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Banner ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating Banner", + "tags": [ + "Banners" + ], + "summary": "Update Banner", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Banner ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.BannersUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting Banner (soft delete)", + "tags": [ + "Banners" + ], + "summary": "Delete Banner", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Banner ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/cities": { "get": { "security": [ @@ -4519,6 +4852,1636 @@ const docTemplate = `{ } } }, + "/galleries": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all Galleries", + "tags": [ + "Galleries" + ], + "summary": "Get all Galleries", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating Gallery", + "tags": [ + "Galleries" + ], + "summary": "Create Gallery", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.GalleriesCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/galleries/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting Gallery by ID", + "tags": [ + "Galleries" + ], + "summary": "Get Gallery by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Gallery ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating Gallery", + "tags": [ + "Galleries" + ], + "summary": "Update Gallery", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Gallery ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.GalleriesUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting Gallery (soft delete)", + "tags": [ + "Galleries" + ], + "summary": "Delete Gallery", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Gallery ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/gallery-files": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all GalleryFiles", + "tags": [ + "GalleryFiles" + ], + "summary": "Get all GalleryFiles", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "gallery_id", + "in": "query" + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating GalleryFile", + "tags": [ + "GalleryFiles" + ], + "summary": "Create GalleryFile", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.GalleryFilesCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/gallery-files/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting GalleryFile by ID", + "tags": [ + "GalleryFiles" + ], + "summary": "Get GalleryFile by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "GalleryFile ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating GalleryFile", + "tags": [ + "GalleryFiles" + ], + "summary": "Update GalleryFile", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "GalleryFile ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.GalleryFilesUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting GalleryFile (soft delete)", + "tags": [ + "GalleryFiles" + ], + "summary": "Delete GalleryFile", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "GalleryFile ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/product-specifications": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all ProductSpecifications", + "tags": [ + "ProductSpecifications" + ], + "summary": "Get all ProductSpecifications", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "product_id", + "in": "query" + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating ProductSpecification", + "tags": [ + "ProductSpecifications" + ], + "summary": "Create ProductSpecification", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ProductSpecificationsCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/product-specifications/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting ProductSpecification by ID", + "tags": [ + "ProductSpecifications" + ], + "summary": "Get ProductSpecification by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "ProductSpecification ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating ProductSpecification", + "tags": [ + "ProductSpecifications" + ], + "summary": "Update ProductSpecification", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "ProductSpecification ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ProductSpecificationsUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting ProductSpecification (soft delete)", + "tags": [ + "ProductSpecifications" + ], + "summary": "Delete ProductSpecification", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "ProductSpecification ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/products": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all Products", + "tags": [ + "Products" + ], + "summary": "Get all Products", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "string", + "name": "variant", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating Product", + "tags": [ + "Products" + ], + "summary": "Create Product", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ProductsCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/products/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting Product by ID", + "tags": [ + "Products" + ], + "summary": "Get Product by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Product ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating Product", + "tags": [ + "Products" + ], + "summary": "Update Product", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Product ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ProductsUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting Product (soft delete)", + "tags": [ + "Products" + ], + "summary": "Delete Product", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Product ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/promotions": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all Promotions", + "tags": [ + "Promotions" + ], + "summary": "Get all Promotions", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating Promotion", + "tags": [ + "Promotions" + ], + "summary": "Create Promotion", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PromotionsCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/promotions/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting Promotion by ID", + "tags": [ + "Promotions" + ], + "summary": "Get Promotion by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Promotion ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating Promotion", + "tags": [ + "Promotions" + ], + "summary": "Update Promotion", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Promotion ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PromotionsUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting Promotion (soft delete)", + "tags": [ + "Promotions" + ], + "summary": "Delete Promotion", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Promotion ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/provinces": { "get": { "security": [ @@ -4770,6 +6733,339 @@ const docTemplate = `{ } } }, + "/sales-agents": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all SalesAgents", + "tags": [ + "SalesAgents" + ], + "summary": "Get all SalesAgents", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "agent_type", + "in": "query" + }, + { + "type": "string", + "name": "job_title", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating SalesAgent", + "tags": [ + "SalesAgents" + ], + "summary": "Create SalesAgent", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SalesAgentsCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/sales-agents/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting SalesAgent by ID", + "tags": [ + "SalesAgents" + ], + "summary": "Get SalesAgent by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "SalesAgent ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating SalesAgent", + "tags": [ + "SalesAgents" + ], + "summary": "Update SalesAgent", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "SalesAgent ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SalesAgentsUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting SalesAgent (soft delete)", + "tags": [ + "SalesAgents" + ], + "summary": "Delete SalesAgent", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "SalesAgent ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/user-levels": { "get": { "security": [ @@ -7524,6 +9820,52 @@ const docTemplate = `{ } } }, + "request.BannersCreateRequest": { + "type": "object", + "required": [ + "title" + ], + "properties": { + "description": { + "type": "string" + }, + "position": { + "type": "string" + }, + "status": { + "type": "string" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.BannersUpdateRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "position": { + "type": "string" + }, + "status": { + "type": "string" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, "request.CitiesCreateRequest": { "type": "object", "required": [ @@ -7651,6 +9993,247 @@ const docTemplate = `{ } } }, + "request.GalleriesCreateRequest": { + "type": "object", + "required": [ + "title" + ], + "properties": { + "description": { + "type": "string" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.GalleriesUpdateRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.GalleryFilesCreateRequest": { + "type": "object", + "required": [ + "gallery_id" + ], + "properties": { + "gallery_id": { + "type": "integer" + }, + "image_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.GalleryFilesUpdateRequest": { + "type": "object", + "properties": { + "gallery_id": { + "type": "integer" + }, + "image_path": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "title": { + "type": "string" + } + } + }, + "request.ProductSpecificationsCreateRequest": { + "type": "object", + "required": [ + "product_id", + "title" + ], + "properties": { + "product_id": { + "type": "integer" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.ProductSpecificationsUpdateRequest": { + "type": "object", + "properties": { + "is_active": { + "type": "boolean" + }, + "product_id": { + "type": "integer" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.ProductsCreateRequest": { + "type": "object", + "required": [ + "title" + ], + "properties": { + "colors": { + "type": "array", + "items": { + "type": "string" + } + }, + "price": { + "type": "number" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + }, + "variant": { + "type": "string" + } + } + }, + "request.ProductsUpdateRequest": { + "type": "object", + "properties": { + "colors": { + "type": "array", + "items": { + "type": "string" + } + }, + "is_active": { + "type": "boolean" + }, + "price": { + "type": "number" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + }, + "variant": { + "type": "string" + } + } + }, + "request.PromotionsCreateRequest": { + "type": "object", + "required": [ + "title" + ], + "properties": { + "description": { + "type": "string" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.PromotionsUpdateRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.SalesAgentsCreateRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "agent_type": { + "type": "array", + "items": { + "type": "string" + } + }, + "job_title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "profile_picture_path": { + "type": "string" + } + } + }, + "request.SalesAgentsUpdateRequest": { + "type": "object", + "properties": { + "agent_type": { + "type": "array", + "items": { + "type": "string" + } + }, + "is_active": { + "type": "boolean" + }, + "job_title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "profile_picture_path": { + "type": "string" + } + } + }, "request.UserEmailValidationRequest": { "type": "object", "properties": { diff --git a/docs/swagger/swagger.json b/docs/swagger/swagger.json index 2c80e60..8d9935f 100644 --- a/docs/swagger/swagger.json +++ b/docs/swagger/swagger.json @@ -3211,6 +3211,339 @@ } } }, + "/banners": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all Banners", + "tags": [ + "Banners" + ], + "summary": "Get all Banners", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "position", + "in": "query" + }, + { + "type": "string", + "name": "status", + "in": "query" + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating Banner", + "tags": [ + "Banners" + ], + "summary": "Create Banner", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.BannersCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/banners/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting Banner by ID", + "tags": [ + "Banners" + ], + "summary": "Get Banner by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Banner ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating Banner", + "tags": [ + "Banners" + ], + "summary": "Update Banner", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Banner ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.BannersUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting Banner (soft delete)", + "tags": [ + "Banners" + ], + "summary": "Delete Banner", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Banner ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/cities": { "get": { "security": [ @@ -4508,6 +4841,1636 @@ } } }, + "/galleries": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all Galleries", + "tags": [ + "Galleries" + ], + "summary": "Get all Galleries", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating Gallery", + "tags": [ + "Galleries" + ], + "summary": "Create Gallery", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.GalleriesCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/galleries/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting Gallery by ID", + "tags": [ + "Galleries" + ], + "summary": "Get Gallery by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Gallery ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating Gallery", + "tags": [ + "Galleries" + ], + "summary": "Update Gallery", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Gallery ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.GalleriesUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting Gallery (soft delete)", + "tags": [ + "Galleries" + ], + "summary": "Delete Gallery", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Gallery ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/gallery-files": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all GalleryFiles", + "tags": [ + "GalleryFiles" + ], + "summary": "Get all GalleryFiles", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "gallery_id", + "in": "query" + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating GalleryFile", + "tags": [ + "GalleryFiles" + ], + "summary": "Create GalleryFile", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.GalleryFilesCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/gallery-files/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting GalleryFile by ID", + "tags": [ + "GalleryFiles" + ], + "summary": "Get GalleryFile by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "GalleryFile ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating GalleryFile", + "tags": [ + "GalleryFiles" + ], + "summary": "Update GalleryFile", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "GalleryFile ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.GalleryFilesUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting GalleryFile (soft delete)", + "tags": [ + "GalleryFiles" + ], + "summary": "Delete GalleryFile", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "GalleryFile ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/product-specifications": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all ProductSpecifications", + "tags": [ + "ProductSpecifications" + ], + "summary": "Get all ProductSpecifications", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "product_id", + "in": "query" + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating ProductSpecification", + "tags": [ + "ProductSpecifications" + ], + "summary": "Create ProductSpecification", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ProductSpecificationsCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/product-specifications/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting ProductSpecification by ID", + "tags": [ + "ProductSpecifications" + ], + "summary": "Get ProductSpecification by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "ProductSpecification ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating ProductSpecification", + "tags": [ + "ProductSpecifications" + ], + "summary": "Update ProductSpecification", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "ProductSpecification ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ProductSpecificationsUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting ProductSpecification (soft delete)", + "tags": [ + "ProductSpecifications" + ], + "summary": "Delete ProductSpecification", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "ProductSpecification ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/products": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all Products", + "tags": [ + "Products" + ], + "summary": "Get all Products", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "string", + "name": "variant", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating Product", + "tags": [ + "Products" + ], + "summary": "Create Product", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ProductsCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/products/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting Product by ID", + "tags": [ + "Products" + ], + "summary": "Get Product by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Product ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating Product", + "tags": [ + "Products" + ], + "summary": "Update Product", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Product ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ProductsUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting Product (soft delete)", + "tags": [ + "Products" + ], + "summary": "Delete Product", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Product ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/promotions": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all Promotions", + "tags": [ + "Promotions" + ], + "summary": "Get all Promotions", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "title", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating Promotion", + "tags": [ + "Promotions" + ], + "summary": "Create Promotion", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PromotionsCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/promotions/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting Promotion by ID", + "tags": [ + "Promotions" + ], + "summary": "Get Promotion by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Promotion ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating Promotion", + "tags": [ + "Promotions" + ], + "summary": "Update Promotion", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Promotion ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.PromotionsUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting Promotion (soft delete)", + "tags": [ + "Promotions" + ], + "summary": "Delete Promotion", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "Promotion ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/provinces": { "get": { "security": [ @@ -4759,6 +6722,339 @@ } } }, + "/sales-agents": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all SalesAgents", + "tags": [ + "SalesAgents" + ], + "summary": "Get all SalesAgents", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "string", + "name": "agent_type", + "in": "query" + }, + { + "type": "string", + "name": "job_title", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "query" + }, + { + "type": "integer", + "name": "count", + "in": "query" + }, + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "nextPage", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "previousPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "name": "sortBy", + "in": "query" + }, + { + "type": "integer", + "name": "totalPage", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for creating SalesAgent", + "tags": [ + "SalesAgents" + ], + "summary": "Create SalesAgent", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SalesAgentsCreateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/sales-agents/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting SalesAgent by ID", + "tags": [ + "SalesAgents" + ], + "summary": "Get SalesAgent by ID", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "SalesAgent ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for updating SalesAgent", + "tags": [ + "SalesAgents" + ], + "summary": "Update SalesAgent", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "SalesAgent ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SalesAgentsUpdateRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for deleting SalesAgent (soft delete)", + "tags": [ + "SalesAgents" + ], + "summary": "Delete SalesAgent", + "parameters": [ + { + "type": "string", + "description": "Insert the X-Client-Key", + "name": "X-Client-Key", + "in": "header", + "required": true + }, + { + "type": "integer", + "description": "SalesAgent ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/user-levels": { "get": { "security": [ @@ -7513,6 +9809,52 @@ } } }, + "request.BannersCreateRequest": { + "type": "object", + "required": [ + "title" + ], + "properties": { + "description": { + "type": "string" + }, + "position": { + "type": "string" + }, + "status": { + "type": "string" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.BannersUpdateRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "position": { + "type": "string" + }, + "status": { + "type": "string" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, "request.CitiesCreateRequest": { "type": "object", "required": [ @@ -7640,6 +9982,247 @@ } } }, + "request.GalleriesCreateRequest": { + "type": "object", + "required": [ + "title" + ], + "properties": { + "description": { + "type": "string" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.GalleriesUpdateRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.GalleryFilesCreateRequest": { + "type": "object", + "required": [ + "gallery_id" + ], + "properties": { + "gallery_id": { + "type": "integer" + }, + "image_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.GalleryFilesUpdateRequest": { + "type": "object", + "properties": { + "gallery_id": { + "type": "integer" + }, + "image_path": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "title": { + "type": "string" + } + } + }, + "request.ProductSpecificationsCreateRequest": { + "type": "object", + "required": [ + "product_id", + "title" + ], + "properties": { + "product_id": { + "type": "integer" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.ProductSpecificationsUpdateRequest": { + "type": "object", + "properties": { + "is_active": { + "type": "boolean" + }, + "product_id": { + "type": "integer" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.ProductsCreateRequest": { + "type": "object", + "required": [ + "title" + ], + "properties": { + "colors": { + "type": "array", + "items": { + "type": "string" + } + }, + "price": { + "type": "number" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + }, + "variant": { + "type": "string" + } + } + }, + "request.ProductsUpdateRequest": { + "type": "object", + "properties": { + "colors": { + "type": "array", + "items": { + "type": "string" + } + }, + "is_active": { + "type": "boolean" + }, + "price": { + "type": "number" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + }, + "variant": { + "type": "string" + } + } + }, + "request.PromotionsCreateRequest": { + "type": "object", + "required": [ + "title" + ], + "properties": { + "description": { + "type": "string" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.PromotionsUpdateRequest": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "thumbnail_path": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.SalesAgentsCreateRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "agent_type": { + "type": "array", + "items": { + "type": "string" + } + }, + "job_title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "profile_picture_path": { + "type": "string" + } + } + }, + "request.SalesAgentsUpdateRequest": { + "type": "object", + "properties": { + "agent_type": { + "type": "array", + "items": { + "type": "string" + } + }, + "is_active": { + "type": "boolean" + }, + "job_title": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "profile_picture_path": { + "type": "string" + } + } + }, "request.UserEmailValidationRequest": { "type": "object", "properties": { diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index 8fcc22d..c7a3606 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -281,6 +281,36 @@ definitions: - title - typeId type: object + request.BannersCreateRequest: + properties: + description: + type: string + position: + type: string + status: + type: string + thumbnail_path: + type: string + title: + type: string + required: + - title + type: object + request.BannersUpdateRequest: + properties: + description: + type: string + is_active: + type: boolean + position: + type: string + status: + type: string + thumbnail_path: + type: string + title: + type: string + type: object request.CitiesCreateRequest: properties: cityName: @@ -368,6 +398,163 @@ definitions: - id - message type: object + request.GalleriesCreateRequest: + properties: + description: + type: string + thumbnail_path: + type: string + title: + type: string + required: + - title + type: object + request.GalleriesUpdateRequest: + properties: + description: + type: string + is_active: + type: boolean + thumbnail_path: + type: string + title: + type: string + type: object + request.GalleryFilesCreateRequest: + properties: + gallery_id: + type: integer + image_path: + type: string + title: + type: string + required: + - gallery_id + type: object + request.GalleryFilesUpdateRequest: + properties: + gallery_id: + type: integer + image_path: + type: string + is_active: + type: boolean + title: + type: string + type: object + request.ProductSpecificationsCreateRequest: + properties: + product_id: + type: integer + thumbnail_path: + type: string + title: + type: string + required: + - product_id + - title + type: object + request.ProductSpecificationsUpdateRequest: + properties: + is_active: + type: boolean + product_id: + type: integer + thumbnail_path: + type: string + title: + type: string + type: object + request.ProductsCreateRequest: + properties: + colors: + items: + type: string + type: array + price: + type: number + thumbnail_path: + type: string + title: + type: string + variant: + type: string + required: + - title + type: object + request.ProductsUpdateRequest: + properties: + colors: + items: + type: string + type: array + is_active: + type: boolean + price: + type: number + thumbnail_path: + type: string + title: + type: string + variant: + type: string + type: object + request.PromotionsCreateRequest: + properties: + description: + type: string + thumbnail_path: + type: string + title: + type: string + required: + - title + type: object + request.PromotionsUpdateRequest: + properties: + description: + type: string + is_active: + type: boolean + thumbnail_path: + type: string + title: + type: string + type: object + request.SalesAgentsCreateRequest: + properties: + agent_type: + items: + type: string + type: array + job_title: + type: string + name: + type: string + phone: + type: string + profile_picture_path: + type: string + required: + - name + type: object + request.SalesAgentsUpdateRequest: + properties: + agent_type: + items: + type: string + type: array + is_active: + type: boolean + job_title: + type: string + name: + type: string + phone: + type: string + profile_picture_path: + type: string + type: object request.UserEmailValidationRequest: properties: newEmail: @@ -2776,6 +2963,218 @@ paths: summary: Viewer Articles Thumbnail tags: - Articles + /banners: + get: + description: API for getting all Banners + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - in: query + name: position + type: string + - in: query + name: status + type: string + - in: query + name: title + type: string + - in: query + name: count + type: integer + - in: query + name: limit + type: integer + - in: query + name: nextPage + type: integer + - in: query + name: page + type: integer + - in: query + name: previousPage + type: integer + - in: query + name: sort + type: string + - in: query + name: sortBy + type: string + - in: query + name: totalPage + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get all Banners + tags: + - Banners + post: + description: API for creating Banner + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.BannersCreateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Create Banner + tags: + - Banners + /banners/{id}: + delete: + description: API for deleting Banner (soft delete) + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Banner ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Delete Banner + tags: + - Banners + get: + description: API for getting Banner by ID + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Banner ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get Banner by ID + tags: + - Banners + put: + description: API for updating Banner + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Banner ID + in: path + name: id + required: true + type: integer + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.BannersUpdateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Update Banner + tags: + - Banners /cities: get: description: API for getting all Cities @@ -3600,6 +3999,1045 @@ paths: summary: FeedbackMonthlyStats Feedbacks tags: - Feedbacks + /galleries: + get: + description: API for getting all Galleries + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - in: query + name: title + type: string + - in: query + name: count + type: integer + - in: query + name: limit + type: integer + - in: query + name: nextPage + type: integer + - in: query + name: page + type: integer + - in: query + name: previousPage + type: integer + - in: query + name: sort + type: string + - in: query + name: sortBy + type: string + - in: query + name: totalPage + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get all Galleries + tags: + - Galleries + post: + description: API for creating Gallery + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.GalleriesCreateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Create Gallery + tags: + - Galleries + /galleries/{id}: + delete: + description: API for deleting Gallery (soft delete) + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Gallery ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Delete Gallery + tags: + - Galleries + get: + description: API for getting Gallery by ID + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Gallery ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get Gallery by ID + tags: + - Galleries + put: + description: API for updating Gallery + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Gallery ID + in: path + name: id + required: true + type: integer + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.GalleriesUpdateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Update Gallery + tags: + - Galleries + /gallery-files: + get: + description: API for getting all GalleryFiles + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - in: query + name: gallery_id + type: string + - in: query + name: title + type: string + - in: query + name: count + type: integer + - in: query + name: limit + type: integer + - in: query + name: nextPage + type: integer + - in: query + name: page + type: integer + - in: query + name: previousPage + type: integer + - in: query + name: sort + type: string + - in: query + name: sortBy + type: string + - in: query + name: totalPage + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get all GalleryFiles + tags: + - GalleryFiles + post: + description: API for creating GalleryFile + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.GalleryFilesCreateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Create GalleryFile + tags: + - GalleryFiles + /gallery-files/{id}: + delete: + description: API for deleting GalleryFile (soft delete) + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: GalleryFile ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Delete GalleryFile + tags: + - GalleryFiles + get: + description: API for getting GalleryFile by ID + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: GalleryFile ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get GalleryFile by ID + tags: + - GalleryFiles + put: + description: API for updating GalleryFile + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: GalleryFile ID + in: path + name: id + required: true + type: integer + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.GalleryFilesUpdateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Update GalleryFile + tags: + - GalleryFiles + /product-specifications: + get: + description: API for getting all ProductSpecifications + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - in: query + name: product_id + type: string + - in: query + name: title + type: string + - in: query + name: count + type: integer + - in: query + name: limit + type: integer + - in: query + name: nextPage + type: integer + - in: query + name: page + type: integer + - in: query + name: previousPage + type: integer + - in: query + name: sort + type: string + - in: query + name: sortBy + type: string + - in: query + name: totalPage + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get all ProductSpecifications + tags: + - ProductSpecifications + post: + description: API for creating ProductSpecification + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.ProductSpecificationsCreateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Create ProductSpecification + tags: + - ProductSpecifications + /product-specifications/{id}: + delete: + description: API for deleting ProductSpecification (soft delete) + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: ProductSpecification ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Delete ProductSpecification + tags: + - ProductSpecifications + get: + description: API for getting ProductSpecification by ID + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: ProductSpecification ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get ProductSpecification by ID + tags: + - ProductSpecifications + put: + description: API for updating ProductSpecification + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: ProductSpecification ID + in: path + name: id + required: true + type: integer + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.ProductSpecificationsUpdateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Update ProductSpecification + tags: + - ProductSpecifications + /products: + get: + description: API for getting all Products + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - in: query + name: title + type: string + - in: query + name: variant + type: string + - in: query + name: count + type: integer + - in: query + name: limit + type: integer + - in: query + name: nextPage + type: integer + - in: query + name: page + type: integer + - in: query + name: previousPage + type: integer + - in: query + name: sort + type: string + - in: query + name: sortBy + type: string + - in: query + name: totalPage + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get all Products + tags: + - Products + post: + description: API for creating Product + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.ProductsCreateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Create Product + tags: + - Products + /products/{id}: + delete: + description: API for deleting Product (soft delete) + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Product ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Delete Product + tags: + - Products + get: + description: API for getting Product by ID + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Product ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get Product by ID + tags: + - Products + put: + description: API for updating Product + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Product ID + in: path + name: id + required: true + type: integer + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.ProductsUpdateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Update Product + tags: + - Products + /promotions: + get: + description: API for getting all Promotions + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - in: query + name: title + type: string + - in: query + name: count + type: integer + - in: query + name: limit + type: integer + - in: query + name: nextPage + type: integer + - in: query + name: page + type: integer + - in: query + name: previousPage + type: integer + - in: query + name: sort + type: string + - in: query + name: sortBy + type: string + - in: query + name: totalPage + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get all Promotions + tags: + - Promotions + post: + description: API for creating Promotion + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.PromotionsCreateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Create Promotion + tags: + - Promotions + /promotions/{id}: + delete: + description: API for deleting Promotion (soft delete) + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Promotion ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Delete Promotion + tags: + - Promotions + get: + description: API for getting Promotion by ID + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Promotion ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get Promotion by ID + tags: + - Promotions + put: + description: API for updating Promotion + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Promotion ID + in: path + name: id + required: true + type: integer + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.PromotionsUpdateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Update Promotion + tags: + - Promotions /provinces: get: description: API for getting all Provinces @@ -3760,6 +5198,218 @@ paths: summary: Update Provinces tags: - Untags + /sales-agents: + get: + description: API for getting all SalesAgents + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - in: query + name: agent_type + type: string + - in: query + name: job_title + type: string + - in: query + name: name + type: string + - in: query + name: count + type: integer + - in: query + name: limit + type: integer + - in: query + name: nextPage + type: integer + - in: query + name: page + type: integer + - in: query + name: previousPage + type: integer + - in: query + name: sort + type: string + - in: query + name: sortBy + type: string + - in: query + name: totalPage + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get all SalesAgents + tags: + - SalesAgents + post: + description: API for creating SalesAgent + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.SalesAgentsCreateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Create SalesAgent + tags: + - SalesAgents + /sales-agents/{id}: + delete: + description: API for deleting SalesAgent (soft delete) + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: SalesAgent ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Delete SalesAgent + tags: + - SalesAgents + get: + description: API for getting SalesAgent by ID + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: SalesAgent ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Get SalesAgent by ID + tags: + - SalesAgents + put: + description: API for updating SalesAgent + parameters: + - description: Insert the X-Client-Key + in: header + name: X-Client-Key + required: true + type: string + - description: SalesAgent ID + in: path + name: id + required: true + type: integer + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.SalesAgentsUpdateRequest' + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Update SalesAgent + tags: + - SalesAgents /user-levels: get: description: API for getting all UserLevels diff --git a/main.go b/main.go index 908a478..0417094 100644 --- a/main.go +++ b/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,