203 lines
4.9 KiB
Go
203 lines
4.9 KiB
Go
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
|
|
}
|