4
0

customers.prisma 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. customerSessions CustomerSession[]
  30. scheduledMessages ScheduledMessage[]
  31. serviceRequests ServiceRequest[]
  32. inspectionReminders InspectionReminderSend[]
  33. serviceRecords ServiceRecord[]
  34. reminders Reminder[]
  35. tireSets TireSet[]
  36. aiChats AiChat[]
  37. /// The invoice design this customer's invoices use in place of the
  38. /// workshop's default: a fleet account that wants its own paper. An
  39. /// invoice's own choice wins over it. SetNull: a deleted design falls
  40. /// back to the default.
  41. invoiceDesignId String?
  42. invoiceDesign DocumentDesign? @relation(fields: [invoiceDesignId], references: [id], onDelete: SetNull)
  43. importBatchId String?
  44. importBatch ImportBatch? @relation(fields: [importBatchId], references: [id], onDelete: SetNull)
  45. @@unique([organizationId, customerNumber])
  46. @@index([organizationId])
  47. @@index([importBatchId])
  48. @@index([invoiceDesignId])
  49. @@map("customers")
  50. }
  51. model CustomerSession {
  52. id String @id @default(cuid())
  53. token String @unique
  54. expiresAt DateTime
  55. createdAt DateTime @default(now())
  56. customerId String
  57. customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
  58. organizationId String
  59. @@index([token])
  60. @@index([customerId, organizationId])
  61. @@map("customer_sessions")
  62. }
  63. model CustomerMagicLink {
  64. id String @id @default(cuid())
  65. token String @unique
  66. email String
  67. organizationId String
  68. expiresAt DateTime
  69. usedAt DateTime?
  70. createdAt DateTime @default(now())
  71. @@index([token])
  72. @@map("customer_magic_links")
  73. }
  74. model CustomerSmsCode {
  75. id String @id @default(cuid())
  76. /// SHA-256 of the digits, not the digits.
  77. ///
  78. /// The code reaches the customer in a text message and lives in their head
  79. /// for a minute. It has no business also sitting in a table where reading a
  80. /// row hands over somebody's portal session.
  81. code String
  82. /// Wrong guesses so far. Six digits is a million, which sounds like plenty
  83. /// and is not: limiting by address does nothing about a hundred machines
  84. /// sharing the work. Five attempts against one code makes the space
  85. /// irrelevant, because the code is gone long before the guessing arrives.
  86. attempts Int @default(0)
  87. phone String
  88. organizationId String
  89. expiresAt DateTime
  90. usedAt DateTime?
  91. createdAt DateTime @default(now())
  92. @@index([phone, organizationId])
  93. @@index([organizationId])
  94. @@map("customer_sms_codes")
  95. }
  96. model ServiceRequest {
  97. id String @id @default(cuid())
  98. description String
  99. preferredDate DateTime?
  100. status String @default("pending")
  101. adminNotes String?
  102. createdAt DateTime @default(now())
  103. updatedAt DateTime @updatedAt
  104. customerId String
  105. customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
  106. vehicleId String
  107. vehicle Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
  108. organizationId String
  109. @@index([organizationId, status])
  110. @@index([customerId])
  111. @@map("service_requests")
  112. }