package repository import ( "context" "encoding/json" dbgen "Yimaru-Backend/gen/db" "Yimaru-Backend/internal/domain" "github.com/jackc/pgx/v5/pgtype" ) /* ========================= Create ========================= */ func (r *Store) CreateScheduledNotification( ctx context.Context, sn *domain.ScheduledNotification, ) (*domain.ScheduledNotification, error) { params := dbgen.CreateScheduledNotificationParams{ Channel: string(sn.Channel), Title: pgtype.Text{String: sn.Title, Valid: sn.Title != ""}, Message: sn.Message, Html: pgtype.Text{String: sn.HTML, Valid: sn.HTML != ""}, ScheduledAt: pgtype.Timestamptz{Time: sn.ScheduledAt, Valid: true}, TargetUserIds: sn.TargetUserIDs, TargetRole: pgtype.Text{String: sn.TargetRole, Valid: sn.TargetRole != ""}, TargetRaw: json.RawMessage(sn.TargetRaw), CreatedBy: sn.CreatedBy, } dbRow, err := r.queries.CreateScheduledNotification(ctx, params) if err != nil { return nil, err } return mapScheduledDBToDomain(&dbRow), nil } /* ========================= Read ========================= */ func (r *Store) GetScheduledNotification( ctx context.Context, id int64, ) (*domain.ScheduledNotification, error) { dbRow, err := r.queries.GetScheduledNotification(ctx, id) if err != nil { return nil, err } return mapScheduledDBToDomain(&dbRow), nil } func (r *Store) ListScheduledNotifications( ctx context.Context, filter domain.ScheduledNotificationFilter, ) ([]domain.ScheduledNotification, int64, error) { filterParams := dbgen.ListScheduledNotificationsParams{ FilterStatus: pgtype.Text{String: filter.Status, Valid: filter.Status != ""}, FilterChannel: pgtype.Text{String: filter.Channel, Valid: filter.Channel != ""}, PageLimit: int32(filter.Limit), PageOffset: int32(filter.Offset), } countParams := dbgen.CountScheduledNotificationsParams{ FilterStatus: filterParams.FilterStatus, FilterChannel: filterParams.FilterChannel, } if filter.After != nil { v := pgtype.Timestamptz{Time: *filter.After, Valid: true} filterParams.FilterAfter = v countParams.FilterAfter = v } if filter.Before != nil { v := pgtype.Timestamptz{Time: *filter.Before, Valid: true} filterParams.FilterBefore = v countParams.FilterBefore = v } rows, err := r.queries.ListScheduledNotifications(ctx, filterParams) if err != nil { return nil, 0, err } total, err := r.queries.CountScheduledNotifications(ctx, countParams) if err != nil { return nil, 0, err } result := make([]domain.ScheduledNotification, 0, len(rows)) for _, row := range rows { result = append(result, *mapScheduledDBToDomain(&row)) } return result, total, nil } /* ========================= Update ========================= */ func (r *Store) CancelScheduledNotification( ctx context.Context, id int64, ) (*domain.ScheduledNotification, error) { dbRow, err := r.queries.CancelScheduledNotification(ctx, id) if err != nil { return nil, err } return mapScheduledDBToDomain(&dbRow), nil } func (r *Store) ClaimDueScheduledNotifications( ctx context.Context, limit int32, ) ([]domain.ScheduledNotification, error) { rows, err := r.queries.ClaimDueScheduledNotifications(ctx, limit) if err != nil { return nil, err } result := make([]domain.ScheduledNotification, 0, len(rows)) for _, row := range rows { result = append(result, *mapScheduledDBToDomain(&row)) } return result, nil } func (r *Store) MarkScheduledNotificationSent( ctx context.Context, id int64, ) error { return r.queries.MarkScheduledNotificationSent(ctx, id) } func (r *Store) MarkScheduledNotificationFailed( ctx context.Context, id int64, lastError string, ) error { return r.queries.MarkScheduledNotificationFailed(ctx, dbgen.MarkScheduledNotificationFailedParams{ ID: id, LastError: pgtype.Text{String: lastError, Valid: lastError != ""}, }) } /* ========================= Mapping ========================= */ func mapScheduledDBToDomain(db *dbgen.ScheduledNotification) *domain.ScheduledNotification { sn := &domain.ScheduledNotification{ ID: db.ID, Channel: domain.DeliveryChannel(db.Channel), Message: db.Message, ScheduledAt: db.ScheduledAt.Time, Status: domain.ScheduledNotificationStatus(db.Status), TargetUserIDs: db.TargetUserIds, TargetRaw: json.RawMessage(db.TargetRaw), AttemptCount: db.AttemptCount, CreatedBy: db.CreatedBy, CreatedAt: db.CreatedAt.Time, UpdatedAt: db.UpdatedAt.Time, } if db.Title.Valid { sn.Title = db.Title.String } if db.Html.Valid { sn.HTML = db.Html.String } if db.TargetRole.Valid { sn.TargetRole = db.TargetRole.String } if db.LastError.Valid { sn.LastError = db.LastError.String } if db.ProcessingStartedAt.Valid { t := db.ProcessingStartedAt.Time sn.ProcessingStartedAt = &t } if db.SentAt.Valid { t := db.SentAt.Time sn.SentAt = &t } if db.CancelledAt.Valid { t := db.CancelledAt.Time sn.CancelledAt = &t } return sn }