inspections.prisma 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. model InspectionTemplate {
  2. id String @id @default(cuid())
  3. name String
  4. description String?
  5. isDefault Boolean @default(false)
  6. createdAt DateTime @default(now())
  7. updatedAt DateTime @updatedAt
  8. // Regulatory profile. `country` is an ISO-3166 alpha-2 code (or null for a
  9. // shop-specific checklist), `standard` names the regime the template follows
  10. // (e.g. "eu-2014-45"), and `severityScale` picks which defect vocabulary the
  11. // technician grades against — see Lib/conditions.ts.
  12. country String?
  13. standard String? @default("custom")
  14. severityScale String @default("eu")
  15. /// Provenance, for templates that came from a package rather than being
  16. /// written here. `packageId` is namespaced and stable across renames
  17. /// ("torqvoice/eu-roadworthiness"), which is what lets the library tell an
  18. /// update from a duplicate. Null on a template the workshop wrote itself.
  19. packageId String?
  20. packageVersion String?
  21. /// Where it came from: "builtin", "file" or "catalogue".
  22. packageSource String?
  23. organizationId String
  24. organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  25. sections InspectionTemplateSection[]
  26. inspections Inspection[]
  27. @@index([organizationId])
  28. @@index([organizationId, packageId])
  29. @@map("inspection_templates")
  30. }
  31. model InspectionTemplateSection {
  32. id String @id @default(cuid())
  33. name String
  34. description String?
  35. // Regulation reference for the section, e.g. "1" for Braking equipment in
  36. // Directive 2014/45/EU Annex I.
  37. code String?
  38. sortOrder Int @default(0)
  39. templateId String
  40. template InspectionTemplate @relation(fields: [templateId], references: [id], onDelete: Cascade)
  41. items InspectionTemplateItem[]
  42. @@index([templateId])
  43. @@map("inspection_template_sections")
  44. }
  45. model InspectionTemplateItem {
  46. id String @id @default(cuid())
  47. name String
  48. description String?
  49. // Regulation reference for the check, e.g. "1.1.13".
  50. code String?
  51. sortOrder Int @default(0)
  52. // How the technician records the result: "condition" (defect grading only),
  53. // "measurement" (numeric value in `unit`, graded against min/max),
  54. // "text" (free text) or "choice" (one of `choices`).
  55. inputType String @default("condition")
  56. unit String?
  57. minValue Float?
  58. maxValue Float?
  59. choices String[] @default([])
  60. required Boolean @default(false)
  61. photoRequired Boolean @default(false)
  62. /// The check may be graded "not applicable": the vehicle has no such part.
  63. allowNotApplicable Boolean @default(true)
  64. // Defect severity applied when a measurement falls outside min/max.
  65. defaultSeverity String?
  66. // Phrases this workshop wants offered when a defect is recorded against the
  67. // check, on top of the built-in catalogue. See Lib/defectCatalogue.ts.
  68. defectSuggestions String[] @default([])
  69. sectionId String
  70. section InspectionTemplateSection @relation(fields: [sectionId], references: [id], onDelete: Cascade)
  71. @@index([sectionId])
  72. @@map("inspection_template_items")
  73. }
  74. model Inspection {
  75. id String @id @default(cuid())
  76. status String @default("in_progress")
  77. mileage Int?
  78. notes String?
  79. startDateTime DateTime?
  80. endDateTime DateTime?
  81. publicToken String? @unique
  82. completedAt DateTime?
  83. createdAt DateTime @default(now())
  84. updatedAt DateTime @updatedAt
  85. vehicleId String
  86. vehicle Vehicle @relation(fields: [vehicleId], references: [id], onDelete: Cascade)
  87. templateId String
  88. template InspectionTemplate @relation(fields: [templateId], references: [id])
  89. technicianId String?
  90. technician Technician? @relation(fields: [technicianId], references: [id], onDelete: SetNull)
  91. /// See ServiceRecord.workBayId — an inspection occupies a bay just as a
  92. /// repair does, and the work board lanes both the same way.
  93. workBayId String?
  94. workBay WorkBay? @relation(fields: [workBayId], references: [id], onDelete: SetNull)
  95. sortOrder Int @default(0)
  96. // Roadworthiness certificate fields required by Directive 2014/45/EU Annex IV.
  97. // `inspectorName` and `certificateNumber` are snapshots taken at completion so
  98. // the issued certificate stays stable even if staff or settings change later.
  99. /// Snapshot of how this inspection was graded, taken when it was created.
  100. /// Read in preference to the template's current setting: a workshop that
  101. /// later switches a template to the EU scale must not relabel a certificate
  102. /// it already issued. Null on inspections that predate the snapshot; those
  103. /// fall back to the template, which the migration pinned to its old scale.
  104. severityScale String?
  105. country String?
  106. vehicleCategory String?
  107. nextTestDue DateTime?
  108. certificateNumber String?
  109. inspectorName String?
  110. testLocation String?
  111. /// The certificate design as it was when the inspection was completed, so a
  112. /// design edited later never changes a certificate a customer already has.
  113. /// Null on inspections completed before designs existed, or by a workshop
  114. /// that has never designed one; those print the built-in sheet.
  115. designSnapshotId String?
  116. designSnapshot DocumentDesignSnapshot? @relation(fields: [designSnapshotId], references: [id], onDelete: SetNull)
  117. /// The inspector's signature as it was at completion, for the same reason:
  118. /// a redrawn signature never changes a certificate already issued.
  119. signatureSnapshotId String?
  120. signatureSnapshot DocumentAssetSnapshot? @relation(fields: [signatureSnapshotId], references: [id], onDelete: SetNull)
  121. organizationId String
  122. items InspectionItem[]
  123. attachments InspectionAttachment[]
  124. statusReports StatusReport[]
  125. quoteRequests InspectionQuoteRequest[]
  126. quotes Quote[]
  127. serviceRecords ServiceRecord[]
  128. conditionMarks ConditionMark[]
  129. importBatchId String?
  130. importBatch ImportBatch? @relation(fields: [importBatchId], references: [id], onDelete: SetNull)
  131. @@index([vehicleId])
  132. @@index([designSnapshotId])
  133. @@index([signatureSnapshotId])
  134. @@index([organizationId])
  135. @@index([technicianId])
  136. @@index([workBayId])
  137. @@map("inspections")
  138. }
  139. /// Files filed on the inspection as a whole rather than on one check: the
  140. /// overview photos, a video of the walk round, the regulator's own paper form
  141. /// once it is filled in and signed. A photo that is the evidence for a single
  142. /// check stays on that check (InspectionItem.imageUrls), next to its grade.
  143. model InspectionAttachment {
  144. id String @id @default(cuid())
  145. fileName String
  146. fileUrl String
  147. fileType String
  148. fileSize Int
  149. /// "image", "document" or "video".
  150. category String @default("image")
  151. description String?
  152. /// Shown to the customer on the shared inspection link. Photos start shown,
  153. /// documents start hidden: paperwork is the workshop's until it says so.
  154. includeInReport Boolean @default(true)
  155. createdAt DateTime @default(now())
  156. inspectionId String
  157. inspection Inspection @relation(fields: [inspectionId], references: [id], onDelete: Cascade)
  158. @@index([inspectionId])
  159. @@map("inspection_attachments")
  160. }
  161. model InspectionItem {
  162. id String @id @default(cuid())
  163. name String
  164. section String
  165. sortOrder Int @default(0)
  166. condition String @default("not_inspected")
  167. notes String?
  168. imageUrls String[] @default([])
  169. // Copied from the template at creation so an inspection stays readable even
  170. // after its template is edited or deleted.
  171. description String?
  172. code String?
  173. sectionCode String?
  174. inputType String @default("condition")
  175. unit String?
  176. minValue Float?
  177. maxValue Float?
  178. choices String[] @default([])
  179. required Boolean @default(false)
  180. photoRequired Boolean @default(false)
  181. /// The check may be graded "not applicable": the vehicle has no such part.
  182. allowNotApplicable Boolean @default(true)
  183. defaultSeverity String?
  184. defectSuggestions String[] @default([])
  185. measuredValue Float?
  186. textValue String?
  187. inspectionId String
  188. inspection Inspection @relation(fields: [inspectionId], references: [id], onDelete: Cascade)
  189. conditionMarks ConditionMark[]
  190. @@index([inspectionId])
  191. @@map("inspection_items")
  192. }
  193. model InspectionQuoteRequest {
  194. id String @id @default(cuid())
  195. status String @default("pending")
  196. message String?
  197. selectedItemIds String[]
  198. createdAt DateTime @default(now())
  199. inspectionId String
  200. inspection Inspection @relation(fields: [inspectionId], references: [id], onDelete: Cascade)
  201. organizationId String
  202. @@index([organizationId])
  203. @@index([inspectionId])
  204. @@map("inspection_quote_requests")
  205. }