organization.prisma 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. workshopClosures WorkshopClosure[]
  90. technicianAbsences TechnicianAbsence[]
  91. serviceRecordHelpers ServiceRecordHelper[]
  92. platformBackup PlatformBackup?
  93. @@map("organizations")
  94. }
  95. model OrganizationMember {
  96. id String @id @default(cuid())
  97. role String @default("member")
  98. userId String
  99. user User @relation(fields: [userId], references: [id], onDelete: Cascade)
  100. organizationId String
  101. organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  102. roleId String?
  103. customRole Role? @relation(fields: [roleId], references: [id], onDelete: SetNull)
  104. signature MemberSignature?
  105. @@unique([userId, organizationId])
  106. @@map("organization_members")
  107. }
  108. /// A member's handwritten signature, drawn or uploaded in account settings,
  109. /// for the Signature section of the documents they issue.
  110. ///
  111. /// Kept per workshop rather than per person: a mechanic who works for two
  112. /// shops signs each one's paper, and leaving a workshop takes the signature
  113. /// with the membership. The image is held in the row (a PNG or JPEG of a few
  114. /// kilobytes) so a document can print it without the upload folder, and so
  115. /// replacing it never touches a file an issued invoice still needs; issued
  116. /// documents keep their own copy in DocumentAssetSnapshot.
  117. model MemberSignature {
  118. id String @id @default(cuid())
  119. memberId String @unique
  120. member OrganizationMember @relation(fields: [memberId], references: [id], onDelete: Cascade)
  121. mimeType String
  122. data Bytes
  123. createdAt DateTime @default(now())
  124. updatedAt DateTime @updatedAt
  125. @@map("member_signatures")
  126. }
  127. model Role {
  128. id String @id @default(cuid())
  129. name String
  130. isAdmin Boolean @default(false)
  131. createdAt DateTime @default(now())
  132. updatedAt DateTime @updatedAt
  133. organizationId String
  134. organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  135. permissions Permission[]
  136. members OrganizationMember[]
  137. teamInvitations TeamInvitation[]
  138. @@unique([organizationId, name])
  139. @@map("roles")
  140. }
  141. model Permission {
  142. id String @id @default(cuid())
  143. action String
  144. subject String
  145. roleId String
  146. role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
  147. @@unique([roleId, action, subject])
  148. @@index([roleId])
  149. @@map("permissions")
  150. }
  151. model SystemSetting {
  152. id String @id @default(cuid())
  153. key String @unique
  154. value String
  155. @@map("system_settings")
  156. }
  157. model TeamInvitation {
  158. id String @id @default(cuid())
  159. email String
  160. role String @default("member")
  161. token String @unique
  162. status String @default("pending") // pending | accepted | cancelled
  163. expiresAt DateTime
  164. createdAt DateTime @default(now())
  165. organizationId String
  166. organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  167. invitedById String
  168. roleId String?
  169. customRole Role? @relation(fields: [roleId], references: [id], onDelete: SetNull)
  170. @@unique([email, organizationId])
  171. @@index([token])
  172. @@map("team_invitations")
  173. }
  174. /// Customer mail a workshop sent through the platform's own address in one
  175. /// day, for the daily cap on plans without custom email
  176. /// (src/features/email/Lib/emailAllowance.ts). In the database rather than in
  177. /// memory, so a restart or a second server does not hand out a fresh allowance.
  178. /// A slot is taken just before a mail goes out and given back if it fails.
  179. model PlatformMailUsage {
  180. organizationId String
  181. /// The UTC day, YYYY-MM-DD
  182. day String
  183. count Int @default(0)
  184. @@id([organizationId, day])
  185. @@map("platform_mail_usage")
  186. }