From fce142cee556f452f07002644b2c96657ee1e11d Mon Sep 17 00:00:00 2001 From: hanif salafi Date: Fri, 22 Nov 2024 22:58:15 +0700 Subject: [PATCH] add: article nulis ai --- .../entity/article_nulis_ai.entity.go | 21 + app/database/index.database.go | 1 + .../article_nulis_ai.module.go | 54 +++ .../controller/article_nulis_ai.controller.go | 230 +++++++++ .../article_nulis_ai/controller/controller.go | 16 + .../mapper/article_nulis_ai.mapper.go | 29 ++ .../repository/article_nulis_ai.repository.go | 113 +++++ .../request/article_nulis_ai.request.go | 133 +++++ .../response/article_nulis_ai.response.go | 21 + .../service/article_nulis_ai.service.go | 121 +++++ app/router/api.go | 5 + docs/swagger/docs.go | 459 ++++++++++++++++++ docs/swagger/swagger.json | 459 ++++++++++++++++++ docs/swagger/swagger.yaml | 295 +++++++++++ main.go | 2 + utils/service/string.service.go | 21 +- 16 files changed, 1979 insertions(+), 1 deletion(-) create mode 100644 app/database/entity/article_nulis_ai.entity.go create mode 100644 app/module/article_nulis_ai/article_nulis_ai.module.go create mode 100644 app/module/article_nulis_ai/controller/article_nulis_ai.controller.go create mode 100644 app/module/article_nulis_ai/controller/controller.go create mode 100644 app/module/article_nulis_ai/mapper/article_nulis_ai.mapper.go create mode 100644 app/module/article_nulis_ai/repository/article_nulis_ai.repository.go create mode 100644 app/module/article_nulis_ai/request/article_nulis_ai.request.go create mode 100644 app/module/article_nulis_ai/response/article_nulis_ai.response.go create mode 100644 app/module/article_nulis_ai/service/article_nulis_ai.service.go diff --git a/app/database/entity/article_nulis_ai.entity.go b/app/database/entity/article_nulis_ai.entity.go new file mode 100644 index 0000000..fb3d9f8 --- /dev/null +++ b/app/database/entity/article_nulis_ai.entity.go @@ -0,0 +1,21 @@ +package entity + +import "time" + +type ArticleNulisAI struct { + ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"` + NulisAiId int `json:"nulis_ai_id" gorm:"type:int4"` + ArticleId int `json:"article_id" gorm:"type:int4"` + Title string `json:"title" gorm:"type:varchar"` + Description string `json:"description" gorm:"type:varchar"` + HtmlDescription string `json:"html_description" gorm:"type:varchar"` + CategoryId int `json:"category_id" gorm:"type:int4"` + CreatorId uint `json:"creator_id" gorm:"type:int4"` + Tags string `json:"tags" gorm:"type:varchar"` + ThumbnailPath string `json:"thumbnail_path" gorm:"type:varchar"` + IsPublish bool `json:"is_publish" gorm:"type:bool"` + PublishedAt time.Time `json:"published_at" gorm:"type:timestamp"` + IsActive bool `json:"is_active" gorm:"type:bool"` + 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 898a1bf..a4c87b9 100644 --- a/app/database/index.database.go +++ b/app/database/index.database.go @@ -71,6 +71,7 @@ func Models() []interface{} { entity.ArticleCategories{}, entity.ArticleCategoryDetails{}, entity.ArticleFiles{}, + entity.ArticleNulisAI{}, entity.Cities{}, entity.CustomStaticPages{}, entity.Districts{}, diff --git a/app/module/article_nulis_ai/article_nulis_ai.module.go b/app/module/article_nulis_ai/article_nulis_ai.module.go new file mode 100644 index 0000000..f34f257 --- /dev/null +++ b/app/module/article_nulis_ai/article_nulis_ai.module.go @@ -0,0 +1,54 @@ +package article_nulis_ai + +import ( + "github.com/gofiber/fiber/v2" + "go-humas-be/app/module/article_nulis_ai/controller" + "go-humas-be/app/module/article_nulis_ai/repository" + "go-humas-be/app/module/article_nulis_ai/service" + "go.uber.org/fx" +) + +// struct of ArticleNulisAIRouter +type ArticleNulisAIRouter struct { + App *fiber.App + Controller *controller.Controller +} + +// register bulky of ArticleNulisAI module +var NewArticleNulisAIModule = fx.Options( + // register repository of ArticleNulisAI module + fx.Provide(repository.NewArticleNulisAIRepository), + + // register service of ArticleNulisAI module + fx.Provide(service.NewArticleNulisAIService), + + // register controller of ArticleNulisAI module + fx.Provide(controller.NewController), + + // register router of ArticleNulisAI module + fx.Provide(NewArticleNulisAIRouter), +) + +// init ArticleNulisAIRouter +func NewArticleNulisAIRouter(fiber *fiber.App, controller *controller.Controller) *ArticleNulisAIRouter { + return &ArticleNulisAIRouter{ + App: fiber, + Controller: controller, + } +} + +// register routes of ArticleNulisAI module +func (_i *ArticleNulisAIRouter) RegisterArticleNulisAIRoutes() { + // define controllers + articleNulisAIController := _i.Controller.ArticleNulisAI + + // define routes + _i.App.Route("/article-nulis-ai", func(router fiber.Router) { + router.Get("/", articleNulisAIController.All) + router.Get("/:id", articleNulisAIController.Show) + router.Post("/", articleNulisAIController.Save) + router.Post("/publish", articleNulisAIController.Publish) + router.Put("/:id", articleNulisAIController.Update) + router.Delete("/:id", articleNulisAIController.Delete) + }) +} diff --git a/app/module/article_nulis_ai/controller/article_nulis_ai.controller.go b/app/module/article_nulis_ai/controller/article_nulis_ai.controller.go new file mode 100644 index 0000000..0901727 --- /dev/null +++ b/app/module/article_nulis_ai/controller/article_nulis_ai.controller.go @@ -0,0 +1,230 @@ +package controller + +import ( + "github.com/gofiber/fiber/v2" + "github.com/rs/zerolog" + "go-humas-be/app/module/article_nulis_ai/request" + "go-humas-be/app/module/article_nulis_ai/service" + "go-humas-be/utils/paginator" + utilRes "go-humas-be/utils/response" + utilVal "go-humas-be/utils/validator" + "strconv" +) + +type articleNulisAIController struct { + articleNulisAIService service.ArticleNulisAIService + Log zerolog.Logger +} + +type ArticleNulisAIController interface { + All(c *fiber.Ctx) error + Show(c *fiber.Ctx) error + Save(c *fiber.Ctx) error + Update(c *fiber.Ctx) error + Publish(c *fiber.Ctx) error + Delete(c *fiber.Ctx) error +} + +func NewArticleNulisAIController(articleNulisAIService service.ArticleNulisAIService, log zerolog.Logger) ArticleNulisAIController { + return &articleNulisAIController{ + articleNulisAIService: articleNulisAIService, + Log: log, + } +} + +// All get all ArticleNulisAI +// @Summary Get all ArticleNulisAI +// @Description API for getting all ArticleNulisAI +// @Tags ArticleNulisAI +// @Security Bearer +// @Param req query request.ArticleNulisAIQueryRequest 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 /article-nulis-ai [get] +func (_i *articleNulisAIController) All(c *fiber.Ctx) error { + paginate, err := paginator.Paginate(c) + if err != nil { + return err + } + + reqContext := request.ArticleNulisAIQueryRequestContext{ + NulisAiId: c.Query("nulisAiId"), + ArticleId: c.Query("articleId"), + Title: c.Query("title"), + Description: c.Query("description"), + HtmlDescription: c.Query("htmlDescription"), + CategoryId: c.Query("categoryId"), + CreatorId: c.Query("creatorId"), + Tags: c.Query("tags"), + ThumbnailPath: c.Query("thumbnailPath"), + IsPublish: c.Query("isPublish"), + PublishedAt: c.Query("publishedAt"), + } + req := reqContext.ToParamRequest() + req.Pagination = paginate + + articleNulisAIData, paging, err := _i.articleNulisAIService.All(req) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"ArticleNulisAI list successfully retrieved"}, + Data: articleNulisAIData, + Meta: paging, + }) +} + +// Show get one ArticleNulisAI +// @Summary Get one ArticleNulisAI +// @Description API for getting one ArticleNulisAI +// @Tags ArticleNulisAI +// @Security Bearer +// @Param id path int true "ArticleNulisAI ID" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /article-nulis-ai/{id} [get] +func (_i *articleNulisAIController) Show(c *fiber.Ctx) error { + id, err := strconv.ParseUint(c.Params("id"), 10, 0) + if err != nil { + return err + } + + articleNulisAIData, err := _i.articleNulisAIService.Show(uint(id)) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"ArticleNulisAI successfully retrieved"}, + Data: articleNulisAIData, + }) +} + +// Save create ArticleNulisAI +// @Summary Create ArticleNulisAI +// @Description API for create ArticleNulisAI +// @Tags ArticleNulisAI +// @Security Bearer +// @Param payload body request.ArticleNulisAICreateRequest true "Required payload" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /article-nulis-ai [post] +func (_i *articleNulisAIController) Save(c *fiber.Ctx) error { + req := new(request.ArticleNulisAICreateRequest) + if err := utilVal.ParseAndValidate(c, req); err != nil { + return err + } + + authToken := c.Get("Authorization") + dataResult, err := _i.articleNulisAIService.Save(*req, authToken) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"ArticleNulisAI successfully created"}, + Data: dataResult, + }) +} + +// Update update ArticleNulisAI +// @Summary update ArticleNulisAI +// @Description API for update ArticleNulisAI +// @Tags ArticleNulisAI +// @Security Bearer +// @Param payload body request.ArticleNulisAIUpdateRequest true "Required payload" +// @Param id path int true "ArticleNulisAI ID" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /article-nulis-ai/{id} [put] +func (_i *articleNulisAIController) Update(c *fiber.Ctx) error { + id, err := strconv.ParseUint(c.Params("id"), 10, 0) + if err != nil { + return err + } + + req := new(request.ArticleNulisAIUpdateRequest) + if err := utilVal.ParseAndValidate(c, req); err != nil { + return err + } + + err = _i.articleNulisAIService.Update(uint(id), *req) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"ArticleNulisAI successfully updated"}, + }) +} + +// Publish publish ArticleNulisAI +// @Summary publish ArticleNulisAI +// @Description API for publish ArticleNulisAI +// @Tags ArticleNulisAI +// @Security Bearer +// @Param payload body request.ArticleNulisAIUpdateRequest true "Required payload" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /article-nulis-ai/publish [post] +func (_i *articleNulisAIController) Publish(c *fiber.Ctx) error { + req := new(request.ArticleNulisAICreateRequest) + if err := utilVal.ParseAndValidate(c, req); err != nil { + return err + } + + authToken := c.Get("Authorization") + err := _i.articleNulisAIService.Publish(*req, authToken) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"ArticleNulisAI successfully published"}, + }) +} + +// Delete delete ArticleNulisAI +// @Summary delete ArticleNulisAI +// @Description API for delete ArticleNulisAI +// @Tags ArticleNulisAI +// @Security Bearer +// @Param id path int true "ArticleNulisAI ID" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /article-nulis-ai/{id} [delete] +func (_i *articleNulisAIController) Delete(c *fiber.Ctx) error { + id, err := strconv.ParseUint(c.Params("id"), 10, 0) + if err != nil { + return err + } + + err = _i.articleNulisAIService.Delete(uint(id)) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"ArticleNulisAI successfully deleted"}, + }) +} diff --git a/app/module/article_nulis_ai/controller/controller.go b/app/module/article_nulis_ai/controller/controller.go new file mode 100644 index 0000000..03095c6 --- /dev/null +++ b/app/module/article_nulis_ai/controller/controller.go @@ -0,0 +1,16 @@ +package controller + +import ( + "github.com/rs/zerolog" + "go-humas-be/app/module/article_nulis_ai/service" +) + +type Controller struct { + ArticleNulisAI ArticleNulisAIController +} + +func NewController(ArticleNulisAIService service.ArticleNulisAIService, log zerolog.Logger) *Controller { + return &Controller{ + ArticleNulisAI: NewArticleNulisAIController(ArticleNulisAIService, log), + } +} diff --git a/app/module/article_nulis_ai/mapper/article_nulis_ai.mapper.go b/app/module/article_nulis_ai/mapper/article_nulis_ai.mapper.go new file mode 100644 index 0000000..e894c74 --- /dev/null +++ b/app/module/article_nulis_ai/mapper/article_nulis_ai.mapper.go @@ -0,0 +1,29 @@ +package mapper + +import ( + "go-humas-be/app/database/entity" + res "go-humas-be/app/module/article_nulis_ai/response" +) + +func ArticleNulisAIResponseMapper(articleNulisAIReq *entity.ArticleNulisAI) (articleNulisAIRes *res.ArticleNulisAIResponse) { + if articleNulisAIReq != nil { + articleNulisAIRes = &res.ArticleNulisAIResponse{ + ID: articleNulisAIReq.ID, + NulisAiId: articleNulisAIReq.NulisAiId, + ArticleId: articleNulisAIReq.ArticleId, + Title: articleNulisAIReq.Title, + Description: articleNulisAIReq.Description, + HtmlDescription: articleNulisAIReq.HtmlDescription, + CategoryId: articleNulisAIReq.CategoryId, + CreatorId: articleNulisAIReq.CreatorId, + Tags: articleNulisAIReq.Tags, + ThumbnailPath: articleNulisAIReq.ThumbnailPath, + IsPublish: articleNulisAIReq.IsPublish, + PublishedAt: articleNulisAIReq.PublishedAt, + IsActive: articleNulisAIReq.IsActive, + CreatedAt: articleNulisAIReq.CreatedAt, + UpdatedAt: articleNulisAIReq.UpdatedAt, + } + } + return articleNulisAIRes +} diff --git a/app/module/article_nulis_ai/repository/article_nulis_ai.repository.go b/app/module/article_nulis_ai/repository/article_nulis_ai.repository.go new file mode 100644 index 0000000..73b5921 --- /dev/null +++ b/app/module/article_nulis_ai/repository/article_nulis_ai.repository.go @@ -0,0 +1,113 @@ +package repository + +import ( + "fmt" + "github.com/rs/zerolog" + "go-humas-be/app/database" + "go-humas-be/app/database/entity" + "go-humas-be/app/module/article_nulis_ai/request" + "go-humas-be/utils/paginator" + "strings" +) + +type articleNulisAIRepository struct { + DB *database.Database + Log zerolog.Logger +} + +// ArticleNulisAIRepository define interface of IArticleNulisAIRepository +type ArticleNulisAIRepository interface { + GetAll(req request.ArticleNulisAIQueryRequest) (articleNulisAIs []*entity.ArticleNulisAI, paging paginator.Pagination, err error) + FindOne(id uint) (articleNulisAI *entity.ArticleNulisAI, err error) + Create(articleNulisAI *entity.ArticleNulisAI) (articleNulisAIReturn *entity.ArticleNulisAI, err error) + Update(id uint, articleNulisAI *entity.ArticleNulisAI) (err error) + Delete(id uint) (err error) +} + +func NewArticleNulisAIRepository(db *database.Database, logger zerolog.Logger) ArticleNulisAIRepository { + return &articleNulisAIRepository{ + DB: db, + Log: logger, + } +} + +// implement interface of IArticleNulisAIRepository +func (_i *articleNulisAIRepository) GetAll(req request.ArticleNulisAIQueryRequest) (articleNulisAIs []*entity.ArticleNulisAI, paging paginator.Pagination, err error) { + var count int64 + + query := _i.DB.DB.Model(&entity.ArticleNulisAI{}) + query = query.Where("is_active = ?", true) + + if req.NulisAiId != nil { + query = query.Where("nulis_ai_id = ?", req.NulisAiId) + } + if req.ArticleId != nil { + query = query.Where("article_id = ?", req.ArticleId) + } + if req.Title != nil && *req.Title != "" { + title := strings.ToLower(*req.Title) + query = query.Where("LOWER(title) LIKE ?", "%"+strings.ToLower(title)+"%") + } + if req.Description != nil && *req.Description != "" { + description := strings.ToLower(*req.Description) + query = query.Where("LOWER(description) LIKE ?", "%"+strings.ToLower(description)+"%") + } + if req.HtmlDescription != nil && *req.HtmlDescription != "" { + htmlDescription := strings.ToLower(*req.HtmlDescription) + query = query.Where("LOWER(html_description) LIKE ?", "%"+strings.ToLower(htmlDescription)+"%") + } + if req.CategoryId != nil { + query = query.Where("category_id = ?", req.CategoryId) + } + if req.CreatorId != nil { + query = query.Where("creator_id = ?", req.CreatorId) + } + if req.Tags != nil && *req.Tags != "" { + tags := strings.ToLower(*req.Tags) + query = query.Where("LOWER(tags) LIKE ?", "%"+strings.ToLower(tags)+"%") + } + query.Count(&count) + + if req.Pagination.SortBy != "" { + direction := "ASC" + if req.Pagination.Sort == "desc" { + direction = "DESC" + } + query.Order(fmt.Sprintf("%s %s", req.Pagination.SortBy, direction)) + } + + req.Pagination.Count = count + req.Pagination = paginator.Paging(req.Pagination) + + err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&articleNulisAIs).Error + if err != nil { + return + } + + paging = *req.Pagination + + return +} + +func (_i *articleNulisAIRepository) FindOne(id uint) (articleNulisAI *entity.ArticleNulisAI, err error) { + if err := _i.DB.DB.First(&articleNulisAI, id).Error; err != nil { + return nil, err + } + + return articleNulisAI, nil +} + +func (_i *articleNulisAIRepository) Create(articleNulisAI *entity.ArticleNulisAI) (articleNulisAIReturn *entity.ArticleNulisAI, err error) { + result := _i.DB.DB.Create(articleNulisAI) + return articleNulisAI, result.Error +} + +func (_i *articleNulisAIRepository) Update(id uint, articleNulisAI *entity.ArticleNulisAI) (err error) { + return _i.DB.DB.Model(&entity.ArticleNulisAI{}). + Where(&entity.ArticleNulisAI{ID: id}). + Updates(articleNulisAI).Error +} + +func (_i *articleNulisAIRepository) Delete(id uint) error { + return _i.DB.DB.Delete(&entity.ArticleNulisAI{}, id).Error +} diff --git a/app/module/article_nulis_ai/request/article_nulis_ai.request.go b/app/module/article_nulis_ai/request/article_nulis_ai.request.go new file mode 100644 index 0000000..70e2756 --- /dev/null +++ b/app/module/article_nulis_ai/request/article_nulis_ai.request.go @@ -0,0 +1,133 @@ +package request + +import ( + "go-humas-be/app/database/entity" + "go-humas-be/utils/paginator" + "strconv" + "time" +) + +type ArticleNulisAIGeneric interface { + ToEntity() +} + +type ArticleNulisAIQueryRequest struct { + NulisAiId *int `json:"nulisAiId"` + ArticleId *int `json:"articleId"` + Title *string `json:"title"` + Description *string `json:"description"` + HtmlDescription *string `json:"htmlDescription"` + CategoryId *int `json:"categoryId"` + CreatorId *int `json:"creatorId"` + Tags *string `json:"tags"` + Pagination *paginator.Pagination `json:"pagination"` +} + +type ArticleNulisAICreateRequest struct { + NulisAiId int `json:"nulisAiId" validate:"required"` + ArticleId int `json:"articleId" validate:"required"` + Title string `json:"title" validate:"required"` + Description string `json:"description" validate:"required"` + HtmlDescription string `json:"htmlDescription" validate:"required"` + CategoryId int `json:"categoryId" validate:"required"` + CreatorId uint `json:"creatorId" validate:"required"` + Tags string `json:"tags" validate:"required"` +} + +func (req ArticleNulisAICreateRequest) ToEntity() *entity.ArticleNulisAI { + return &entity.ArticleNulisAI{ + NulisAiId: req.NulisAiId, + ArticleId: req.ArticleId, + Title: req.Title, + Description: req.Description, + HtmlDescription: req.HtmlDescription, + CategoryId: req.CategoryId, + CreatorId: req.CreatorId, + Tags: req.Tags, + } +} + +type ArticleNulisAIUpdateRequest struct { + ID uint `json:"id" validate:"required"` + NulisAiId int `json:"nulisAiId" validate:"required"` + ArticleId int `json:"articleId" validate:"required"` + Title string `json:"title" validate:"required"` + Description string `json:"description" validate:"required"` + HtmlDescription string `json:"htmlDescription" validate:"required"` + CategoryId int `json:"categoryId" validate:"required"` + CreatorId uint `json:"creatorId" validate:"required"` + Tags string `json:"tags" validate:"required"` + UpdatedAt time.Time `json:"updated_at"` +} + +func (req ArticleNulisAIUpdateRequest) ToEntity() *entity.ArticleNulisAI { + return &entity.ArticleNulisAI{ + ID: req.ID, + NulisAiId: req.NulisAiId, + ArticleId: req.ArticleId, + Title: req.Title, + Description: req.Description, + HtmlDescription: req.HtmlDescription, + CategoryId: req.CategoryId, + CreatorId: req.CreatorId, + Tags: req.Tags, + UpdatedAt: time.Now(), + } +} + +type ArticleNulisAIQueryRequestContext struct { + NulisAiId string `json:"nulisAiId"` + ArticleId string `json:"articleId"` + Title string `json:"title"` + Description string `json:"description"` + HtmlDescription string `json:"htmlDescription"` + CategoryId string `json:"categoryId"` + CreatorId string `json:"creatorId"` + Tags string `json:"tags"` + ThumbnailPath string `json:"thumbnailPath"` + IsPublish string `json:"isPublish"` + PublishedAt string `json:"publishedAt"` +} + +func (req ArticleNulisAIQueryRequestContext) ToParamRequest() ArticleNulisAIQueryRequest { + var request ArticleNulisAIQueryRequest + + if nulisAiIdStr := req.NulisAiId; nulisAiIdStr != "" { + nulisAiId, err := strconv.Atoi(nulisAiIdStr) + if err == nil { + request.NulisAiId = &nulisAiId + } + } + if articleIdStr := req.ArticleId; articleIdStr != "" { + articleId, err := strconv.Atoi(articleIdStr) + if err == nil { + request.ArticleId = &articleId + } + } + if title := req.Title; title != "" { + request.Title = &title + } + if description := req.Description; description != "" { + request.Description = &description + } + if htmlDescription := req.HtmlDescription; htmlDescription != "" { + request.HtmlDescription = &htmlDescription + } + if categoryIdStr := req.CategoryId; categoryIdStr != "" { + categoryId, err := strconv.Atoi(categoryIdStr) + if err == nil { + request.CategoryId = &categoryId + } + } + if creatorIdStr := req.CreatorId; creatorIdStr != "" { + creatorId, err := strconv.Atoi(creatorIdStr) + if err == nil { + request.CreatorId = &creatorId + } + } + if tags := req.Tags; tags != "" { + request.Tags = &tags + } + + return request +} diff --git a/app/module/article_nulis_ai/response/article_nulis_ai.response.go b/app/module/article_nulis_ai/response/article_nulis_ai.response.go new file mode 100644 index 0000000..7d26e52 --- /dev/null +++ b/app/module/article_nulis_ai/response/article_nulis_ai.response.go @@ -0,0 +1,21 @@ +package response + +import "time" + +type ArticleNulisAIResponse struct { + ID uint `json:"id"` + NulisAiId int `json:"nulisAiId"` + ArticleId int `json:"articleId"` + Title string `json:"title"` + Description string `json:"description"` + HtmlDescription string `json:"htmlDescription"` + CategoryId int `json:"categoryId"` + CreatorId uint `json:"creatorId"` + Tags string `json:"tags"` + ThumbnailPath string `json:"thumbnailPath"` + IsPublish bool `json:"isPublish"` + PublishedAt time.Time `json:"publishedAt"` + IsActive bool `json:"isActive"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} diff --git a/app/module/article_nulis_ai/service/article_nulis_ai.service.go b/app/module/article_nulis_ai/service/article_nulis_ai.service.go new file mode 100644 index 0000000..c95eb8c --- /dev/null +++ b/app/module/article_nulis_ai/service/article_nulis_ai.service.go @@ -0,0 +1,121 @@ +package service + +import ( + "github.com/rs/zerolog" + "go-humas-be/app/database/entity" + "go-humas-be/app/module/article_nulis_ai/mapper" + "go-humas-be/app/module/article_nulis_ai/repository" + "go-humas-be/app/module/article_nulis_ai/request" + "go-humas-be/app/module/article_nulis_ai/response" + articlesRepository "go-humas-be/app/module/articles/repository" + articles "go-humas-be/app/module/articles/request" + usersRepository "go-humas-be/app/module/users/repository" + "go-humas-be/utils/paginator" + + utilSvc "go-humas-be/utils/service" +) + +// ArticleNulisAIService +type articleNulisAIService struct { + Repo repository.ArticleNulisAIRepository + UsersRepo usersRepository.UsersRepository + ArticlesRepo articlesRepository.ArticlesRepository + Log zerolog.Logger +} + +// ArticleNulisAIService define interface of IArticleNulisAIService +type ArticleNulisAIService interface { + All(req request.ArticleNulisAIQueryRequest) (articleNulisAI []*response.ArticleNulisAIResponse, paging paginator.Pagination, err error) + Show(id uint) (articleNulisAI *response.ArticleNulisAIResponse, err error) + Save(req request.ArticleNulisAICreateRequest, authToken string) (articleNulisAI *entity.ArticleNulisAI, err error) + Update(id uint, req request.ArticleNulisAIUpdateRequest) (err error) + Publish(req request.ArticleNulisAICreateRequest, authToken string) (err error) + Delete(id uint) error +} + +// NewArticleNulisAIService init ArticleNulisAIService +func NewArticleNulisAIService(repo repository.ArticleNulisAIRepository, log zerolog.Logger, usersRepo usersRepository.UsersRepository, articlesRepo articlesRepository.ArticlesRepository) ArticleNulisAIService { + + return &articleNulisAIService{ + Repo: repo, + Log: log, + UsersRepo: usersRepo, + ArticlesRepo: articlesRepo, + } +} + +// All implement interface of ArticleNulisAIService +func (_i *articleNulisAIService) All(req request.ArticleNulisAIQueryRequest) (articleNulisAIs []*response.ArticleNulisAIResponse, paging paginator.Pagination, err error) { + results, paging, err := _i.Repo.GetAll(req) + if err != nil { + return + } + + for _, result := range results { + articleNulisAIs = append(articleNulisAIs, mapper.ArticleNulisAIResponseMapper(result)) + } + + return +} + +func (_i *articleNulisAIService) Show(id uint) (articleNulisAI *response.ArticleNulisAIResponse, err error) { + result, err := _i.Repo.FindOne(id) + if err != nil { + return nil, err + } + + return mapper.ArticleNulisAIResponseMapper(result), nil +} + +func (_i *articleNulisAIService) Save(req request.ArticleNulisAICreateRequest, authToken string) (articleNulisAI *entity.ArticleNulisAI, err error) { + _i.Log.Info().Interface("data", req).Msg("") + + newReq := req.ToEntity() + + createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) + newReq.CreatorId = createdBy.ID + + return _i.Repo.Create(newReq) +} + +func (_i *articleNulisAIService) Publish(req request.ArticleNulisAICreateRequest, authToken string) (err error) { + _i.Log.Info().Interface("data", req).Msg("") + + newReq := req.ToEntity() + articleReq := articles.ArticlesCreateRequest{ + Title: newReq.Title, + Slug: utilSvc.MakeSlug(req.Title), + CategoryId: newReq.CategoryId, + Tags: newReq.Tags, + TypeId: 1, + Description: newReq.Description, + HtmlDescription: newReq.HtmlDescription, + } + + createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) + + newArticleReq := articleReq.ToEntity() + newArticleReq.CreatedById = &createdBy.ID + + _, err = _i.ArticlesRepo.Create(newArticleReq) + if err != nil { + return err + } else { + return nil + } +} + +func (_i *articleNulisAIService) Update(id uint, req request.ArticleNulisAIUpdateRequest) (err error) { + _i.Log.Info().Interface("data", req).Msg("") + return _i.Repo.Update(id, req.ToEntity()) +} + +func (_i *articleNulisAIService) Delete(id uint) error { + result, err := _i.Repo.FindOne(id) + if err != nil { + return err + } + + result.IsActive = false + return _i.Repo.Update(id, result) +} diff --git a/app/router/api.go b/app/router/api.go index b9d580b..8b482a4 100644 --- a/app/router/api.go +++ b/app/router/api.go @@ -6,6 +6,7 @@ import ( "go-humas-be/app/module/article_categories" "go-humas-be/app/module/article_category_details" "go-humas-be/app/module/article_files" + "go-humas-be/app/module/article_nulis_ai" "go-humas-be/app/module/articles" "go-humas-be/app/module/cities" "go-humas-be/app/module/custom_static_pages" @@ -31,6 +32,7 @@ type Router struct { ArticleCategoryDetailsRouter *article_category_details.ArticleCategoryDetailsRouter ArticleFilesRouter *article_files.ArticleFilesRouter ArticlesRouter *articles.ArticlesRouter + ArticleNulisAIRouter *article_nulis_ai.ArticleNulisAIRouter CitiesRouter *cities.CitiesRouter CustomStaticPagesRouter *custom_static_pages.CustomStaticPagesRouter DistrictsRouter *districts.DistrictsRouter @@ -53,6 +55,7 @@ func NewRouter( articleCategoryDetailsRouter *article_category_details.ArticleCategoryDetailsRouter, articleFilesRouter *article_files.ArticleFilesRouter, articlesRouter *articles.ArticlesRouter, + articleNulisRouter *article_nulis_ai.ArticleNulisAIRouter, citiesRouter *cities.CitiesRouter, customStaticPagesRouter *custom_static_pages.CustomStaticPagesRouter, districtsRouter *districts.DistrictsRouter, @@ -73,6 +76,7 @@ func NewRouter( ArticleCategoryDetailsRouter: articleCategoryDetailsRouter, ArticleFilesRouter: articleFilesRouter, ArticlesRouter: articlesRouter, + ArticleNulisAIRouter: articleNulisRouter, CitiesRouter: citiesRouter, CustomStaticPagesRouter: customStaticPagesRouter, DistrictsRouter: districtsRouter, @@ -103,6 +107,7 @@ func (r *Router) Register() { r.ArticleCategoryDetailsRouter.RegisterArticleCategoryDetailsRoutes() r.ArticleFilesRouter.RegisterArticleFilesRoutes() r.ArticlesRouter.RegisterArticlesRoutes() + r.ArticleNulisAIRouter.RegisterArticleNulisAIRoutes() r.CitiesRouter.RegisterCitiesRoutes() r.CustomStaticPagesRouter.RegisterCustomStaticPagesRoutes() r.DistrictsRouter.RegisterDistrictsRoutes() diff --git a/docs/swagger/docs.go b/docs/swagger/docs.go index 44e9710..9f4669d 100644 --- a/docs/swagger/docs.go +++ b/docs/swagger/docs.go @@ -1052,6 +1052,380 @@ const docTemplate = `{ } } }, + "/article-nulis-ai": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "Get all ArticleNulisAI", + "parameters": [ + { + "type": "integer", + "name": "articleId", + "in": "query" + }, + { + "type": "integer", + "name": "categoryId", + "in": "query" + }, + { + "type": "integer", + "name": "creatorId", + "in": "query" + }, + { + "type": "string", + "name": "description", + "in": "query" + }, + { + "type": "string", + "name": "htmlDescription", + "in": "query" + }, + { + "type": "integer", + "name": "nulisAiId", + "in": "query" + }, + { + "type": "string", + "name": "tags", + "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 create ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "Create ArticleNulisAI", + "parameters": [ + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ArticleNulisAICreateRequest" + } + } + ], + "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" + } + } + } + } + }, + "/article-nulis-ai/publish": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for publish ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "publish ArticleNulisAI", + "parameters": [ + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ArticleNulisAIUpdateRequest" + } + } + ], + "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" + } + } + } + } + }, + "/article-nulis-ai/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting one ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "Get one ArticleNulisAI", + "parameters": [ + { + "type": "integer", + "description": "ArticleNulisAI 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 update ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "update ArticleNulisAI", + "parameters": [ + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ArticleNulisAIUpdateRequest" + } + }, + { + "type": "integer", + "description": "ArticleNulisAI 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" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for delete ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "delete ArticleNulisAI", + "parameters": [ + { + "type": "integer", + "description": "ArticleNulisAI 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" + } + } + } + } + }, "/articles": { "get": { "security": [ @@ -5704,6 +6078,91 @@ const docTemplate = `{ } } }, + "request.ArticleNulisAICreateRequest": { + "type": "object", + "required": [ + "articleId", + "categoryId", + "creatorId", + "description", + "htmlDescription", + "nulisAiId", + "tags", + "title" + ], + "properties": { + "articleId": { + "type": "integer" + }, + "categoryId": { + "type": "integer" + }, + "creatorId": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "htmlDescription": { + "type": "string" + }, + "nulisAiId": { + "type": "integer" + }, + "tags": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.ArticleNulisAIUpdateRequest": { + "type": "object", + "required": [ + "articleId", + "categoryId", + "creatorId", + "description", + "htmlDescription", + "id", + "nulisAiId", + "tags", + "title" + ], + "properties": { + "articleId": { + "type": "integer" + }, + "categoryId": { + "type": "integer" + }, + "creatorId": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "htmlDescription": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "nulisAiId": { + "type": "integer" + }, + "tags": { + "type": "string" + }, + "title": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + } + }, "request.ArticlesCreateRequest": { "type": "object", "required": [ diff --git a/docs/swagger/swagger.json b/docs/swagger/swagger.json index 0e1fc3e..09bb41e 100644 --- a/docs/swagger/swagger.json +++ b/docs/swagger/swagger.json @@ -1041,6 +1041,380 @@ } } }, + "/article-nulis-ai": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "Get all ArticleNulisAI", + "parameters": [ + { + "type": "integer", + "name": "articleId", + "in": "query" + }, + { + "type": "integer", + "name": "categoryId", + "in": "query" + }, + { + "type": "integer", + "name": "creatorId", + "in": "query" + }, + { + "type": "string", + "name": "description", + "in": "query" + }, + { + "type": "string", + "name": "htmlDescription", + "in": "query" + }, + { + "type": "integer", + "name": "nulisAiId", + "in": "query" + }, + { + "type": "string", + "name": "tags", + "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 create ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "Create ArticleNulisAI", + "parameters": [ + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ArticleNulisAICreateRequest" + } + } + ], + "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" + } + } + } + } + }, + "/article-nulis-ai/publish": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for publish ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "publish ArticleNulisAI", + "parameters": [ + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ArticleNulisAIUpdateRequest" + } + } + ], + "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" + } + } + } + } + }, + "/article-nulis-ai/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting one ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "Get one ArticleNulisAI", + "parameters": [ + { + "type": "integer", + "description": "ArticleNulisAI 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 update ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "update ArticleNulisAI", + "parameters": [ + { + "description": "Required payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.ArticleNulisAIUpdateRequest" + } + }, + { + "type": "integer", + "description": "ArticleNulisAI 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" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for delete ArticleNulisAI", + "tags": [ + "ArticleNulisAI" + ], + "summary": "delete ArticleNulisAI", + "parameters": [ + { + "type": "integer", + "description": "ArticleNulisAI 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" + } + } + } + } + }, "/articles": { "get": { "security": [ @@ -5693,6 +6067,91 @@ } } }, + "request.ArticleNulisAICreateRequest": { + "type": "object", + "required": [ + "articleId", + "categoryId", + "creatorId", + "description", + "htmlDescription", + "nulisAiId", + "tags", + "title" + ], + "properties": { + "articleId": { + "type": "integer" + }, + "categoryId": { + "type": "integer" + }, + "creatorId": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "htmlDescription": { + "type": "string" + }, + "nulisAiId": { + "type": "integer" + }, + "tags": { + "type": "string" + }, + "title": { + "type": "string" + } + } + }, + "request.ArticleNulisAIUpdateRequest": { + "type": "object", + "required": [ + "articleId", + "categoryId", + "creatorId", + "description", + "htmlDescription", + "id", + "nulisAiId", + "tags", + "title" + ], + "properties": { + "articleId": { + "type": "integer" + }, + "categoryId": { + "type": "integer" + }, + "creatorId": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "htmlDescription": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "nulisAiId": { + "type": "integer" + }, + "tags": { + "type": "string" + }, + "title": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + } + }, "request.ArticlesCreateRequest": { "type": "object", "required": [ diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index b6491bb..bf69d81 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -90,6 +90,67 @@ definitions: - publishedAt - statusId type: object + request.ArticleNulisAICreateRequest: + properties: + articleId: + type: integer + categoryId: + type: integer + creatorId: + type: integer + description: + type: string + htmlDescription: + type: string + nulisAiId: + type: integer + tags: + type: string + title: + type: string + required: + - articleId + - categoryId + - creatorId + - description + - htmlDescription + - nulisAiId + - tags + - title + type: object + request.ArticleNulisAIUpdateRequest: + properties: + articleId: + type: integer + categoryId: + type: integer + creatorId: + type: integer + description: + type: string + htmlDescription: + type: string + id: + type: integer + nulisAiId: + type: integer + tags: + type: string + title: + type: string + updated_at: + type: string + required: + - articleId + - categoryId + - creatorId + - description + - htmlDescription + - id + - nulisAiId + - tags + - title + type: object request.ArticlesCreateRequest: properties: categoryId: @@ -1212,6 +1273,240 @@ paths: summary: Create ArticleFiles tags: - Article Files + /article-nulis-ai: + get: + description: API for getting all ArticleNulisAI + parameters: + - in: query + name: articleId + type: integer + - in: query + name: categoryId + type: integer + - in: query + name: creatorId + type: integer + - in: query + name: description + type: string + - in: query + name: htmlDescription + type: string + - in: query + name: nulisAiId + type: integer + - in: query + name: tags + 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 ArticleNulisAI + tags: + - ArticleNulisAI + post: + description: API for create ArticleNulisAI + parameters: + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.ArticleNulisAICreateRequest' + 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 ArticleNulisAI + tags: + - ArticleNulisAI + /article-nulis-ai/{id}: + delete: + description: API for delete ArticleNulisAI + parameters: + - description: ArticleNulisAI 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 ArticleNulisAI + tags: + - ArticleNulisAI + get: + description: API for getting one ArticleNulisAI + parameters: + - description: ArticleNulisAI 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 one ArticleNulisAI + tags: + - ArticleNulisAI + put: + description: API for update ArticleNulisAI + parameters: + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.ArticleNulisAIUpdateRequest' + - description: ArticleNulisAI 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: update ArticleNulisAI + tags: + - ArticleNulisAI + /article-nulis-ai/publish: + post: + description: API for publish ArticleNulisAI + parameters: + - description: Required payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/request.ArticleNulisAIUpdateRequest' + 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: publish ArticleNulisAI + tags: + - ArticleNulisAI /articles: get: description: API for getting all Articles diff --git a/main.go b/main.go index af9678c..b3ea004 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "go-humas-be/app/module/article_categories" "go-humas-be/app/module/article_category_details" "go-humas-be/app/module/article_files" + "go-humas-be/app/module/article_nulis_ai" "go-humas-be/app/module/articles" "go-humas-be/app/module/cities" "go-humas-be/app/module/custom_static_pages" @@ -54,6 +55,7 @@ func main() { article_category_details.NewArticleCategoryDetailsModule, article_files.NewArticleFilesModule, articles.NewArticlesModule, + article_nulis_ai.NewArticleNulisAIModule, cities.NewCitiesModule, custom_static_pages.NewCustomStaticPagesModule, districts.NewDistrictsModule, diff --git a/utils/service/string.service.go b/utils/service/string.service.go index 74ec275..9ed2bec 100644 --- a/utils/service/string.service.go +++ b/utils/service/string.service.go @@ -1,6 +1,9 @@ package service -import "unicode" +import ( + "strings" + "unicode" +) func IsNumeric(str string) bool { for _, char := range str { @@ -10,3 +13,19 @@ func IsNumeric(str string) bool { } return true } + +func MakeSlug(s string) string { + // Convert to lowercase + s = strings.ToLower(s) + + // Replace spaces with hyphens + s = strings.ReplaceAll(s, " ", "-") + + // Remove non-alphanumeric characters + return strings.Map(func(r rune) rune { + if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '-' { + return r + } + return -1 + }, s) +}