email service and template using resend
This commit is contained in:
@@ -467,6 +467,51 @@ model Refund {
|
||||
@@index([status, createdAt])
|
||||
}
|
||||
|
||||
/// Log append-only setiap email yang berhasil terkirim. `idempotencyKey`
|
||||
/// UNIQUE cegah double-send saat webhook retry / cron rerun.
|
||||
model EmailSent {
|
||||
id String @id @default(cuid())
|
||||
idempotencyKey String @unique
|
||||
to String
|
||||
template String
|
||||
subject String
|
||||
/// ID dari Resend (atau provider lain) untuk troubleshooting di dashboard mereka.
|
||||
providerMessageId String?
|
||||
sentAt DateTime @default(now())
|
||||
|
||||
@@index([to, sentAt(sort: Desc)])
|
||||
@@index([template, sentAt(sort: Desc)])
|
||||
}
|
||||
|
||||
/// Retry queue untuk email yang gagal saat sync send. Cron pick PENDING/FAILED
|
||||
/// (attempts<5) → retry dengan exponential backoff. Idempotent via `idempotencyKey`.
|
||||
model EmailJob {
|
||||
id String @id @default(cuid())
|
||||
idempotencyKey String
|
||||
to String
|
||||
template String
|
||||
subject String
|
||||
html String
|
||||
status EmailJobStatus @default(PENDING)
|
||||
attempts Int @default(0)
|
||||
scheduledAt DateTime @default(now())
|
||||
lastAttemptAt DateTime?
|
||||
lastError String?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([status, scheduledAt])
|
||||
@@index([idempotencyKey])
|
||||
}
|
||||
|
||||
enum EmailJobStatus {
|
||||
PENDING
|
||||
PROCESSING
|
||||
SUCCESS
|
||||
FAILED
|
||||
}
|
||||
|
||||
/// Log polymorphic untuk admin actions lintas entity. Append-only — kalau
|
||||
/// admin dihapus, `adminId` di-set NULL tapi `adminEmail` snapshot tetap.
|
||||
/// Dipakai untuk compliance & investigasi (siapa approve/reject/cancel/
|
||||
|
||||
Reference in New Issue
Block a user