diff --git a/app/module/article_files/repository/article_files.repository.go b/app/module/article_files/repository/article_files.repository.go index d55eb82..f9d294e 100644 --- a/app/module/article_files/repository/article_files.repository.go +++ b/app/module/article_files/repository/article_files.repository.go @@ -2,13 +2,14 @@ package repository import ( "fmt" - "github.com/google/uuid" "strings" "web-medols-be/app/database" "web-medols-be/app/database/entity" "web-medols-be/app/module/article_files/request" "web-medols-be/utils/paginator" utilSvc "web-medols-be/utils/service" + + "github.com/google/uuid" ) type articleFilesRepository struct { @@ -136,7 +137,32 @@ func (_i *articleFilesRepository) Update(clientId *uuid.UUID, id uint, articleFi } } - articleFilesMap, err := utilSvc.StructToMap(articleFiles) + // Create a copy without the relation field to avoid updating non-existent columns + updateData := &entity.ArticleFiles{ + ID: articleFiles.ID, + ArticleId: articleFiles.ArticleId, + UploadID: articleFiles.UploadID, + FilePath: articleFiles.FilePath, + FileUrl: articleFiles.FileUrl, + FileName: articleFiles.FileName, + FileThumbnail: articleFiles.FileThumbnail, + FileAlt: articleFiles.FileAlt, + WidthPixel: articleFiles.WidthPixel, + HeightPixel: articleFiles.HeightPixel, + Size: articleFiles.Size, + DownloadCount: articleFiles.DownloadCount, + CreatedById: articleFiles.CreatedById, + StatusId: articleFiles.StatusId, + IsPublish: articleFiles.IsPublish, + PublishedAt: articleFiles.PublishedAt, + ClientId: articleFiles.ClientId, + IsActive: articleFiles.IsActive, + CreatedAt: articleFiles.CreatedAt, + UpdatedAt: articleFiles.UpdatedAt, + // Exclude Article relation field + } + + articleFilesMap, err := utilSvc.StructToMap(updateData) if err != nil { return err } diff --git a/app/module/article_files/service/article_files.service.go b/app/module/article_files/service/article_files.service.go index 72237f9..eef6e46 100644 --- a/app/module/article_files/service/article_files.service.go +++ b/app/module/article_files/service/article_files.service.go @@ -3,10 +3,6 @@ package service import ( "context" "fmt" - "github.com/gofiber/fiber/v2" - "github.com/google/uuid" - "github.com/minio/minio-go/v7" - "github.com/rs/zerolog" "io" "log" "math/rand" @@ -25,6 +21,11 @@ import ( config "web-medols-be/config/config" minioStorage "web-medols-be/config/config" "web-medols-be/utils/paginator" + + "github.com/gofiber/fiber/v2" + "github.com/google/uuid" + "github.com/minio/minio-go/v7" + "github.com/rs/zerolog" ) // ArticleFilesService diff --git a/app/module/articles/controller/articles.controller.go b/app/module/articles/controller/articles.controller.go index c7d1b07..851744e 100644 --- a/app/module/articles/controller/articles.controller.go +++ b/app/module/articles/controller/articles.controller.go @@ -473,14 +473,14 @@ func (_i *articlesController) ArticleMonthlyStats(c *fiber.Ctx) error { // PublishScheduling Articles // @Summary PublishScheduling Articles -// @Description API for Publish Schedule of Article +// @Description API for Publish Schedule of Article. Supports both date-only format (2006-01-02) and datetime format (2006-01-02 15:04:05) // @Tags Articles // @Security Bearer // @Param X-Client-Key header string true "Insert the X-Client-Key" // @Param X-Csrf-Token header string false "Insert the X-Csrf-Token" // @Param Authorization header string false "Insert your access token" default(Bearer ) // @Param id query int false "article id" -// @Param date query string false "publish date" +// @Param date query string false "publish date/time (format: 2006-01-02 or 2006-01-02 15:04:05)" // @Success 200 {object} response.Response // @Failure 400 {object} response.BadRequestError // @Failure 401 {object} response.UnauthorizedError diff --git a/app/module/articles/service/articles.service.go b/app/module/articles/service/articles.service.go index 94e574c..4839e79 100644 --- a/app/module/articles/service/articles.service.go +++ b/app/module/articles/service/articles.service.go @@ -663,6 +663,21 @@ func (_i *articlesService) PublishScheduling(clientId *uuid.UUID, id uint, publi if err != nil { return err } + + // Validate publish schedule format + dateLayout := "2006-01-02" + datetimeLayout := "2006-01-02 15:04:05" + + // Try parsing as datetime first (with time) + _, parseErr := time.Parse(datetimeLayout, publishSchedule) + if parseErr != nil { + // If datetime parsing fails, try parsing as date only + _, parseErr = time.Parse(dateLayout, publishSchedule) + if parseErr != nil { + return fmt.Errorf("invalid publish schedule format. Supported formats: '2006-01-02' or '2006-01-02 15:04:05'") + } + } + result.PublishSchedule = &publishSchedule return _i.Repo.Update(clientId, id, result) } @@ -683,21 +698,47 @@ func (_i *articlesService) ExecuteScheduling() error { return err } - layout := "2006-01-02" + // Support both date-only and datetime formats + dateLayout := "2006-01-02" + datetimeLayout := "2006-01-02 15:04:05" 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 + var scheduledTime time.Time + var parseErr error + + // Try parsing as datetime first (with time) + scheduledTime, parseErr = time.Parse(datetimeLayout, *article.PublishSchedule) + if parseErr != nil { + // If datetime parsing fails, try parsing as date only + scheduledTime, parseErr = time.Parse(dateLayout, *article.PublishSchedule) + if parseErr != nil { + _i.Log.Warn().Str("timestamp", time.Now(). + Format(time.RFC3339)).Str("Service:articlesService", "Methods:ExecuteScheduling"). + Str("Invalid schedule format", *article.PublishSchedule). + Interface("Article ID", article.ID).Msg("") + continue + } + // If parsed as date only, set time to start of day (00:00:00) + scheduledTime = scheduledTime.Truncate(24 * time.Hour) } - if parsedDate.Equal(today) { + // Check if the scheduled time has passed (for datetime) or if it's today (for date only) + shouldPublish := false + if len(*article.PublishSchedule) > 10 { // Contains time (datetime format) + // For datetime format, check if scheduled time has passed + shouldPublish = now.After(scheduledTime) || now.Equal(scheduledTime) + } else { + // For date-only format, check if it's today + today := now.Truncate(24 * time.Hour) + shouldPublish = scheduledTime.Equal(today) + } + + if shouldPublish { isPublish := true statusIdTwo := 2 @@ -711,6 +752,10 @@ func (_i *articlesService) ExecuteScheduling() error { _i.Log.Info().Str("timestamp", time.Now(). Format(time.RFC3339)).Str("Service:articlesService", "Methods:ExecuteScheduling"). Interface("Failed to publish Article ID : ", article.ID).Msg("") + } else { + _i.Log.Info().Str("timestamp", time.Now(). + Format(time.RFC3339)).Str("Service:articlesService", "Methods:ExecuteScheduling"). + Interface("Successfully published Article ID : ", article.ID).Msg("") } } } diff --git a/docs/swagger/docs.go b/docs/swagger/docs.go index 8a8731b..102db9d 100644 --- a/docs/swagger/docs.go +++ b/docs/swagger/docs.go @@ -7240,7 +7240,7 @@ const docTemplate = `{ "Bearer": [] } ], - "description": "API for Publish Schedule of Article", + "description": "API for Publish Schedule of Article. Supports both date-only format (2006-01-02) and datetime format (2006-01-02 15:04:05)", "tags": [ "Articles" ], @@ -7274,7 +7274,7 @@ const docTemplate = `{ }, { "type": "string", - "description": "publish date", + "description": "publish date/time (format: 2006-01-02 or 2006-01-02 15:04:05)", "name": "date", "in": "query" } diff --git a/docs/swagger/swagger.json b/docs/swagger/swagger.json index 96c0f19..81ddcd5 100644 --- a/docs/swagger/swagger.json +++ b/docs/swagger/swagger.json @@ -7229,7 +7229,7 @@ "Bearer": [] } ], - "description": "API for Publish Schedule of Article", + "description": "API for Publish Schedule of Article. Supports both date-only format (2006-01-02) and datetime format (2006-01-02 15:04:05)", "tags": [ "Articles" ], @@ -7263,7 +7263,7 @@ }, { "type": "string", - "description": "publish date", + "description": "publish date/time (format: 2006-01-02 or 2006-01-02 15:04:05)", "name": "date", "in": "query" } diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index f7b45e6..949fcf0 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -6285,7 +6285,8 @@ paths: - Articles /articles/publish-scheduling: post: - description: API for Publish Schedule of Article + description: API for Publish Schedule of Article. Supports both date-only format + (2006-01-02) and datetime format (2006-01-02 15:04:05) parameters: - description: Insert the X-Client-Key in: header @@ -6305,7 +6306,7 @@ paths: in: query name: id type: integer - - description: publish date + - description: 'publish date/time (format: 2006-01-02 or 2006-01-02 15:04:05)' in: query name: date type: string diff --git a/web-medols-be.exe b/web-medols-be.exe index 9409e3c..401b986 100644 Binary files a/web-medols-be.exe and b/web-medols-be.exe differ