fix notifications
Build & Push / Pipeline Tests (push) Failing after 1m8s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Successful in 53s
Test / API Unit Tests (push) Failing after 52s
Test / Homepage Unit Tests (push) Successful in 46s
Test / Carplace Unit Tests (push) Successful in 43s
Test / Admin Unit Tests (push) Successful in 43s
Test / Dashboard Unit Tests (push) Successful in 46s
Test / API Integration Tests (push) Successful in 1m7s

This commit is contained in:
root
2026-07-22 22:31:39 -04:00
parent bcabd17220
commit f6fcd7ce54
26 changed files with 1171 additions and 361 deletions
+118
View File
@@ -488,6 +488,27 @@ enum NotificationStatus {
READ
}
enum NotificationRecipientType {
EMPLOYEE
RENTER
}
enum NotificationDeliveryStatus {
PENDING
QUEUED
SENT
DELIVERED
FAILED
SKIPPED
DEAD_LETTER
}
enum NotificationOutboxStatus {
PENDING
PUBLISHED
FAILED
}
enum CalendarBlockType {
MANUAL
MAINTENANCE
@@ -523,6 +544,8 @@ model Company {
insurancePolicies InsurancePolicy[]
pricingRules PricingRule[]
notifications Notification[] @relation("CompanyNotifications")
notificationEvents NotificationEvent[]
notificationDefaults CompanyNotificationPreference[]
complaints Complaint[]
companyMenuItems CompanyMenuItem[]
apiKeys CompanyApiKey[]
@@ -1013,6 +1036,7 @@ model Employee {
isActive Boolean @default(true)
notifications Notification[] @relation("EmployeeNotifications")
notificationRecipients NotificationRecipient[]
notificationPreferences NotificationPreference[]
recordedRentalPayments RentalPayment[] @relation("RecordedRentalPayments")
@@ -1208,6 +1232,7 @@ model Renter {
savedCompanies RenterSavedCompany[]
reviews Review[]
notifications Notification[] @relation("RenterNotifications")
notificationRecipients NotificationRecipient[]
notificationPreferences NotificationPreference[]
createdAt DateTime @default(now())
@@ -1509,6 +1534,87 @@ model Notification {
@@map("notifications")
}
model NotificationEvent {
id String @id @default(cuid())
companyId String
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
type NotificationType
templateKey String?
locale String @default("en")
title String
body String
data Json?
sourceType String
sourceId String
idempotencyKey String
recipients NotificationRecipient[]
outboxEntries NotificationOutbox[]
createdAt DateTime @default(now())
@@unique([companyId, idempotencyKey])
@@index([companyId, type, createdAt])
@@map("notification_events")
}
model NotificationRecipient {
id String @id @default(cuid())
notificationEventId String
notificationEvent NotificationEvent @relation(fields: [notificationEventId], references: [id], onDelete: Cascade)
recipientType NotificationRecipientType
employeeId String?
employee Employee? @relation(fields: [employeeId], references: [id], onDelete: Cascade)
renterId String?
renter Renter? @relation(fields: [renterId], references: [id], onDelete: Cascade)
readAt DateTime?
archivedAt DateTime?
deliveries NotificationDelivery[]
createdAt DateTime @default(now())
@@index([employeeId, readAt, createdAt])
@@index([renterId, readAt, createdAt])
@@index([notificationEventId])
@@map("notification_recipients")
}
model NotificationDelivery {
id String @id @default(cuid())
notificationRecipientId String
notificationRecipient NotificationRecipient @relation(fields: [notificationRecipientId], references: [id], onDelete: Cascade)
channel NotificationChannel
status NotificationDeliveryStatus @default(PENDING)
attemptCount Int @default(0)
lastAttemptAt DateTime?
nextAttemptAt DateTime?
provider String?
providerMessageId String?
failureCode String?
failureReason String?
preferenceDecision String?
sentAt DateTime?
deliveredAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([notificationRecipientId, channel])
@@index([channel, status, nextAttemptAt])
@@map("notification_deliveries")
}
model NotificationOutbox {
id String @id @default(cuid())
notificationEventId String
notificationEvent NotificationEvent @relation(fields: [notificationEventId], references: [id], onDelete: Cascade)
status NotificationOutboxStatus @default(PENDING)
payload Json
publishedAt DateTime?
failureReason String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([status, createdAt])
@@map("notification_outbox")
}
model NotificationTemplate {
id String @id @default(cuid())
templateKey String
@@ -1544,6 +1650,18 @@ model NotificationPreference {
@@map("notification_preferences")
}
model CompanyNotificationPreference {
id String @id @default(cuid())
companyId String
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
notificationType NotificationType
channel NotificationChannel
enabled Boolean @default(true)
@@unique([companyId, notificationType, channel])
@@map("company_notification_preferences")
}
// ═══════════════════════════════════════════════════════════════
// MAINTENANCE
// ═══════════════════════════════════════════════════════════════