Fix BASE_URL config loading, add tasks/projects; robust .env path resolution
- Config: try ENV_FILE, .env, ../.env for loading; trim trailing slash from BaseURL - Log BASE_URL at server startup for verification - .env.example: document BASE_URL - Tasks, projects, tags, migrations and related API/handlers Made-with: Cursor
This commit is contained in:
123
internal/service/task_reminder.go
Normal file
123
internal/service/task_reminder.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/calendarapi/internal/models"
|
||||
"github.com/calendarapi/internal/repository"
|
||||
"github.com/calendarapi/internal/utils"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
type TaskReminderScheduler interface {
|
||||
ScheduleTaskReminder(ctx context.Context, reminderID, taskID, ownerID uuid.UUID, triggerAt time.Time) error
|
||||
}
|
||||
|
||||
type TaskReminderService struct {
|
||||
queries *repository.Queries
|
||||
scheduler TaskReminderScheduler
|
||||
}
|
||||
|
||||
func NewTaskReminderService(queries *repository.Queries, scheduler TaskReminderScheduler) *TaskReminderService {
|
||||
return &TaskReminderService{queries: queries, scheduler: scheduler}
|
||||
}
|
||||
|
||||
type CreateTaskReminderRequest struct {
|
||||
Type string
|
||||
Config map[string]interface{}
|
||||
ScheduledAt time.Time
|
||||
}
|
||||
|
||||
func (s *TaskReminderService) Create(ctx context.Context, userID uuid.UUID, taskID uuid.UUID, req CreateTaskReminderRequest) (*models.TaskReminder, error) {
|
||||
if _, err := s.queries.GetTaskByID(ctx, repository.GetTaskByIDParams{
|
||||
ID: utils.ToPgUUID(taskID),
|
||||
OwnerID: utils.ToPgUUID(userID),
|
||||
}); err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return nil, models.ErrNotFound
|
||||
}
|
||||
return nil, models.ErrInternal
|
||||
}
|
||||
|
||||
validTypes := map[string]bool{"push": true, "email": true, "webhook": true, "telegram": true, "nostr": true}
|
||||
if !validTypes[req.Type] {
|
||||
return nil, models.NewValidationError("invalid reminder type")
|
||||
}
|
||||
|
||||
configJSON := []byte("{}")
|
||||
if req.Config != nil {
|
||||
configJSON, _ = json.Marshal(req.Config)
|
||||
}
|
||||
|
||||
id := uuid.New()
|
||||
rem, err := s.queries.CreateTaskReminder(ctx, repository.CreateTaskReminderParams{
|
||||
ID: utils.ToPgUUID(id),
|
||||
TaskID: utils.ToPgUUID(taskID),
|
||||
Type: req.Type,
|
||||
Column4: configJSON,
|
||||
ScheduledAt: utils.ToPgTimestamptz(req.ScheduledAt),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, models.ErrInternal
|
||||
}
|
||||
|
||||
if s.scheduler != nil {
|
||||
_ = s.scheduler.ScheduleTaskReminder(ctx, id, taskID, userID, req.ScheduledAt)
|
||||
}
|
||||
|
||||
return taskReminderFromDB(rem), nil
|
||||
}
|
||||
|
||||
func (s *TaskReminderService) List(ctx context.Context, userID uuid.UUID, taskID uuid.UUID) ([]models.TaskReminder, error) {
|
||||
if _, err := s.queries.GetTaskByID(ctx, repository.GetTaskByIDParams{
|
||||
ID: utils.ToPgUUID(taskID),
|
||||
OwnerID: utils.ToPgUUID(userID),
|
||||
}); err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return nil, models.ErrNotFound
|
||||
}
|
||||
return nil, models.ErrInternal
|
||||
}
|
||||
|
||||
rows, err := s.queries.ListTaskReminders(ctx, utils.ToPgUUID(taskID))
|
||||
if err != nil {
|
||||
return nil, models.ErrInternal
|
||||
}
|
||||
|
||||
reminders := make([]models.TaskReminder, 0, len(rows))
|
||||
for _, r := range rows {
|
||||
reminders = append(reminders, *taskReminderFromDB(r))
|
||||
}
|
||||
return reminders, nil
|
||||
}
|
||||
|
||||
func (s *TaskReminderService) Delete(ctx context.Context, userID uuid.UUID, taskID uuid.UUID, reminderID uuid.UUID) error {
|
||||
if _, err := s.queries.GetTaskByID(ctx, repository.GetTaskByIDParams{
|
||||
ID: utils.ToPgUUID(taskID),
|
||||
OwnerID: utils.ToPgUUID(userID),
|
||||
}); err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return models.ErrNotFound
|
||||
}
|
||||
return models.ErrInternal
|
||||
}
|
||||
|
||||
return s.queries.DeleteTaskReminder(ctx, utils.ToPgUUID(reminderID))
|
||||
}
|
||||
|
||||
func taskReminderFromDB(r repository.TaskReminder) *models.TaskReminder {
|
||||
rem := &models.TaskReminder{
|
||||
ID: utils.FromPgUUID(r.ID),
|
||||
TaskID: utils.FromPgUUID(r.TaskID),
|
||||
Type: r.Type,
|
||||
ScheduledAt: utils.FromPgTimestamptz(r.ScheduledAt),
|
||||
CreatedAt: utils.FromPgTimestamptz(r.CreatedAt),
|
||||
}
|
||||
if len(r.Config) > 0 {
|
||||
json.Unmarshal(r.Config, &rem.Config)
|
||||
}
|
||||
return rem
|
||||
}
|
||||
Reference in New Issue
Block a user