customers.prisma 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. model Customer {
  2. id String @id @default(cuid())
  3. /// Human-facing customer number: auto-assigned sequentially on create,
  4. /// editable afterwards. Unique per organization (nulls allowed for
  5. /// legacy customers).
  6. customerNumber String?
  7. name String
  8. email String?
  9. phone String?
  10. address String?
  11. company String?
  12. taxId String?
  13. taxExempt Boolean @default(false)
  14. /// Asked not to receive reminders and campaigns. Honoured by every outreach flow.
  15. reminderOptOut Boolean @default(false)
  16. notes String?
  17. telegramChatId String?
  18. createdAt DateTime @default(now())
  19. updatedAt DateTime @updatedAt
  20. userId String
  21. user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  22. organizationId String?
  23. organization Organization? @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  24. vehicles Vehicle[]
  25. quotes Quote[]
  26. smsMessages SmsMessage[]
  27. telegramMessages TelegramMessage[]
  28. whatsappMessages WhatsappMessage[]
  29. emailMessages EmailMessage[]
  30. customerSessions CustomerSession[]
  31. scheduledMessages ScheduledMessage[]
  32. serviceRequests ServiceRequest[]
  33. inspectionReminders InspectionReminderSend[]
  34. serviceRecords ServiceRecord[]
  35. reminders Reminder[]
  36. tireSets TireSet[]
  37. aiChats AiChat[]
  38. /// The invoice design this customer's invoices use in place of the
  39. /// workshop's default: a fleet account that wants its own paper. An
  40. /// invoice's own choice wins over it. SetNull: a deleted design falls
  41. /// back to the default.
  42. invoiceDesignId String?
  43. invoiceDesign DocumentDesign? @relation(fields: [invoiceDesignId], references: [id], onDelete: SetNull)
  44. importBatchId String?
  45. importBatch ImportBatch? @relation(fields: [importBatchId], references: [id], onDelete: SetNull)
  46. @@unique([organizationId, customerNumber])
  47. @@index([organizationId])
  48. @@index([importBatchId])
  49. @@index([invoiceDesignId])
  50. @@map("customers")
  51. }
  52. model CustomerSession {
  53. id String @id @default(cuid())
  54. token String @unique
  55. expiresAt DateTime
  56. createdAt DateTime @default(now())
  57. customerId String
  58. customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
  59. organizationId String
  60. @@index([token])
  61. @@index([customerId, organizationId])
  62. @@map("customer_sessions")
  63. }
  64. model CustomerMagicLink {
  65. id String @id @default(cuid())
  66. token String @unique
  67. email String
  68. organizationId String
  69. expiresAt DateTime
  70. usedAt DateTime?
  71. createdAt DateTime @default(now())
  72. @@index([token])
  73. @@map("customer_magic_links")
  74. }
  75. model CustomerSmsCode {
  76. id String @id @default(cuid())
  77. /// SHA-256 of the digits, not the digits.
  78. ///
  79. /// The code reaches the customer in a text message and lives in their head
  80. /// for a minute. It has no business also sitting in a table where reading a
  81. /// row hands over somebody's portal session.
  82. code String
  83. /// Wrong guesses so far. Six digits is a million, which sounds like plenty
  84. /// and is not: limiting by address does nothing about a hundred machines
  85. /// sharing the work. Five attempts against one code makes the space
  86. /// irrelevant, because the code is gone long before the guessing arrives.
  87. attempts Int @default(0)
  88. phone String
  89. organizationId String
  90. expiresAt DateTime
  91. usedAt DateTime?
  92. createdAt DateTime @default(now())
  93. @@index([phone, organizationId])
  94. @@index([organizationId])
  95. @@map("customer_sms_codes")
  96. }
  97. model ServiceRequest {
  98. id String @id @default(cuid())
  99. description String
  100. preferredDate DateTime?
  101. status String @default("pending")
  102. adminNotes String?
  103. createdAt DateTime @default(now())
  104. updatedAt DateTime @updatedAt
  105. customerId String
  106. customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
  107. vehicleId String
  108. vehicle Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
  109. organizationId String
  110. @@index([organizationId, status])
  111. @@index([customerId])
  112. @@map("service_requests")
  113. }