4
0

migration.sql 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. -- Idempotent baseline migration: creates all tables, indexes, and foreign keys
  2. -- Safe to run on both fresh and existing databases
  3. CREATE SCHEMA IF NOT EXISTS "public";
  4. -- CreateTable
  5. CREATE TABLE IF NOT EXISTS "users" (
  6. "id" TEXT NOT NULL,
  7. "name" TEXT NOT NULL,
  8. "email" TEXT NOT NULL,
  9. "emailVerified" BOOLEAN NOT NULL DEFAULT false,
  10. "image" TEXT,
  11. "isSuperAdmin" BOOLEAN NOT NULL DEFAULT false,
  12. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  13. "updatedAt" TIMESTAMP(3) NOT NULL,
  14. "twoFactorEnabled" BOOLEAN NOT NULL DEFAULT false,
  15. "termsAcceptedAt" TIMESTAMP(3),
  16. "lastLogin" TIMESTAMP(3),
  17. "lastSeen" TIMESTAMP(3),
  18. CONSTRAINT "users_pkey" PRIMARY KEY ("id")
  19. );
  20. CREATE TABLE IF NOT EXISTS "app_settings" (
  21. "id" TEXT NOT NULL,
  22. "key" TEXT NOT NULL,
  23. "value" TEXT NOT NULL,
  24. "userId" TEXT NOT NULL,
  25. "organizationId" TEXT,
  26. CONSTRAINT "app_settings_pkey" PRIMARY KEY ("id")
  27. );
  28. CREATE TABLE IF NOT EXISTS "sessions" (
  29. "id" TEXT NOT NULL,
  30. "expiresAt" TIMESTAMP(3) NOT NULL,
  31. "token" TEXT NOT NULL,
  32. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  33. "updatedAt" TIMESTAMP(3) NOT NULL,
  34. "ipAddress" TEXT,
  35. "userAgent" TEXT,
  36. "userId" TEXT NOT NULL,
  37. CONSTRAINT "sessions_pkey" PRIMARY KEY ("id")
  38. );
  39. CREATE TABLE IF NOT EXISTS "accounts" (
  40. "id" TEXT NOT NULL,
  41. "accountId" TEXT NOT NULL,
  42. "providerId" TEXT NOT NULL,
  43. "userId" TEXT NOT NULL,
  44. "accessToken" TEXT,
  45. "refreshToken" TEXT,
  46. "idToken" TEXT,
  47. "accessTokenExpiresAt" TIMESTAMP(3),
  48. "refreshTokenExpiresAt" TIMESTAMP(3),
  49. "scope" TEXT,
  50. "password" TEXT,
  51. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  52. "updatedAt" TIMESTAMP(3) NOT NULL,
  53. CONSTRAINT "accounts_pkey" PRIMARY KEY ("id")
  54. );
  55. CREATE TABLE IF NOT EXISTS "verifications" (
  56. "id" TEXT NOT NULL,
  57. "identifier" TEXT NOT NULL,
  58. "value" TEXT NOT NULL,
  59. "expiresAt" TIMESTAMP(3) NOT NULL,
  60. "createdAt" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
  61. "updatedAt" TIMESTAMP(3),
  62. CONSTRAINT "verifications_pkey" PRIMARY KEY ("id")
  63. );
  64. CREATE TABLE IF NOT EXISTS "two_factor" (
  65. "id" TEXT NOT NULL,
  66. "secret" TEXT NOT NULL,
  67. "backupCodes" TEXT NOT NULL,
  68. "userId" TEXT NOT NULL,
  69. CONSTRAINT "two_factor_pkey" PRIMARY KEY ("id")
  70. );
  71. CREATE TABLE IF NOT EXISTS "passkeys" (
  72. "id" TEXT NOT NULL,
  73. "name" TEXT,
  74. "publicKey" TEXT NOT NULL,
  75. "userId" TEXT NOT NULL,
  76. "credentialID" TEXT NOT NULL,
  77. "counter" INTEGER NOT NULL,
  78. "deviceType" TEXT NOT NULL,
  79. "backedUp" BOOLEAN NOT NULL,
  80. "transports" TEXT,
  81. "aaguid" TEXT,
  82. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  83. CONSTRAINT "passkeys_pkey" PRIMARY KEY ("id")
  84. );
  85. CREATE TABLE IF NOT EXISTS "vehicles" (
  86. "id" TEXT NOT NULL,
  87. "make" TEXT NOT NULL,
  88. "model" TEXT NOT NULL,
  89. "year" INTEGER NOT NULL,
  90. "vin" TEXT,
  91. "licensePlate" TEXT,
  92. "color" TEXT,
  93. "mileage" INTEGER NOT NULL DEFAULT 0,
  94. "fuelType" TEXT DEFAULT 'gasoline',
  95. "transmission" TEXT DEFAULT 'automatic',
  96. "engineSize" TEXT,
  97. "purchaseDate" TIMESTAMP(3),
  98. "purchasePrice" DOUBLE PRECISION,
  99. "imageUrl" TEXT,
  100. "isArchived" BOOLEAN NOT NULL DEFAULT false,
  101. "archiveReason" TEXT,
  102. "maintenanceDismissed" BOOLEAN NOT NULL DEFAULT false,
  103. "maintenanceDismissedAt" TIMESTAMP(3),
  104. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  105. "updatedAt" TIMESTAMP(3) NOT NULL,
  106. "userId" TEXT NOT NULL,
  107. "organizationId" TEXT,
  108. "customerId" TEXT,
  109. CONSTRAINT "vehicles_pkey" PRIMARY KEY ("id")
  110. );
  111. CREATE TABLE IF NOT EXISTS "service_records" (
  112. "id" TEXT NOT NULL,
  113. "title" TEXT NOT NULL,
  114. "description" TEXT,
  115. "type" TEXT NOT NULL DEFAULT 'maintenance',
  116. "status" TEXT NOT NULL DEFAULT 'completed',
  117. "cost" DOUBLE PRECISION NOT NULL DEFAULT 0,
  118. "mileage" INTEGER,
  119. "serviceDate" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  120. "shopName" TEXT,
  121. "techName" TEXT,
  122. "parts" TEXT,
  123. "laborHours" DOUBLE PRECISION,
  124. "diagnosticNotes" TEXT,
  125. "invoiceNotes" TEXT,
  126. "subtotal" DOUBLE PRECISION NOT NULL DEFAULT 0,
  127. "taxRate" DOUBLE PRECISION NOT NULL DEFAULT 0,
  128. "taxAmount" DOUBLE PRECISION NOT NULL DEFAULT 0,
  129. "totalAmount" DOUBLE PRECISION NOT NULL DEFAULT 0,
  130. "invoiceNumber" TEXT,
  131. "discountType" TEXT,
  132. "discountValue" DOUBLE PRECISION NOT NULL DEFAULT 0,
  133. "discountAmount" DOUBLE PRECISION NOT NULL DEFAULT 0,
  134. "manuallyPaid" BOOLEAN NOT NULL DEFAULT false,
  135. "publicToken" TEXT,
  136. "sharedAt" TIMESTAMP(3),
  137. "viewCount" INTEGER NOT NULL DEFAULT 0,
  138. "lastViewedAt" TIMESTAMP(3),
  139. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  140. "updatedAt" TIMESTAMP(3) NOT NULL,
  141. "vehicleId" TEXT NOT NULL,
  142. CONSTRAINT "service_records_pkey" PRIMARY KEY ("id")
  143. );
  144. CREATE TABLE IF NOT EXISTS "notes" (
  145. "id" TEXT NOT NULL,
  146. "title" TEXT NOT NULL,
  147. "content" TEXT NOT NULL,
  148. "isPinned" BOOLEAN NOT NULL DEFAULT false,
  149. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  150. "updatedAt" TIMESTAMP(3) NOT NULL,
  151. "vehicleId" TEXT NOT NULL,
  152. CONSTRAINT "notes_pkey" PRIMARY KEY ("id")
  153. );
  154. CREATE TABLE IF NOT EXISTS "fuel_logs" (
  155. "id" TEXT NOT NULL,
  156. "date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  157. "mileage" INTEGER NOT NULL,
  158. "gallons" DOUBLE PRECISION NOT NULL,
  159. "pricePerGallon" DOUBLE PRECISION NOT NULL,
  160. "totalCost" DOUBLE PRECISION NOT NULL,
  161. "isFillUp" BOOLEAN NOT NULL DEFAULT true,
  162. "station" TEXT,
  163. "notes" TEXT,
  164. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  165. "updatedAt" TIMESTAMP(3) NOT NULL,
  166. "vehicleId" TEXT NOT NULL,
  167. CONSTRAINT "fuel_logs_pkey" PRIMARY KEY ("id")
  168. );
  169. CREATE TABLE IF NOT EXISTS "reminders" (
  170. "id" TEXT NOT NULL,
  171. "title" TEXT NOT NULL,
  172. "description" TEXT,
  173. "dueDate" TIMESTAMP(3),
  174. "dueMileage" INTEGER,
  175. "isCompleted" BOOLEAN NOT NULL DEFAULT false,
  176. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  177. "updatedAt" TIMESTAMP(3) NOT NULL,
  178. "vehicleId" TEXT NOT NULL,
  179. CONSTRAINT "reminders_pkey" PRIMARY KEY ("id")
  180. );
  181. CREATE TABLE IF NOT EXISTS "customers" (
  182. "id" TEXT NOT NULL,
  183. "name" TEXT NOT NULL,
  184. "email" TEXT,
  185. "phone" TEXT,
  186. "address" TEXT,
  187. "company" TEXT,
  188. "notes" TEXT,
  189. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  190. "updatedAt" TIMESTAMP(3) NOT NULL,
  191. "userId" TEXT NOT NULL,
  192. "organizationId" TEXT,
  193. CONSTRAINT "customers_pkey" PRIMARY KEY ("id")
  194. );
  195. CREATE TABLE IF NOT EXISTS "payments" (
  196. "id" TEXT NOT NULL,
  197. "amount" DOUBLE PRECISION NOT NULL,
  198. "date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  199. "method" TEXT NOT NULL DEFAULT 'other',
  200. "note" TEXT,
  201. "provider" TEXT,
  202. "externalId" TEXT,
  203. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  204. "updatedAt" TIMESTAMP(3) NOT NULL,
  205. "serviceRecordId" TEXT NOT NULL,
  206. CONSTRAINT "payments_pkey" PRIMARY KEY ("id")
  207. );
  208. CREATE TABLE IF NOT EXISTS "service_attachments" (
  209. "id" TEXT NOT NULL,
  210. "fileName" TEXT NOT NULL,
  211. "fileUrl" TEXT NOT NULL,
  212. "fileType" TEXT NOT NULL,
  213. "fileSize" INTEGER NOT NULL,
  214. "category" TEXT NOT NULL DEFAULT 'diagnostic',
  215. "description" TEXT,
  216. "includeInInvoice" BOOLEAN NOT NULL DEFAULT true,
  217. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  218. "serviceRecordId" TEXT NOT NULL,
  219. CONSTRAINT "service_attachments_pkey" PRIMARY KEY ("id")
  220. );
  221. CREATE TABLE IF NOT EXISTS "service_parts" (
  222. "id" TEXT NOT NULL,
  223. "partNumber" TEXT,
  224. "name" TEXT NOT NULL,
  225. "quantity" DOUBLE PRECISION NOT NULL DEFAULT 1,
  226. "unitPrice" DOUBLE PRECISION NOT NULL DEFAULT 0,
  227. "total" DOUBLE PRECISION NOT NULL DEFAULT 0,
  228. "serviceRecordId" TEXT NOT NULL,
  229. CONSTRAINT "service_parts_pkey" PRIMARY KEY ("id")
  230. );
  231. CREATE TABLE IF NOT EXISTS "service_labor" (
  232. "id" TEXT NOT NULL,
  233. "description" TEXT NOT NULL,
  234. "hours" DOUBLE PRECISION NOT NULL DEFAULT 0,
  235. "rate" DOUBLE PRECISION NOT NULL DEFAULT 0,
  236. "total" DOUBLE PRECISION NOT NULL DEFAULT 0,
  237. "serviceRecordId" TEXT NOT NULL,
  238. CONSTRAINT "service_labor_pkey" PRIMARY KEY ("id")
  239. );
  240. CREATE TABLE IF NOT EXISTS "inventory_parts" (
  241. "id" TEXT NOT NULL,
  242. "partNumber" TEXT,
  243. "name" TEXT NOT NULL,
  244. "description" TEXT,
  245. "category" TEXT,
  246. "quantity" INTEGER NOT NULL DEFAULT 0,
  247. "minQuantity" INTEGER NOT NULL DEFAULT 0,
  248. "unitCost" DOUBLE PRECISION NOT NULL DEFAULT 0,
  249. "sellPrice" DOUBLE PRECISION NOT NULL DEFAULT 0,
  250. "supplier" TEXT,
  251. "supplierPhone" TEXT,
  252. "supplierEmail" TEXT,
  253. "supplierUrl" TEXT,
  254. "imageUrl" TEXT,
  255. "location" TEXT,
  256. "isArchived" BOOLEAN NOT NULL DEFAULT false,
  257. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  258. "updatedAt" TIMESTAMP(3) NOT NULL,
  259. "userId" TEXT NOT NULL,
  260. "organizationId" TEXT,
  261. CONSTRAINT "inventory_parts_pkey" PRIMARY KEY ("id")
  262. );
  263. CREATE TABLE IF NOT EXISTS "quotes" (
  264. "id" TEXT NOT NULL,
  265. "quoteNumber" TEXT,
  266. "title" TEXT NOT NULL,
  267. "description" TEXT,
  268. "status" TEXT NOT NULL DEFAULT 'draft',
  269. "validUntil" TIMESTAMP(3),
  270. "subtotal" DOUBLE PRECISION NOT NULL DEFAULT 0,
  271. "taxRate" DOUBLE PRECISION NOT NULL DEFAULT 0,
  272. "taxAmount" DOUBLE PRECISION NOT NULL DEFAULT 0,
  273. "discountType" TEXT,
  274. "discountValue" DOUBLE PRECISION NOT NULL DEFAULT 0,
  275. "discountAmount" DOUBLE PRECISION NOT NULL DEFAULT 0,
  276. "totalAmount" DOUBLE PRECISION NOT NULL DEFAULT 0,
  277. "notes" TEXT,
  278. "publicToken" TEXT,
  279. "sharedAt" TIMESTAMP(3),
  280. "viewCount" INTEGER NOT NULL DEFAULT 0,
  281. "lastViewedAt" TIMESTAMP(3),
  282. "customerMessage" TEXT,
  283. "convertedToId" TEXT,
  284. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  285. "updatedAt" TIMESTAMP(3) NOT NULL,
  286. "userId" TEXT NOT NULL,
  287. "organizationId" TEXT,
  288. "customerId" TEXT,
  289. "vehicleId" TEXT,
  290. "inspectionId" TEXT,
  291. CONSTRAINT "quotes_pkey" PRIMARY KEY ("id")
  292. );
  293. CREATE TABLE IF NOT EXISTS "quote_attachments" (
  294. "id" TEXT NOT NULL,
  295. "fileName" TEXT NOT NULL,
  296. "fileUrl" TEXT NOT NULL,
  297. "fileType" TEXT NOT NULL,
  298. "fileSize" INTEGER NOT NULL,
  299. "category" TEXT NOT NULL DEFAULT 'image',
  300. "description" TEXT,
  301. "includeInInvoice" BOOLEAN NOT NULL DEFAULT true,
  302. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  303. "quoteId" TEXT NOT NULL,
  304. CONSTRAINT "quote_attachments_pkey" PRIMARY KEY ("id")
  305. );
  306. CREATE TABLE IF NOT EXISTS "quote_parts" (
  307. "id" TEXT NOT NULL,
  308. "partNumber" TEXT,
  309. "name" TEXT NOT NULL,
  310. "quantity" DOUBLE PRECISION NOT NULL DEFAULT 1,
  311. "unitPrice" DOUBLE PRECISION NOT NULL DEFAULT 0,
  312. "total" DOUBLE PRECISION NOT NULL DEFAULT 0,
  313. "excluded" BOOLEAN NOT NULL DEFAULT false,
  314. "quoteId" TEXT NOT NULL,
  315. CONSTRAINT "quote_parts_pkey" PRIMARY KEY ("id")
  316. );
  317. CREATE TABLE IF NOT EXISTS "quote_labor" (
  318. "id" TEXT NOT NULL,
  319. "description" TEXT NOT NULL,
  320. "hours" DOUBLE PRECISION NOT NULL DEFAULT 0,
  321. "rate" DOUBLE PRECISION NOT NULL DEFAULT 0,
  322. "total" DOUBLE PRECISION NOT NULL DEFAULT 0,
  323. "excluded" BOOLEAN NOT NULL DEFAULT false,
  324. "quoteId" TEXT NOT NULL,
  325. CONSTRAINT "quote_labor_pkey" PRIMARY KEY ("id")
  326. );
  327. CREATE TABLE IF NOT EXISTS "custom_field_definitions" (
  328. "id" TEXT NOT NULL,
  329. "name" TEXT NOT NULL,
  330. "label" TEXT NOT NULL,
  331. "fieldType" TEXT NOT NULL DEFAULT 'text',
  332. "options" TEXT,
  333. "required" BOOLEAN NOT NULL DEFAULT false,
  334. "entityType" TEXT NOT NULL,
  335. "sortOrder" INTEGER NOT NULL DEFAULT 0,
  336. "isActive" BOOLEAN NOT NULL DEFAULT true,
  337. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  338. "updatedAt" TIMESTAMP(3) NOT NULL,
  339. "userId" TEXT NOT NULL,
  340. "organizationId" TEXT,
  341. CONSTRAINT "custom_field_definitions_pkey" PRIMARY KEY ("id")
  342. );
  343. CREATE TABLE IF NOT EXISTS "custom_field_values" (
  344. "id" TEXT NOT NULL,
  345. "value" TEXT NOT NULL,
  346. "entityId" TEXT NOT NULL,
  347. "entityType" TEXT NOT NULL,
  348. "fieldId" TEXT NOT NULL,
  349. CONSTRAINT "custom_field_values_pkey" PRIMARY KEY ("id")
  350. );
  351. CREATE TABLE IF NOT EXISTS "organizations" (
  352. "id" TEXT NOT NULL,
  353. "name" TEXT NOT NULL,
  354. "portalSlug" TEXT,
  355. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  356. "updatedAt" TIMESTAMP(3) NOT NULL,
  357. CONSTRAINT "organizations_pkey" PRIMARY KEY ("id")
  358. );
  359. CREATE TABLE IF NOT EXISTS "organization_members" (
  360. "id" TEXT NOT NULL,
  361. "role" TEXT NOT NULL DEFAULT 'member',
  362. "userId" TEXT NOT NULL,
  363. "organizationId" TEXT NOT NULL,
  364. "roleId" TEXT,
  365. CONSTRAINT "organization_members_pkey" PRIMARY KEY ("id")
  366. );
  367. CREATE TABLE IF NOT EXISTS "roles" (
  368. "id" TEXT NOT NULL,
  369. "name" TEXT NOT NULL,
  370. "isAdmin" BOOLEAN NOT NULL DEFAULT false,
  371. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  372. "updatedAt" TIMESTAMP(3) NOT NULL,
  373. "organizationId" TEXT NOT NULL,
  374. CONSTRAINT "roles_pkey" PRIMARY KEY ("id")
  375. );
  376. CREATE TABLE IF NOT EXISTS "permissions" (
  377. "id" TEXT NOT NULL,
  378. "action" TEXT NOT NULL,
  379. "subject" TEXT NOT NULL,
  380. "roleId" TEXT NOT NULL,
  381. CONSTRAINT "permissions_pkey" PRIMARY KEY ("id")
  382. );
  383. CREATE TABLE IF NOT EXISTS "system_settings" (
  384. "id" TEXT NOT NULL,
  385. "key" TEXT NOT NULL,
  386. "value" TEXT NOT NULL,
  387. CONSTRAINT "system_settings_pkey" PRIMARY KEY ("id")
  388. );
  389. CREATE TABLE IF NOT EXISTS "team_invitations" (
  390. "id" TEXT NOT NULL,
  391. "email" TEXT NOT NULL,
  392. "role" TEXT NOT NULL DEFAULT 'member',
  393. "token" TEXT NOT NULL,
  394. "status" TEXT NOT NULL DEFAULT 'pending',
  395. "expiresAt" TIMESTAMP(3) NOT NULL,
  396. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  397. "organizationId" TEXT NOT NULL,
  398. "invitedById" TEXT NOT NULL,
  399. "roleId" TEXT,
  400. CONSTRAINT "team_invitations_pkey" PRIMARY KEY ("id")
  401. );
  402. CREATE TABLE IF NOT EXISTS "subscription_plans" (
  403. "id" TEXT NOT NULL,
  404. "name" TEXT NOT NULL,
  405. "stripePriceId" TEXT,
  406. "price" DOUBLE PRECISION NOT NULL DEFAULT 0,
  407. "interval" TEXT NOT NULL DEFAULT 'month',
  408. "maxMembers" INTEGER NOT NULL DEFAULT 1,
  409. "features" TEXT,
  410. "isActive" BOOLEAN NOT NULL DEFAULT true,
  411. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  412. "updatedAt" TIMESTAMP(3) NOT NULL,
  413. CONSTRAINT "subscription_plans_pkey" PRIMARY KEY ("id")
  414. );
  415. CREATE TABLE IF NOT EXISTS "subscriptions" (
  416. "id" TEXT NOT NULL,
  417. "status" TEXT NOT NULL DEFAULT 'active',
  418. "stripeSubscriptionId" TEXT,
  419. "stripeCustomerId" TEXT,
  420. "currentPeriodStart" TIMESTAMP(3),
  421. "currentPeriodEnd" TIMESTAMP(3),
  422. "cancelAtPeriodEnd" BOOLEAN NOT NULL DEFAULT false,
  423. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  424. "updatedAt" TIMESTAMP(3) NOT NULL,
  425. "organizationId" TEXT NOT NULL,
  426. "planId" TEXT NOT NULL,
  427. CONSTRAINT "subscriptions_pkey" PRIMARY KEY ("id")
  428. );
  429. CREATE TABLE IF NOT EXISTS "recurring_invoices" (
  430. "id" TEXT NOT NULL,
  431. "title" TEXT NOT NULL,
  432. "description" TEXT,
  433. "frequency" TEXT NOT NULL,
  434. "nextRunDate" TIMESTAMP(3) NOT NULL,
  435. "endDate" TIMESTAMP(3),
  436. "isActive" BOOLEAN NOT NULL DEFAULT true,
  437. "lastRunAt" TIMESTAMP(3),
  438. "runCount" INTEGER NOT NULL DEFAULT 0,
  439. "type" TEXT NOT NULL DEFAULT 'maintenance',
  440. "cost" DOUBLE PRECISION NOT NULL DEFAULT 0,
  441. "taxRate" DOUBLE PRECISION NOT NULL DEFAULT 0,
  442. "invoiceNotes" TEXT,
  443. "vehicleId" TEXT NOT NULL,
  444. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  445. "updatedAt" TIMESTAMP(3) NOT NULL,
  446. CONSTRAINT "recurring_invoices_pkey" PRIMARY KEY ("id")
  447. );
  448. CREATE TABLE IF NOT EXISTS "recurring_parts" (
  449. "id" TEXT NOT NULL,
  450. "name" TEXT NOT NULL,
  451. "partNumber" TEXT,
  452. "quantity" INTEGER NOT NULL DEFAULT 1,
  453. "unitPrice" DOUBLE PRECISION NOT NULL DEFAULT 0,
  454. "recurringInvoiceId" TEXT NOT NULL,
  455. CONSTRAINT "recurring_parts_pkey" PRIMARY KEY ("id")
  456. );
  457. CREATE TABLE IF NOT EXISTS "recurring_labor" (
  458. "id" TEXT NOT NULL,
  459. "description" TEXT NOT NULL,
  460. "hours" DOUBLE PRECISION NOT NULL DEFAULT 0,
  461. "rate" DOUBLE PRECISION NOT NULL DEFAULT 0,
  462. "recurringInvoiceId" TEXT NOT NULL,
  463. CONSTRAINT "recurring_labor_pkey" PRIMARY KEY ("id")
  464. );
  465. CREATE TABLE IF NOT EXISTS "inspection_templates" (
  466. "id" TEXT NOT NULL,
  467. "name" TEXT NOT NULL,
  468. "description" TEXT,
  469. "isDefault" BOOLEAN NOT NULL DEFAULT false,
  470. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  471. "updatedAt" TIMESTAMP(3) NOT NULL,
  472. "organizationId" TEXT NOT NULL,
  473. CONSTRAINT "inspection_templates_pkey" PRIMARY KEY ("id")
  474. );
  475. CREATE TABLE IF NOT EXISTS "inspection_template_sections" (
  476. "id" TEXT NOT NULL,
  477. "name" TEXT NOT NULL,
  478. "sortOrder" INTEGER NOT NULL DEFAULT 0,
  479. "templateId" TEXT NOT NULL,
  480. CONSTRAINT "inspection_template_sections_pkey" PRIMARY KEY ("id")
  481. );
  482. CREATE TABLE IF NOT EXISTS "inspection_template_items" (
  483. "id" TEXT NOT NULL,
  484. "name" TEXT NOT NULL,
  485. "sortOrder" INTEGER NOT NULL DEFAULT 0,
  486. "sectionId" TEXT NOT NULL,
  487. CONSTRAINT "inspection_template_items_pkey" PRIMARY KEY ("id")
  488. );
  489. CREATE TABLE IF NOT EXISTS "inspections" (
  490. "id" TEXT NOT NULL,
  491. "status" TEXT NOT NULL DEFAULT 'in_progress',
  492. "mileage" INTEGER,
  493. "notes" TEXT,
  494. "publicToken" TEXT,
  495. "completedAt" TIMESTAMP(3),
  496. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  497. "updatedAt" TIMESTAMP(3) NOT NULL,
  498. "vehicleId" TEXT NOT NULL,
  499. "templateId" TEXT NOT NULL,
  500. "technicianId" TEXT NOT NULL,
  501. "organizationId" TEXT NOT NULL,
  502. CONSTRAINT "inspections_pkey" PRIMARY KEY ("id")
  503. );
  504. CREATE TABLE IF NOT EXISTS "inspection_items" (
  505. "id" TEXT NOT NULL,
  506. "name" TEXT NOT NULL,
  507. "section" TEXT NOT NULL,
  508. "sortOrder" INTEGER NOT NULL DEFAULT 0,
  509. "condition" TEXT NOT NULL DEFAULT 'not_inspected',
  510. "notes" TEXT,
  511. "imageUrls" TEXT[] DEFAULT ARRAY[]::TEXT[],
  512. "inspectionId" TEXT NOT NULL,
  513. CONSTRAINT "inspection_items_pkey" PRIMARY KEY ("id")
  514. );
  515. CREATE TABLE IF NOT EXISTS "inspection_quote_requests" (
  516. "id" TEXT NOT NULL,
  517. "status" TEXT NOT NULL DEFAULT 'pending',
  518. "message" TEXT,
  519. "selectedItemIds" TEXT[],
  520. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  521. "inspectionId" TEXT NOT NULL,
  522. "organizationId" TEXT NOT NULL,
  523. CONSTRAINT "inspection_quote_requests_pkey" PRIMARY KEY ("id")
  524. );
  525. CREATE TABLE IF NOT EXISTS "notifications" (
  526. "id" TEXT NOT NULL,
  527. "type" TEXT NOT NULL,
  528. "title" TEXT NOT NULL,
  529. "message" TEXT NOT NULL,
  530. "entityType" TEXT NOT NULL,
  531. "entityId" TEXT NOT NULL,
  532. "entityUrl" TEXT NOT NULL,
  533. "read" BOOLEAN NOT NULL DEFAULT false,
  534. "organizationId" TEXT NOT NULL,
  535. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  536. CONSTRAINT "notifications_pkey" PRIMARY KEY ("id")
  537. );
  538. CREATE TABLE IF NOT EXISTS "sms_messages" (
  539. "id" TEXT NOT NULL,
  540. "direction" TEXT NOT NULL,
  541. "fromNumber" TEXT NOT NULL,
  542. "toNumber" TEXT NOT NULL,
  543. "body" TEXT NOT NULL,
  544. "status" TEXT NOT NULL DEFAULT 'queued',
  545. "providerMsgId" TEXT,
  546. "errorMessage" TEXT,
  547. "relatedEntityType" TEXT,
  548. "relatedEntityId" TEXT,
  549. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  550. "updatedAt" TIMESTAMP(3) NOT NULL,
  551. "organizationId" TEXT NOT NULL,
  552. "customerId" TEXT,
  553. CONSTRAINT "sms_messages_pkey" PRIMARY KEY ("id")
  554. );
  555. CREATE TABLE IF NOT EXISTS "technicians" (
  556. "id" TEXT NOT NULL,
  557. "name" TEXT NOT NULL,
  558. "color" TEXT NOT NULL DEFAULT '#3b82f6',
  559. "isActive" BOOLEAN NOT NULL DEFAULT true,
  560. "sortOrder" INTEGER NOT NULL DEFAULT 0,
  561. "memberId" TEXT,
  562. "organizationId" TEXT NOT NULL,
  563. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  564. "updatedAt" TIMESTAMP(3) NOT NULL,
  565. CONSTRAINT "technicians_pkey" PRIMARY KEY ("id")
  566. );
  567. CREATE TABLE IF NOT EXISTS "board_assignments" (
  568. "id" TEXT NOT NULL,
  569. "date" DATE NOT NULL,
  570. "sortOrder" INTEGER NOT NULL DEFAULT 0,
  571. "notes" TEXT,
  572. "technicianId" TEXT NOT NULL,
  573. "serviceRecordId" TEXT,
  574. "inspectionId" TEXT,
  575. "organizationId" TEXT NOT NULL,
  576. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  577. "updatedAt" TIMESTAMP(3) NOT NULL,
  578. CONSTRAINT "board_assignments_pkey" PRIMARY KEY ("id")
  579. );
  580. CREATE TABLE IF NOT EXISTS "customer_sessions" (
  581. "id" TEXT NOT NULL,
  582. "token" TEXT NOT NULL,
  583. "expiresAt" TIMESTAMP(3) NOT NULL,
  584. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  585. "customerId" TEXT NOT NULL,
  586. "organizationId" TEXT NOT NULL,
  587. CONSTRAINT "customer_sessions_pkey" PRIMARY KEY ("id")
  588. );
  589. CREATE TABLE IF NOT EXISTS "customer_magic_links" (
  590. "id" TEXT NOT NULL,
  591. "token" TEXT NOT NULL,
  592. "email" TEXT NOT NULL,
  593. "organizationId" TEXT NOT NULL,
  594. "expiresAt" TIMESTAMP(3) NOT NULL,
  595. "usedAt" TIMESTAMP(3),
  596. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  597. CONSTRAINT "customer_magic_links_pkey" PRIMARY KEY ("id")
  598. );
  599. CREATE TABLE IF NOT EXISTS "service_requests" (
  600. "id" TEXT NOT NULL,
  601. "description" TEXT NOT NULL,
  602. "preferredDate" TIMESTAMP(3),
  603. "status" TEXT NOT NULL DEFAULT 'pending',
  604. "adminNotes" TEXT,
  605. "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
  606. "updatedAt" TIMESTAMP(3) NOT NULL,
  607. "customerId" TEXT NOT NULL,
  608. "vehicleId" TEXT NOT NULL,
  609. "organizationId" TEXT NOT NULL,
  610. CONSTRAINT "service_requests_pkey" PRIMARY KEY ("id")
  611. );
  612. -- CreateIndex (idempotent)
  613. CREATE UNIQUE INDEX IF NOT EXISTS "users_email_key" ON "users"("email");
  614. CREATE INDEX IF NOT EXISTS "app_settings_organizationId_idx" ON "app_settings"("organizationId");
  615. CREATE UNIQUE INDEX IF NOT EXISTS "app_settings_organizationId_key_key" ON "app_settings"("organizationId", "key");
  616. CREATE UNIQUE INDEX IF NOT EXISTS "sessions_token_key" ON "sessions"("token");
  617. CREATE INDEX IF NOT EXISTS "sessions_userId_idx" ON "sessions"("userId");
  618. CREATE INDEX IF NOT EXISTS "accounts_userId_idx" ON "accounts"("userId");
  619. CREATE UNIQUE INDEX IF NOT EXISTS "verifications_identifier_key" ON "verifications"("identifier");
  620. CREATE UNIQUE INDEX IF NOT EXISTS "two_factor_userId_key" ON "two_factor"("userId");
  621. CREATE UNIQUE INDEX IF NOT EXISTS "passkeys_credentialID_key" ON "passkeys"("credentialID");
  622. CREATE INDEX IF NOT EXISTS "passkeys_userId_idx" ON "passkeys"("userId");
  623. CREATE INDEX IF NOT EXISTS "vehicles_organizationId_idx" ON "vehicles"("organizationId");
  624. CREATE UNIQUE INDEX IF NOT EXISTS "service_records_publicToken_key" ON "service_records"("publicToken");
  625. CREATE INDEX IF NOT EXISTS "service_records_vehicleId_idx" ON "service_records"("vehicleId");
  626. CREATE INDEX IF NOT EXISTS "notes_vehicleId_idx" ON "notes"("vehicleId");
  627. CREATE INDEX IF NOT EXISTS "fuel_logs_vehicleId_idx" ON "fuel_logs"("vehicleId");
  628. CREATE INDEX IF NOT EXISTS "reminders_vehicleId_idx" ON "reminders"("vehicleId");
  629. CREATE INDEX IF NOT EXISTS "customers_organizationId_idx" ON "customers"("organizationId");
  630. CREATE INDEX IF NOT EXISTS "payments_serviceRecordId_idx" ON "payments"("serviceRecordId");
  631. CREATE INDEX IF NOT EXISTS "service_attachments_serviceRecordId_idx" ON "service_attachments"("serviceRecordId");
  632. CREATE INDEX IF NOT EXISTS "service_parts_serviceRecordId_idx" ON "service_parts"("serviceRecordId");
  633. CREATE INDEX IF NOT EXISTS "service_labor_serviceRecordId_idx" ON "service_labor"("serviceRecordId");
  634. CREATE INDEX IF NOT EXISTS "inventory_parts_organizationId_idx" ON "inventory_parts"("organizationId");
  635. CREATE INDEX IF NOT EXISTS "quotes_organizationId_idx" ON "quotes"("organizationId");
  636. CREATE INDEX IF NOT EXISTS "quote_attachments_quoteId_idx" ON "quote_attachments"("quoteId");
  637. CREATE INDEX IF NOT EXISTS "quote_parts_quoteId_idx" ON "quote_parts"("quoteId");
  638. CREATE INDEX IF NOT EXISTS "quote_labor_quoteId_idx" ON "quote_labor"("quoteId");
  639. CREATE INDEX IF NOT EXISTS "custom_field_definitions_organizationId_idx" ON "custom_field_definitions"("organizationId");
  640. CREATE UNIQUE INDEX IF NOT EXISTS "custom_field_definitions_organizationId_name_entityType_key" ON "custom_field_definitions"("organizationId", "name", "entityType");
  641. CREATE INDEX IF NOT EXISTS "custom_field_values_fieldId_idx" ON "custom_field_values"("fieldId");
  642. CREATE UNIQUE INDEX IF NOT EXISTS "custom_field_values_fieldId_entityId_key" ON "custom_field_values"("fieldId", "entityId");
  643. CREATE UNIQUE INDEX IF NOT EXISTS "organizations_portalSlug_key" ON "organizations"("portalSlug");
  644. CREATE UNIQUE INDEX IF NOT EXISTS "organization_members_userId_organizationId_key" ON "organization_members"("userId", "organizationId");
  645. CREATE UNIQUE INDEX IF NOT EXISTS "roles_organizationId_name_key" ON "roles"("organizationId", "name");
  646. CREATE INDEX IF NOT EXISTS "permissions_roleId_idx" ON "permissions"("roleId");
  647. CREATE UNIQUE INDEX IF NOT EXISTS "permissions_roleId_action_subject_key" ON "permissions"("roleId", "action", "subject");
  648. CREATE UNIQUE INDEX IF NOT EXISTS "system_settings_key_key" ON "system_settings"("key");
  649. CREATE UNIQUE INDEX IF NOT EXISTS "team_invitations_token_key" ON "team_invitations"("token");
  650. CREATE INDEX IF NOT EXISTS "team_invitations_token_idx" ON "team_invitations"("token");
  651. CREATE UNIQUE INDEX IF NOT EXISTS "team_invitations_email_organizationId_key" ON "team_invitations"("email", "organizationId");
  652. CREATE UNIQUE INDEX IF NOT EXISTS "subscription_plans_stripePriceId_key" ON "subscription_plans"("stripePriceId");
  653. CREATE UNIQUE INDEX IF NOT EXISTS "subscriptions_stripeSubscriptionId_key" ON "subscriptions"("stripeSubscriptionId");
  654. CREATE UNIQUE INDEX IF NOT EXISTS "subscriptions_organizationId_key" ON "subscriptions"("organizationId");
  655. CREATE INDEX IF NOT EXISTS "recurring_invoices_vehicleId_idx" ON "recurring_invoices"("vehicleId");
  656. CREATE INDEX IF NOT EXISTS "recurring_invoices_nextRunDate_isActive_idx" ON "recurring_invoices"("nextRunDate", "isActive");
  657. CREATE INDEX IF NOT EXISTS "inspection_templates_organizationId_idx" ON "inspection_templates"("organizationId");
  658. CREATE INDEX IF NOT EXISTS "inspection_template_sections_templateId_idx" ON "inspection_template_sections"("templateId");
  659. CREATE INDEX IF NOT EXISTS "inspection_template_items_sectionId_idx" ON "inspection_template_items"("sectionId");
  660. CREATE UNIQUE INDEX IF NOT EXISTS "inspections_publicToken_key" ON "inspections"("publicToken");
  661. CREATE INDEX IF NOT EXISTS "inspections_vehicleId_idx" ON "inspections"("vehicleId");
  662. CREATE INDEX IF NOT EXISTS "inspections_organizationId_idx" ON "inspections"("organizationId");
  663. CREATE INDEX IF NOT EXISTS "inspection_items_inspectionId_idx" ON "inspection_items"("inspectionId");
  664. CREATE INDEX IF NOT EXISTS "inspection_quote_requests_organizationId_idx" ON "inspection_quote_requests"("organizationId");
  665. CREATE INDEX IF NOT EXISTS "inspection_quote_requests_inspectionId_idx" ON "inspection_quote_requests"("inspectionId");
  666. CREATE INDEX IF NOT EXISTS "notifications_organizationId_createdAt_idx" ON "notifications"("organizationId", "createdAt" DESC);
  667. CREATE INDEX IF NOT EXISTS "notifications_organizationId_read_idx" ON "notifications"("organizationId", "read");
  668. CREATE INDEX IF NOT EXISTS "sms_messages_organizationId_customerId_createdAt_idx" ON "sms_messages"("organizationId", "customerId", "createdAt" DESC);
  669. CREATE INDEX IF NOT EXISTS "sms_messages_organizationId_createdAt_idx" ON "sms_messages"("organizationId", "createdAt" DESC);
  670. CREATE INDEX IF NOT EXISTS "sms_messages_toNumber_organizationId_idx" ON "sms_messages"("toNumber", "organizationId");
  671. CREATE INDEX IF NOT EXISTS "technicians_organizationId_idx" ON "technicians"("organizationId");
  672. CREATE INDEX IF NOT EXISTS "board_assignments_organizationId_date_idx" ON "board_assignments"("organizationId", "date");
  673. CREATE INDEX IF NOT EXISTS "board_assignments_technicianId_date_idx" ON "board_assignments"("technicianId", "date");
  674. CREATE UNIQUE INDEX IF NOT EXISTS "board_assignments_serviceRecordId_date_key" ON "board_assignments"("serviceRecordId", "date");
  675. CREATE UNIQUE INDEX IF NOT EXISTS "board_assignments_inspectionId_date_key" ON "board_assignments"("inspectionId", "date");
  676. CREATE UNIQUE INDEX IF NOT EXISTS "customer_sessions_token_key" ON "customer_sessions"("token");
  677. CREATE INDEX IF NOT EXISTS "customer_sessions_token_idx" ON "customer_sessions"("token");
  678. CREATE INDEX IF NOT EXISTS "customer_sessions_customerId_organizationId_idx" ON "customer_sessions"("customerId", "organizationId");
  679. CREATE UNIQUE INDEX IF NOT EXISTS "customer_magic_links_token_key" ON "customer_magic_links"("token");
  680. CREATE INDEX IF NOT EXISTS "customer_magic_links_token_idx" ON "customer_magic_links"("token");
  681. CREATE INDEX IF NOT EXISTS "service_requests_organizationId_status_idx" ON "service_requests"("organizationId", "status");
  682. CREATE INDEX IF NOT EXISTS "service_requests_customerId_idx" ON "service_requests"("customerId");
  683. -- AddForeignKey (idempotent: drop if exists, then add)
  684. DO $$ BEGIN
  685. ALTER TABLE "app_settings" ADD CONSTRAINT "app_settings_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  686. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  687. DO $$ BEGIN
  688. ALTER TABLE "app_settings" ADD CONSTRAINT "app_settings_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  689. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  690. DO $$ BEGIN
  691. ALTER TABLE "sessions" ADD CONSTRAINT "sessions_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  692. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  693. DO $$ BEGIN
  694. ALTER TABLE "accounts" ADD CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  695. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  696. DO $$ BEGIN
  697. ALTER TABLE "two_factor" ADD CONSTRAINT "two_factor_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  698. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  699. DO $$ BEGIN
  700. ALTER TABLE "passkeys" ADD CONSTRAINT "passkeys_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  701. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  702. DO $$ BEGIN
  703. ALTER TABLE "vehicles" ADD CONSTRAINT "vehicles_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  704. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  705. DO $$ BEGIN
  706. ALTER TABLE "vehicles" ADD CONSTRAINT "vehicles_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  707. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  708. DO $$ BEGIN
  709. ALTER TABLE "vehicles" ADD CONSTRAINT "vehicles_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE SET NULL ON UPDATE CASCADE;
  710. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  711. DO $$ BEGIN
  712. ALTER TABLE "service_records" ADD CONSTRAINT "service_records_vehicleId_fkey" FOREIGN KEY ("vehicleId") REFERENCES "vehicles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  713. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  714. DO $$ BEGIN
  715. ALTER TABLE "notes" ADD CONSTRAINT "notes_vehicleId_fkey" FOREIGN KEY ("vehicleId") REFERENCES "vehicles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  716. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  717. DO $$ BEGIN
  718. ALTER TABLE "fuel_logs" ADD CONSTRAINT "fuel_logs_vehicleId_fkey" FOREIGN KEY ("vehicleId") REFERENCES "vehicles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  719. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  720. DO $$ BEGIN
  721. ALTER TABLE "reminders" ADD CONSTRAINT "reminders_vehicleId_fkey" FOREIGN KEY ("vehicleId") REFERENCES "vehicles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  722. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  723. DO $$ BEGIN
  724. ALTER TABLE "customers" ADD CONSTRAINT "customers_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  725. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  726. DO $$ BEGIN
  727. ALTER TABLE "customers" ADD CONSTRAINT "customers_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  728. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  729. DO $$ BEGIN
  730. ALTER TABLE "payments" ADD CONSTRAINT "payments_serviceRecordId_fkey" FOREIGN KEY ("serviceRecordId") REFERENCES "service_records"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  731. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  732. DO $$ BEGIN
  733. ALTER TABLE "service_attachments" ADD CONSTRAINT "service_attachments_serviceRecordId_fkey" FOREIGN KEY ("serviceRecordId") REFERENCES "service_records"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  734. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  735. DO $$ BEGIN
  736. ALTER TABLE "service_parts" ADD CONSTRAINT "service_parts_serviceRecordId_fkey" FOREIGN KEY ("serviceRecordId") REFERENCES "service_records"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  737. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  738. DO $$ BEGIN
  739. ALTER TABLE "service_labor" ADD CONSTRAINT "service_labor_serviceRecordId_fkey" FOREIGN KEY ("serviceRecordId") REFERENCES "service_records"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  740. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  741. DO $$ BEGIN
  742. ALTER TABLE "inventory_parts" ADD CONSTRAINT "inventory_parts_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  743. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  744. DO $$ BEGIN
  745. ALTER TABLE "inventory_parts" ADD CONSTRAINT "inventory_parts_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  746. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  747. DO $$ BEGIN
  748. ALTER TABLE "quotes" ADD CONSTRAINT "quotes_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  749. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  750. DO $$ BEGIN
  751. ALTER TABLE "quotes" ADD CONSTRAINT "quotes_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  752. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  753. DO $$ BEGIN
  754. ALTER TABLE "quotes" ADD CONSTRAINT "quotes_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE SET NULL ON UPDATE CASCADE;
  755. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  756. DO $$ BEGIN
  757. ALTER TABLE "quotes" ADD CONSTRAINT "quotes_vehicleId_fkey" FOREIGN KEY ("vehicleId") REFERENCES "vehicles"("id") ON DELETE SET NULL ON UPDATE CASCADE;
  758. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  759. DO $$ BEGIN
  760. ALTER TABLE "quotes" ADD CONSTRAINT "quotes_inspectionId_fkey" FOREIGN KEY ("inspectionId") REFERENCES "inspections"("id") ON DELETE SET NULL ON UPDATE CASCADE;
  761. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  762. DO $$ BEGIN
  763. ALTER TABLE "quote_attachments" ADD CONSTRAINT "quote_attachments_quoteId_fkey" FOREIGN KEY ("quoteId") REFERENCES "quotes"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  764. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  765. DO $$ BEGIN
  766. ALTER TABLE "quote_parts" ADD CONSTRAINT "quote_parts_quoteId_fkey" FOREIGN KEY ("quoteId") REFERENCES "quotes"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  767. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  768. DO $$ BEGIN
  769. ALTER TABLE "quote_labor" ADD CONSTRAINT "quote_labor_quoteId_fkey" FOREIGN KEY ("quoteId") REFERENCES "quotes"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  770. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  771. DO $$ BEGIN
  772. ALTER TABLE "custom_field_definitions" ADD CONSTRAINT "custom_field_definitions_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  773. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  774. DO $$ BEGIN
  775. ALTER TABLE "custom_field_definitions" ADD CONSTRAINT "custom_field_definitions_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  776. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  777. DO $$ BEGIN
  778. ALTER TABLE "custom_field_values" ADD CONSTRAINT "custom_field_values_fieldId_fkey" FOREIGN KEY ("fieldId") REFERENCES "custom_field_definitions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  779. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  780. DO $$ BEGIN
  781. ALTER TABLE "organization_members" ADD CONSTRAINT "organization_members_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  782. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  783. DO $$ BEGIN
  784. ALTER TABLE "organization_members" ADD CONSTRAINT "organization_members_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  785. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  786. DO $$ BEGIN
  787. ALTER TABLE "organization_members" ADD CONSTRAINT "organization_members_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "roles"("id") ON DELETE SET NULL ON UPDATE CASCADE;
  788. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  789. DO $$ BEGIN
  790. ALTER TABLE "roles" ADD CONSTRAINT "roles_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  791. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  792. DO $$ BEGIN
  793. ALTER TABLE "permissions" ADD CONSTRAINT "permissions_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "roles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  794. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  795. DO $$ BEGIN
  796. ALTER TABLE "team_invitations" ADD CONSTRAINT "team_invitations_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  797. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  798. DO $$ BEGIN
  799. ALTER TABLE "team_invitations" ADD CONSTRAINT "team_invitations_roleId_fkey" FOREIGN KEY ("roleId") REFERENCES "roles"("id") ON DELETE SET NULL ON UPDATE CASCADE;
  800. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  801. DO $$ BEGIN
  802. ALTER TABLE "subscriptions" ADD CONSTRAINT "subscriptions_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  803. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  804. DO $$ BEGIN
  805. ALTER TABLE "subscriptions" ADD CONSTRAINT "subscriptions_planId_fkey" FOREIGN KEY ("planId") REFERENCES "subscription_plans"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
  806. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  807. DO $$ BEGIN
  808. ALTER TABLE "recurring_invoices" ADD CONSTRAINT "recurring_invoices_vehicleId_fkey" FOREIGN KEY ("vehicleId") REFERENCES "vehicles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  809. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  810. DO $$ BEGIN
  811. ALTER TABLE "recurring_parts" ADD CONSTRAINT "recurring_parts_recurringInvoiceId_fkey" FOREIGN KEY ("recurringInvoiceId") REFERENCES "recurring_invoices"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  812. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  813. DO $$ BEGIN
  814. ALTER TABLE "recurring_labor" ADD CONSTRAINT "recurring_labor_recurringInvoiceId_fkey" FOREIGN KEY ("recurringInvoiceId") REFERENCES "recurring_invoices"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  815. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  816. DO $$ BEGIN
  817. ALTER TABLE "inspection_templates" ADD CONSTRAINT "inspection_templates_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  818. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  819. DO $$ BEGIN
  820. ALTER TABLE "inspection_template_sections" ADD CONSTRAINT "inspection_template_sections_templateId_fkey" FOREIGN KEY ("templateId") REFERENCES "inspection_templates"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  821. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  822. DO $$ BEGIN
  823. ALTER TABLE "inspection_template_items" ADD CONSTRAINT "inspection_template_items_sectionId_fkey" FOREIGN KEY ("sectionId") REFERENCES "inspection_template_sections"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  824. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  825. DO $$ BEGIN
  826. ALTER TABLE "inspections" ADD CONSTRAINT "inspections_vehicleId_fkey" FOREIGN KEY ("vehicleId") REFERENCES "vehicles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  827. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  828. DO $$ BEGIN
  829. ALTER TABLE "inspections" ADD CONSTRAINT "inspections_templateId_fkey" FOREIGN KEY ("templateId") REFERENCES "inspection_templates"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
  830. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  831. DO $$ BEGIN
  832. ALTER TABLE "inspection_items" ADD CONSTRAINT "inspection_items_inspectionId_fkey" FOREIGN KEY ("inspectionId") REFERENCES "inspections"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  833. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  834. DO $$ BEGIN
  835. ALTER TABLE "inspection_quote_requests" ADD CONSTRAINT "inspection_quote_requests_inspectionId_fkey" FOREIGN KEY ("inspectionId") REFERENCES "inspections"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  836. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  837. DO $$ BEGIN
  838. ALTER TABLE "sms_messages" ADD CONSTRAINT "sms_messages_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  839. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  840. DO $$ BEGIN
  841. ALTER TABLE "sms_messages" ADD CONSTRAINT "sms_messages_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE SET NULL ON UPDATE CASCADE;
  842. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  843. DO $$ BEGIN
  844. ALTER TABLE "technicians" ADD CONSTRAINT "technicians_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  845. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  846. DO $$ BEGIN
  847. ALTER TABLE "board_assignments" ADD CONSTRAINT "board_assignments_technicianId_fkey" FOREIGN KEY ("technicianId") REFERENCES "technicians"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  848. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  849. DO $$ BEGIN
  850. ALTER TABLE "board_assignments" ADD CONSTRAINT "board_assignments_serviceRecordId_fkey" FOREIGN KEY ("serviceRecordId") REFERENCES "service_records"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  851. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  852. DO $$ BEGIN
  853. ALTER TABLE "board_assignments" ADD CONSTRAINT "board_assignments_inspectionId_fkey" FOREIGN KEY ("inspectionId") REFERENCES "inspections"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  854. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  855. DO $$ BEGIN
  856. ALTER TABLE "customer_sessions" ADD CONSTRAINT "customer_sessions_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  857. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  858. DO $$ BEGIN
  859. ALTER TABLE "service_requests" ADD CONSTRAINT "service_requests_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "customers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  860. EXCEPTION WHEN duplicate_object THEN NULL; END $$;
  861. DO $$ BEGIN
  862. ALTER TABLE "service_requests" ADD CONSTRAINT "service_requests_vehicleId_fkey" FOREIGN KEY ("vehicleId") REFERENCES "vehicles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
  863. EXCEPTION WHEN duplicate_object THEN NULL; END $$;