From 95ce94324037f99f98bd4106dc3bc393dfa1a307 Mon Sep 17 00:00:00 2001 From: hanif salafi Date: Mon, 24 Feb 2025 12:28:06 +0700 Subject: [PATCH] feat: update go scheduler, article --- app/database/entity/articles.entity.go | 1 + app/module/articles/articles.module.go | 1 + .../controller/articles.controller.go | 32 +++++++++++ .../repository/articles.repository.go | 9 +++ .../articles/service/articles.service.go | 55 +++++++++++++++++++ config/toml/config.toml | 2 +- config/webserver/webserver.config.go | 7 ++- 7 files changed, 105 insertions(+), 2 deletions(-) diff --git a/app/database/entity/articles.entity.go b/app/database/entity/articles.entity.go index 0d2d1ec..b2f9ae1 100644 --- a/app/database/entity/articles.entity.go +++ b/app/database/entity/articles.entity.go @@ -27,6 +27,7 @@ type Articles struct { PublishedAt *time.Time `json:"published_at" gorm:"type:timestamp"` IsDraft *bool `json:"is_draft" gorm:"type:bool;default:false"` DraftedAt *time.Time `json:"drafted_at" gorm:"type:timestamp"` + PublishSchedule *string `json:"publish_schedule" 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/module/articles/articles.module.go b/app/module/articles/articles.module.go index 5c69729..785b976 100644 --- a/app/module/articles/articles.module.go +++ b/app/module/articles/articles.module.go @@ -50,6 +50,7 @@ func (_i *ArticlesRouter) RegisterArticlesRoutes() { router.Put("/:id", articlesController.Update) router.Post("/thumbnail/:id", articlesController.SaveThumbnail) router.Get("/thumbnail/viewer/:thumbnailName", articlesController.Viewer) + router.Post("/publish-scheduling", articlesController.PublishScheduling) router.Delete("/:id", articlesController.Delete) router.Get("/statistic/summary", articlesController.SummaryStats) router.Get("/statistic/user-levels", articlesController.ArticlePerUserLevelStats) diff --git a/app/module/articles/controller/articles.controller.go b/app/module/articles/controller/articles.controller.go index e6ce1db..c4b0e32 100644 --- a/app/module/articles/controller/articles.controller.go +++ b/app/module/articles/controller/articles.controller.go @@ -26,6 +26,7 @@ type ArticlesController interface { SummaryStats(c *fiber.Ctx) error ArticlePerUserLevelStats(c *fiber.Ctx) error ArticleMonthlyStats(c *fiber.Ctx) error + PublishScheduling(c *fiber.Ctx) error } func NewArticlesController(articlesService service.ArticlesService) ArticlesController { @@ -328,3 +329,34 @@ func (_i *articlesController) ArticleMonthlyStats(c *fiber.Ctx) error { Data: response, }) } + +// PublishScheduling Articles +// @Summary PublishScheduling Articles +// @Description API for Publish Schedule of Article +// @Tags Articles +// @Security Bearer +// @Param Authorization header string true "Insert your access token" default(Bearer ) +// @Param id query int false "article id" +// @Param date query string false "publish date" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /articles/publish-scheduling [post] +func (_i *articlesController) PublishScheduling(c *fiber.Ctx) error { + id, err := strconv.ParseUint(c.Query("id"), 10, 0) + if err != nil { + return err + } + date := c.Query("date") + + err = _i.articlesService.PublishScheduling(uint(id), date) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"Publish Scheduling of Articles successfully saved"}, + }) +} diff --git a/app/module/articles/repository/articles.repository.go b/app/module/articles/repository/articles.repository.go index fed9d65..1deb322 100644 --- a/app/module/articles/repository/articles.repository.go +++ b/app/module/articles/repository/articles.repository.go @@ -20,6 +20,7 @@ type articlesRepository struct { // ArticlesRepository define interface of IArticlesRepository type ArticlesRepository interface { GetAll(req request.ArticlesQueryRequest) (articless []*entity.Articles, paging paginator.Pagination, err error) + GetAllPublishSchedule() (articless []*entity.Articles, err error) FindOne(id uint) (articles *entity.Articles, err error) FindByFilename(thumbnailName string) (articleReturn *entity.Articles, err error) Create(articles *entity.Articles) (articleReturn *entity.Articles, err error) @@ -102,6 +103,14 @@ func (_i *articlesRepository) GetAll(req request.ArticlesQueryRequest) (articles return } +func (_i *articlesRepository) GetAllPublishSchedule() (articles []*entity.Articles, err error) { + err = _i.DB.DB.Where("publish_schedule IS NOT NULL").Find(&articles).Error + if err != nil { + return nil, err + } + return articles, nil +} + func (_i *articlesRepository) FindOne(id uint) (articles *entity.Articles, err error) { if err := _i.DB.DB.First(&articles, id).Error; err != nil { return nil, err diff --git a/app/module/articles/service/articles.service.go b/app/module/articles/service/articles.service.go index 340cc30..ddf82fb 100644 --- a/app/module/articles/service/articles.service.go +++ b/app/module/articles/service/articles.service.go @@ -59,6 +59,8 @@ type ArticlesService interface { SummaryStats(authToken string) (summaryStats *response.ArticleSummaryStats, err error) ArticlePerUserLevelStats(authToken string, startDate *string, endDate *string) (articlePerUserLevelStats []*response.ArticlePerUserLevelStats, err error) ArticleMonthlyStats(authToken string, year *int) (articleMonthlyStats []*response.ArticleMonthlyStats, err error) + PublishScheduling(id uint, publishSchedule string) error + ExecuteScheduling() error } // NewArticlesService init ArticlesService @@ -180,6 +182,7 @@ func (_i *articlesService) Save(req request.ArticlesCreateRequest, authToken str // Approval statusIdOne := 1 statusIdTwo := 2 + isPublishFalse := false createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) if createdBy != nil && *createdBy.UserLevel.IsApprovalActive == true { newReq.NeedApprovalFrom = nil @@ -187,6 +190,8 @@ func (_i *articlesService) Save(req request.ArticlesCreateRequest, authToken str } else { newReq.NeedApprovalFrom = &userParentLevelId newReq.StatusId = &statusIdOne + newReq.IsPublish = &isPublishFalse + newReq.PublishedAt = nil } saveArticleRes, err := _i.Repo.Create(newReq) @@ -554,6 +559,56 @@ func (_i *articlesService) UpdateApproval(id uint, statusId int, userLevelId int return } +func (_i *articlesService) PublishScheduling(id uint, publishSchedule string) error { + result, err := _i.Repo.FindOne(id) + if err != nil { + return err + } + result.PublishSchedule = &publishSchedule + + return _i.Repo.Update(id, result) +} + +func (_i *articlesService) ExecuteScheduling() error { + articles, err := _i.Repo.GetAllPublishSchedule() + if err != nil { + return err + } + + layout := "2006-01-02" + now := time.Now() + today := now.Truncate(24 * time.Hour) + + for _, article := range articles { // Looping setiap artikel + if article.PublishSchedule == nil { + continue + } + + parsedDate, err := time.Parse(layout, *article.PublishSchedule) + if err != nil { + continue + } + + if parsedDate.Equal(today) { + isPublish := true + statusIdTwo := 2 + + article.PublishSchedule = nil + article.IsPublish = &isPublish + article.PublishedAt = &now + article.StatusId = &statusIdTwo + + if err := _i.Repo.Update(article.ID, article); err != nil { + _i.Log.Info().Str("timestamp", time.Now(). + Format(time.RFC3339)).Str("Service:articlesService", "Methods:ExecuteScheduling"). + Interface("Failed to publish Article ID : ", article.ID).Msg("") + } + } + } + + return err +} + func getFileExtension(filename string) string { // split file name parts := strings.Split(filename, ".") diff --git a/config/toml/config.toml b/config/toml/config.toml index 57b179b..0a8939f 100644 --- a/config/toml/config.toml +++ b/config/toml/config.toml @@ -14,7 +14,7 @@ body-limit = 1048576000 # "100 * 1024 * 1024" [db.postgres] dsn = "postgresql://humas_user:HumasDB@2024@38.47.180.165:5432/humas_db" # ://:@:/ log-mode = "NONE" -migrate = false +migrate = true seed = false [logger] diff --git a/config/webserver/webserver.config.go b/config/webserver/webserver.config.go index a1dbd09..9640007 100644 --- a/config/webserver/webserver.config.go +++ b/config/webserver/webserver.config.go @@ -11,6 +11,7 @@ import ( "go-humas-be/app/database" "go-humas-be/app/database/seeds" md "go-humas-be/app/middleware" + articlesService "go-humas-be/app/module/articles/service" "go-humas-be/app/router" "go-humas-be/config/config" "go-humas-be/utils/response" @@ -149,12 +150,16 @@ func Start(lifecycle fx.Lifecycle, cfg *config.Config, fiber *fiber.App, router ) } -func RunScheduling(lifecycle fx.Lifecycle) *gocron.Scheduler { +func RunScheduling(lifecycle fx.Lifecycle, articleService articlesService.ArticlesService) *gocron.Scheduler { scheduler := gocron.NewScheduler(time.UTC) // Tambahkan tugas yang berjalan setiap 10 detik scheduler.Every(1).Minutes().SingletonMode().Do(func() { fmt.Println("Run Scheduler", time.Now()) + err := articleService.ExecuteScheduling() + if err != nil { + fmt.Println("Scheduler Got An Error", time.Now()) + } }) // Menambahkan lifecycle hooks di Fx