organization.prisma 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. model AppSetting {
  2. id String @id @default(cuid())
  3. key String
  4. value String
  5. userId String
  6. user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  7. organizationId String?
  8. organization Organization? @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  9. @@unique([organizationId, key])
  10. @@index([organizationId])
  11. @@map("app_settings")
  12. }
  13. /// A user-defined dashboard card: a named, filtered table over one entity.
  14. /// The config shape (entity, filters, columns, limit) is validated against
  15. /// the field registry in customCardActions — nothing here reaches SQL raw.
  16. model DashboardWidget {
  17. id String @id @default(cuid())
  18. name String
  19. config Json
  20. userId String
  21. user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  22. organizationId String
  23. createdAt DateTime @default(now())
  24. updatedAt DateTime @updatedAt
  25. @@index([userId, organizationId])
  26. @@map("dashboard_widgets")
  27. }
  28. model Organization {
  29. id String @id @default(cuid())
  30. name String
  31. portalSlug String? @unique
  32. /// The secret in this workshop's reply address (`reply-<token>@…`) on the
  33. /// cloud instance. Minted by the first customer mail that needs one; never
  34. /// the organization id, which anyone could guess.
  35. replyMailToken String? @unique
  36. createdAt DateTime @default(now())
  37. updatedAt DateTime @updatedAt
  38. members OrganizationMember[]
  39. roles Role[]
  40. vehicles Vehicle[]
  41. serviceRecords ServiceRecord[]
  42. reminders Reminder[]
  43. customers Customer[]
  44. quotes Quote[]
  45. inventoryParts InventoryPart[]
  46. laborPresets LaborPreset[]
  47. customFieldDefinitions CustomFieldDefinition[]
  48. settings AppSetting[]
  49. emailTemplates EmailTemplate[]
  50. subscription Subscription?
  51. invitations TeamInvitation[]
  52. inspectionTemplates InspectionTemplate[]
  53. conditionMarks ConditionMark[]
  54. conditionMarkTypes ConditionMarkType[]
  55. smsMessages SmsMessage[]
  56. telegramMessages TelegramMessage[]
  57. whatsappMessages WhatsappMessage[]
  58. emailMessages EmailMessage[]
  59. technicians Technician[]
  60. workBays WorkBay[]
  61. timeEntries TimeEntry[]
  62. pushDevices PushDevice[]
  63. appSetupCodes TechnicianSetupCode[]
  64. scopedSessions Session[]
  65. technicianLoginCodes TechnicianLoginCode[]
  66. auditLogs AuditLog[]
  67. statusReports StatusReport[]
  68. reportSchedules ReportSchedule[]
  69. scheduledMessages ScheduledMessage[]
  70. webhooks Webhook[]
  71. stockMovements StockMovement[]
  72. tireWarehouses TireWarehouse[]
  73. tireLocations TireLocation[]
  74. tireSets TireSet[]
  75. workOrderStatuses WorkOrderStatus[]
  76. tireSetAttachments TireSetAttachment[]
  77. tireMovements TireMovement[]
  78. tireTreatments TireTreatment[]
  79. integrationConnections IntegrationConnection[]
  80. externalCalendarEvents ExternalCalendarEvent[]
  81. importBatches ImportBatch[]
  82. vehicleInspectionStatuses VehicleInspectionStatus[]
  83. inspectionReminderCampaigns InspectionReminderCampaign[]
  84. inspectionReminderSends InspectionReminderSend[]
  85. documentDesigns DocumentDesign[]
  86. documentDesignSnapshots DocumentDesignSnapshot[]
  87. documentAssetSnapshots DocumentAssetSnapshot[]
  88. backupRuns BackupRun[]
  89. platformBackup PlatformBackup?
  90. @@map("organizations")
  91. }
  92. model OrganizationMember {
  93. id String @id @default(cuid())
  94. role String @default("member")
  95. userId String
  96. user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  97. organizationId String
  98. organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  99. roleId String?
  100. customRole Role? @relation(fields: [roleId], references: [id], onDelete: SetNull)
  101. signature MemberSignature?
  102. @@unique([userId, organizationId])
  103. @@map("organization_members")
  104. }
  105. /// A member's handwritten signature, drawn or uploaded in account settings,
  106. /// for the Signature section of the documents they issue.
  107. ///
  108. /// Kept per workshop rather than per person: a mechanic who works for two
  109. /// shops signs each one's paper, and leaving a workshop takes the signature
  110. /// with the membership. The image is held in the row (a PNG or JPEG of a few
  111. /// kilobytes) so a document can print it without the upload folder, and so
  112. /// replacing it never touches a file an issued invoice still needs; issued
  113. /// documents keep their own copy in DocumentAssetSnapshot.
  114. model MemberSignature {
  115. id String @id @default(cuid())
  116. memberId String @unique
  117. member OrganizationMember @relation(fields: [memberId], references: [id], onDelete: Cascade)
  118. mimeType String
  119. data Bytes
  120. createdAt DateTime @default(now())
  121. updatedAt DateTime @updatedAt
  122. @@map("member_signatures")
  123. }
  124. model Role {
  125. id String @id @default(cuid())
  126. name String
  127. isAdmin Boolean @default(false)
  128. createdAt DateTime @default(now())
  129. updatedAt DateTime @updatedAt
  130. organizationId String
  131. organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  132. permissions Permission[]
  133. members OrganizationMember[]
  134. teamInvitations TeamInvitation[]
  135. @@unique([organizationId, name])
  136. @@map("roles")
  137. }
  138. model Permission {
  139. id String @id @default(cuid())
  140. action String
  141. subject String
  142. roleId String
  143. role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
  144. @@unique([roleId, action, subject])
  145. @@index([roleId])
  146. @@map("permissions")
  147. }
  148. model SystemSetting {
  149. id String @id @default(cuid())
  150. key String @unique
  151. value String
  152. @@map("system_settings")
  153. }
  154. model TeamInvitation {
  155. id String @id @default(cuid())
  156. email String
  157. role String @default("member")
  158. token String @unique
  159. status String @default("pending") // pending | accepted | cancelled
  160. expiresAt DateTime
  161. createdAt DateTime @default(now())
  162. organizationId String
  163. organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  164. invitedById String
  165. roleId String?
  166. customRole Role? @relation(fields: [roleId], references: [id], onDelete: SetNull)
  167. @@unique([email, organizationId])
  168. @@index([token])
  169. @@map("team_invitations")
  170. }
  171. /// Customer mail a workshop sent through the platform's own address in one
  172. /// day, for the daily cap on plans without custom email
  173. /// (src/features/email/Lib/emailAllowance.ts). In the database rather than in
  174. /// memory, so a restart or a second server does not hand out a fresh allowance.
  175. /// A slot is taken just before a mail goes out and given back if it fails.
  176. model PlatformMailUsage {
  177. organizationId String
  178. /// The UTC day, YYYY-MM-DD
  179. day String
  180. count Int @default(0)
  181. @@id([organizationId, day])
  182. @@map("platform_mail_usage")
  183. }