feat: update go scheduler, article

This commit is contained in:
hanif salafi 2025-02-24 12:28:06 +07:00
parent 07a4e0eff2
commit 6c2c5a509d
7 changed files with 105 additions and 2 deletions

View File

@ -27,6 +27,7 @@ type Articles struct {
PublishedAt *time.Time `json:"published_at" gorm:"type:timestamp"` PublishedAt *time.Time `json:"published_at" gorm:"type:timestamp"`
IsDraft *bool `json:"is_draft" gorm:"type:bool;default:false"` IsDraft *bool `json:"is_draft" gorm:"type:bool;default:false"`
DraftedAt *time.Time `json:"drafted_at" gorm:"type:timestamp"` 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"` IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
CreatedAt time.Time `json:"created_at" gorm:"default:now()"` CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"` UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`

View File

@ -50,6 +50,7 @@ func (_i *ArticlesRouter) RegisterArticlesRoutes() {
router.Put("/:id", articlesController.Update) router.Put("/:id", articlesController.Update)
router.Post("/thumbnail/:id", articlesController.SaveThumbnail) router.Post("/thumbnail/:id", articlesController.SaveThumbnail)
router.Get("/thumbnail/viewer/:thumbnailName", articlesController.Viewer) router.Get("/thumbnail/viewer/:thumbnailName", articlesController.Viewer)
router.Post("/publish-scheduling", articlesController.PublishScheduling)
router.Delete("/:id", articlesController.Delete) router.Delete("/:id", articlesController.Delete)
router.Get("/statistic/summary", articlesController.SummaryStats) router.Get("/statistic/summary", articlesController.SummaryStats)
router.Get("/statistic/user-levels", articlesController.ArticlePerUserLevelStats) router.Get("/statistic/user-levels", articlesController.ArticlePerUserLevelStats)

View File

@ -26,6 +26,7 @@ type ArticlesController interface {
SummaryStats(c *fiber.Ctx) error SummaryStats(c *fiber.Ctx) error
ArticlePerUserLevelStats(c *fiber.Ctx) error ArticlePerUserLevelStats(c *fiber.Ctx) error
ArticleMonthlyStats(c *fiber.Ctx) error ArticleMonthlyStats(c *fiber.Ctx) error
PublishScheduling(c *fiber.Ctx) error
} }
func NewArticlesController(articlesService service.ArticlesService) ArticlesController { func NewArticlesController(articlesService service.ArticlesService) ArticlesController {
@ -328,3 +329,34 @@ func (_i *articlesController) ArticleMonthlyStats(c *fiber.Ctx) error {
Data: response, 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 <Add access token here>)
// @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"},
})
}

View File

@ -20,6 +20,7 @@ type articlesRepository struct {
// ArticlesRepository define interface of IArticlesRepository // ArticlesRepository define interface of IArticlesRepository
type ArticlesRepository interface { type ArticlesRepository interface {
GetAll(req request.ArticlesQueryRequest) (articless []*entity.Articles, paging paginator.Pagination, err error) 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) FindOne(id uint) (articles *entity.Articles, err error)
FindByFilename(thumbnailName string) (articleReturn *entity.Articles, err error) FindByFilename(thumbnailName string) (articleReturn *entity.Articles, err error)
Create(articles *entity.Articles) (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 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) { func (_i *articlesRepository) FindOne(id uint) (articles *entity.Articles, err error) {
if err := _i.DB.DB.First(&articles, id).Error; err != nil { if err := _i.DB.DB.First(&articles, id).Error; err != nil {
return nil, err return nil, err

View File

@ -59,6 +59,8 @@ type ArticlesService interface {
SummaryStats(authToken string) (summaryStats *response.ArticleSummaryStats, err error) SummaryStats(authToken string) (summaryStats *response.ArticleSummaryStats, err error)
ArticlePerUserLevelStats(authToken string, startDate *string, endDate *string) (articlePerUserLevelStats []*response.ArticlePerUserLevelStats, err error) ArticlePerUserLevelStats(authToken string, startDate *string, endDate *string) (articlePerUserLevelStats []*response.ArticlePerUserLevelStats, err error)
ArticleMonthlyStats(authToken string, year *int) (articleMonthlyStats []*response.ArticleMonthlyStats, err error) ArticleMonthlyStats(authToken string, year *int) (articleMonthlyStats []*response.ArticleMonthlyStats, err error)
PublishScheduling(id uint, publishSchedule string) error
ExecuteScheduling() error
} }
// NewArticlesService init ArticlesService // NewArticlesService init ArticlesService
@ -180,6 +182,7 @@ func (_i *articlesService) Save(req request.ArticlesCreateRequest, authToken str
// Approval // Approval
statusIdOne := 1 statusIdOne := 1
statusIdTwo := 2 statusIdTwo := 2
isPublishFalse := false
createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if createdBy != nil && *createdBy.UserLevel.IsApprovalActive == true { if createdBy != nil && *createdBy.UserLevel.IsApprovalActive == true {
newReq.NeedApprovalFrom = nil newReq.NeedApprovalFrom = nil
@ -187,6 +190,8 @@ func (_i *articlesService) Save(req request.ArticlesCreateRequest, authToken str
} else { } else {
newReq.NeedApprovalFrom = &userParentLevelId newReq.NeedApprovalFrom = &userParentLevelId
newReq.StatusId = &statusIdOne newReq.StatusId = &statusIdOne
newReq.IsPublish = &isPublishFalse
newReq.PublishedAt = nil
} }
saveArticleRes, err := _i.Repo.Create(newReq) saveArticleRes, err := _i.Repo.Create(newReq)
@ -554,6 +559,56 @@ func (_i *articlesService) UpdateApproval(id uint, statusId int, userLevelId int
return 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 { func getFileExtension(filename string) string {
// split file name // split file name
parts := strings.Split(filename, ".") parts := strings.Split(filename, ".")

View File

@ -14,7 +14,7 @@ body-limit = 1048576000 # "100 * 1024 * 1024"
[db.postgres] [db.postgres]
dsn = "postgresql://humas_user:HumasDB@2024@38.47.180.165:5432/humas_db" # <driver>://<username>:<password>@<host>:<port>/<database> dsn = "postgresql://humas_user:HumasDB@2024@38.47.180.165:5432/humas_db" # <driver>://<username>:<password>@<host>:<port>/<database>
log-mode = "NONE" log-mode = "NONE"
migrate = false migrate = true
seed = false seed = false
[logger] [logger]

View File

@ -11,6 +11,7 @@ import (
"go-humas-be/app/database" "go-humas-be/app/database"
"go-humas-be/app/database/seeds" "go-humas-be/app/database/seeds"
md "go-humas-be/app/middleware" md "go-humas-be/app/middleware"
articlesService "go-humas-be/app/module/articles/service"
"go-humas-be/app/router" "go-humas-be/app/router"
"go-humas-be/config/config" "go-humas-be/config/config"
"go-humas-be/utils/response" "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) scheduler := gocron.NewScheduler(time.UTC)
// Tambahkan tugas yang berjalan setiap 10 detik // Tambahkan tugas yang berjalan setiap 10 detik
scheduler.Every(1).Minutes().SingletonMode().Do(func() { scheduler.Every(1).Minutes().SingletonMode().Do(func() {
fmt.Println("Run Scheduler", time.Now()) 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 // Menambahkan lifecycle hooks di Fx