customers.prisma 4.1 KB

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