seed_dummy_data.ts 173 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270
  1. import { PrismaClient } from "../src/generated/prisma/client";
  2. import { PrismaPg } from "@prisma/adapter-pg";
  3. import { randomBytes, scryptSync } from "node:crypto";
  4. import * as fs from "fs";
  5. import * as path from "path";
  6. import * as https from "https";
  7. import * as http from "http";
  8. // Matches better-auth's scrypt params — output is byte-compatible with its hashPassword,
  9. // so the stored hash is verifiable by better-auth at sign-in time.
  10. function hashPassword(password: string): string {
  11. const N = 16384, r = 16, p = 1, dkLen = 64;
  12. const maxmem = 128 * N * r * 2;
  13. const salt = randomBytes(16).toString("hex");
  14. const key = scryptSync(password.normalize("NFKC"), salt, dkLen, { N, r, p, maxmem });
  15. return `${salt}:${key.toString("hex")}`;
  16. }
  17. const prisma = new PrismaClient({
  18. adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL }),
  19. });
  20. const USER_ID = "IqcAL6GKoedJNO8Xi6UJkCM5YZqgS9uU";
  21. const ORG_ID = "cmmh0vczm0000oiyan37vuyqf";
  22. const DEMO_EMAIL = process.env.DEMO_USER_EMAIL || "demo@torqvoice.com";
  23. const DEMO_PASSWORD = process.env.DEMO_USER_PASSWORD || "demo";
  24. const DEMO_ORG_NAME = process.env.DEMO_ORG_NAME || "Demo Auto Workshop";
  25. const DATA_ROOT = process.env.DATA_ROOT || path.join(process.cwd(), "data");
  26. const UPLOAD_DIR = path.join(DATA_ROOT, "uploads", ORG_ID, "vehicles");
  27. // Image assets bundled with the repo — preferred over live URL downloads so
  28. // the seed never fails when an Unsplash photo gets removed.
  29. const BUNDLED_IMAGE_DIR = path.join(process.cwd(), "prisma", "seed-assets", "vehicles");
  30. // All CDN URLs verified: extracted from Unsplash photo pages via curl, all return HTTP 200
  31. const vehicleImages: Record<string, string> = {
  32. // Cars
  33. "toyota-camry.jpg": "https://images.unsplash.com/photo-1621007947382-bb3c3994e3fb?w=800&q=80",
  34. "ford-f150-white.jpg": "https://images.unsplash.com/photo-1605152322346-bd2391778772?w=800&q=80",
  35. "ford-f150-grey.jpg": "https://images.unsplash.com/photo-1614218110929-caa460524fc1?w=800&q=80",
  36. "ford-f150-black.jpg": "https://images.unsplash.com/photo-1691809158613-1e4d51ad086f?w=800&q=80",
  37. "bmw-3series.jpg": "https://images.unsplash.com/photo-1629994562870-75d504fc02a1?w=800&q=80",
  38. "honda-civic.jpg": "https://images.unsplash.com/photo-1636915873177-a0c1a48d84eb?w=800&q=80",
  39. "tesla-model3.jpg": "https://images.unsplash.com/photo-1610470832703-95d40c3fad55?w=800&q=80",
  40. "tesla-modely.jpg": "https://images.unsplash.com/photo-1504507926084-34cf0b939964?w=800&q=80",
  41. "chevy-silverado.jpg": "https://images.unsplash.com/photo-1601919652576-41bad7c8ccbd?w=800&q=80",
  42. "mercedes-sprinter.jpg": "https://images.unsplash.com/photo-1535655685871-dc8158ff167e?w=800&q=80",
  43. "audi-a4.jpg": "https://images.unsplash.com/photo-1619732569416-83a8adfd8ac4?w=800&q=80",
  44. "jeep-wrangler.jpg": "https://images.unsplash.com/photo-1579097647275-16b002cced9e?w=800&q=80",
  45. "jeep-wrangler-orange.jpg": "https://images.unsplash.com/photo-1622364631585-831e11682a67?w=800&q=80",
  46. "porsche-911.jpg": "https://images.unsplash.com/photo-1624880056652-c7993c99190f?w=800&q=80",
  47. "vw-golf-gti-red.jpg": "https://images.unsplash.com/photo-1560282105-222992ffb774?w=800&q=80",
  48. "vw-golf-gti-grey.jpg": "https://images.unsplash.com/photo-1746184842826-73fd144a4587?w=800&q=80",
  49. "ram-1500.jpg": "https://images.unsplash.com/photo-1649793395985-967862a3b73f?w=800&q=80",
  50. "ram-1500-black.jpg": "https://images.unsplash.com/photo-1678492861610-0bd650a846fe?w=800&q=80",
  51. "toyota-tacoma.jpg": "https://images.unsplash.com/photo-1509510779868-337c9f58ad54?w=800&q=80",
  52. "subaru-outback.jpg": "https://images.unsplash.com/photo-1681680061152-d3fc0b999a8e?w=800&q=80",
  53. "subaru-forester.jpg": "https://images.unsplash.com/photo-1687048988997-ec57f83ea3bd?w=800&q=80",
  54. // Trucks
  55. "kenworth-t680.jpg": "https://images.unsplash.com/photo-1586191552066-d52dd1e3af86?w=800&q=80",
  56. "freightliner-cascadia.jpg": "https://images.unsplash.com/photo-1616432043562-3671ea2e5242?w=800&q=80",
  57. "volvo-fh640.jpg": "https://images.unsplash.com/photo-1633966100013-25a16d17b43d?w=800&q=80",
  58. "mack-granite.jpg": "https://images.unsplash.com/photo-1746349086423-06ea6b4d73f7?w=800&q=80",
  59. "concrete-mixer.jpg": "https://images.unsplash.com/photo-1530139675202-8c52bb810762?w=800&q=80",
  60. "dump-truck.jpg": "https://images.unsplash.com/photo-1686945127938-0296f10937ed?w=800&q=80",
  61. // Tractors
  62. "john-deere-6r.jpg": "https://images.unsplash.com/photo-1604923757148-f6e6957199c3?w=800&q=80",
  63. "fendt-942.jpg": "https://images.unsplash.com/photo-1629818572083-3ceb38e34322?w=800&q=80",
  64. "massey-ferguson.jpg": "https://images.unsplash.com/photo-1635351461882-9ffff1ce323c?w=800&q=80",
  65. "tractor-wheat.jpg": "https://images.unsplash.com/photo-1720273071277-190dd8f0a05a?w=800&q=80",
  66. "tractor-field.jpg": "https://images.unsplash.com/photo-1633554587766-ffc8151e31c0?w=800&q=80",
  67. "combine-harvester.jpg": "https://images.unsplash.com/photo-1754893889385-6c5a2d675524?w=800&q=80",
  68. "combine-jd.jpg": "https://images.unsplash.com/photo-1635174815612-fd9636f70146?w=800&q=80",
  69. // Heavy Machinery
  70. "cat-d6-bulldozer.jpg": "https://images.unsplash.com/photo-1621922688758-359fc864071e?w=800&q=80",
  71. "bulldozer-rocks.jpg": "https://images.unsplash.com/photo-1710669430606-30a8ceeb6e71?w=800&q=80",
  72. "komatsu-excavator.jpg": "https://images.unsplash.com/photo-1649807533255-bbc9c9fb7d77?w=800&q=80",
  73. "excavator-soil.jpg": "https://images.unsplash.com/photo-1622082679766-c5912d9416eb?w=800&q=80",
  74. "volvo-ec220e.jpg": "https://images.unsplash.com/photo-1568678453977-a90de6812e7a?w=800&q=80",
  75. "mini-excavator.jpg": "https://images.unsplash.com/photo-1722925837890-0fa0f0c9a356?w=800&q=80",
  76. "wheel-loader.jpg": "https://images.unsplash.com/photo-1630288214032-2c4cc2c080ca?w=800&q=80",
  77. "bulldozer-road.jpg": "https://images.unsplash.com/photo-1684431438566-6ff4a0df9190?w=800&q=80",
  78. "loader-field.jpg": "https://images.unsplash.com/photo-1727863526509-7670e063f308?w=800&q=80",
  79. "liebherr-crane.jpg": "https://images.unsplash.com/photo-1685305934074-3a7c37614c29?w=800&q=80",
  80. "crane-yellow.jpg": "https://images.unsplash.com/photo-1725882176928-de328f0d485a?w=800&q=80",
  81. "forklift.jpg": "https://images.unsplash.com/photo-1740914994657-f1cdffdc418e?w=800&q=80",
  82. // Additional vehicles
  83. "corvette-c8.jpg": "https://images.unsplash.com/photo-1750050677183-4e68b1d21b65?w=800&q=80",
  84. "land-rover-defender.jpg": "https://images.unsplash.com/photo-1741905358583-1999b08d6e2e?w=800&q=80",
  85. "dodge-charger.jpg": "https://images.unsplash.com/photo-1674520669939-1a8dbcdc2f6b?w=800&q=80",
  86. "subaru-wrx.jpg": "https://images.unsplash.com/photo-1747000586906-c451da789b62?w=800&q=80",
  87. };
  88. function downloadFile(url: string, dest: string): Promise<void> {
  89. return new Promise((resolve, reject) => {
  90. const dir = path.dirname(dest);
  91. if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
  92. const follow = (u: string, r = 0) => {
  93. if (r > 5) return reject(new Error("Too many redirects"));
  94. const mod = u.startsWith("https") ? https : http;
  95. mod.get(u, { headers: { "User-Agent": "Seed/1.0" } }, (res) => {
  96. if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) return follow(res.headers.location, r + 1);
  97. if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}`));
  98. const f = fs.createWriteStream(dest);
  99. res.pipe(f);
  100. f.on("finish", () => { f.close(); resolve(); });
  101. f.on("error", (e) => { fs.unlinkSync(dest); reject(e); });
  102. }).on("error", reject);
  103. };
  104. follow(url);
  105. });
  106. }
  107. function img(cat: string, file: string) { return `/api/files/${ORG_ID}/${cat}/${file}`; }
  108. async function provisionDemoAccount() {
  109. console.log("Provisioning demo user + organization...");
  110. // Owner user (idempotent — safe to re-run)
  111. await prisma.user.upsert({
  112. where: { id: USER_ID },
  113. create: {
  114. id: USER_ID,
  115. email: DEMO_EMAIL,
  116. name: "Demo Owner",
  117. emailVerified: true,
  118. termsAcceptedAt: new Date(),
  119. },
  120. update: { email: DEMO_EMAIL, name: "Demo Owner" },
  121. });
  122. // Credential account — wipe + recreate so the password always matches env
  123. const hashedPassword = hashPassword(DEMO_PASSWORD);
  124. await prisma.account.deleteMany({ where: { userId: USER_ID, providerId: "credential" } });
  125. await prisma.account.create({
  126. data: { accountId: USER_ID, providerId: "credential", userId: USER_ID, password: hashedPassword },
  127. });
  128. // Organization
  129. await prisma.organization.upsert({
  130. where: { id: ORG_ID },
  131. create: { id: ORG_ID, name: DEMO_ORG_NAME },
  132. update: { name: DEMO_ORG_NAME },
  133. });
  134. // Belt and braces alongside the demoGuard on org creation: purge any
  135. // foreign organizations so the reset always converges on a single org.
  136. // Org-scoped rows go with them via ON DELETE CASCADE, and stale
  137. // active-org cookies fall back to the demo org membership.
  138. // inspections.templateId is ON DELETE RESTRICT, so the cascade cannot
  139. // resolve templates and inspections in one statement; clear inspections
  140. // first. (The only other RESTRICT in the schema, subscriptions.planId,
  141. // guards global plans the purge never deletes.)
  142. await prisma.inspection.deleteMany({
  143. where: { organizationId: { not: ORG_ID } },
  144. });
  145. const foreignOrgs = await prisma.organization.deleteMany({
  146. where: { id: { not: ORG_ID } },
  147. });
  148. if (foreignOrgs.count > 0) {
  149. console.log(` Removed ${foreignOrgs.count} visitor-created organization(s).`);
  150. }
  151. // Owner membership
  152. await prisma.organizationMember.upsert({
  153. where: { userId_organizationId: { userId: USER_ID, organizationId: ORG_ID } },
  154. create: { userId: USER_ID, organizationId: ORG_ID, role: "owner" },
  155. update: { role: "owner" },
  156. });
  157. console.log(` Owner: ${DEMO_EMAIL} (org: ${DEMO_ORG_NAME})\n`);
  158. }
  159. /**
  160. * Remove files a demo visitor uploaded, while preserving the seed's own cached
  161. * vehicle images. `prisma/seed-assets/vehicles/` ships empty, so those images
  162. * were fetched from Unsplash once and cached in the data volume — deleting them
  163. * would trigger a full re-download on every 3-hourly reset.
  164. */
  165. function cleanupUploads() {
  166. const orgRoot = path.join(DATA_ROOT, "uploads", ORG_ID);
  167. if (!fs.existsSync(orgRoot)) return;
  168. const keep = new Set(Object.keys(vehicleImages));
  169. let removed = 0;
  170. const walk = (dir: string) => {
  171. for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
  172. const full = path.join(dir, entry.name);
  173. if (entry.isDirectory()) {
  174. walk(full);
  175. // Drop directories that are now empty (e.g. documents/, diagnostics/).
  176. if (fs.readdirSync(full).length === 0) fs.rmdirSync(full);
  177. continue;
  178. }
  179. // Preserve the cached seed images living in uploads/<org>/vehicles/.
  180. if (dir === UPLOAD_DIR && keep.has(entry.name)) continue;
  181. fs.unlinkSync(full);
  182. removed++;
  183. }
  184. };
  185. try {
  186. walk(orgRoot);
  187. console.log(` Removed ${removed} visitor-uploaded file(s).`);
  188. } catch (err) {
  189. console.warn(" Upload cleanup failed:", err);
  190. }
  191. }
  192. async function cleanup() {
  193. console.log("Cleaning existing data...");
  194. // Config/state a visitor can change that would otherwise survive every reset:
  195. // branding, invoice templates, webhooks pointing at external URLs, schedules,
  196. // custom presets. Deleting a Webhook cascades its WebhookDelivery rows.
  197. await prisma.webhook.deleteMany({ where: { organizationId: ORG_ID } });
  198. await prisma.reportSchedule.deleteMany({ where: { organizationId: ORG_ID } });
  199. await prisma.teamInvitation.deleteMany({ where: { organizationId: ORG_ID } });
  200. await prisma.laborPreset.deleteMany({ where: { organizationId: ORG_ID } });
  201. // Inspection.template is a required relation with no onDelete, so Postgres
  202. // restricts the template delete while any inspection still points at it.
  203. // Vehicle deletion further down would cascade these away, but that runs too
  204. // late — drop them here first. InspectionItem and InspectionQuoteRequest
  205. // cascade from Inspection, and Quote.inspectionId is SetNull.
  206. await prisma.inspection.deleteMany({ where: { organizationId: ORG_ID } });
  207. await prisma.inspectionTemplate.deleteMany({ where: { organizationId: ORG_ID } });
  208. await prisma.customFieldDefinition.deleteMany({ where: { organizationId: ORG_ID } });
  209. await prisma.subscription.deleteMany({ where: { organizationId: ORG_ID } });
  210. // Wipes branding, logo, invoice layout, localization, tax config. The
  211. // maintenance.* keys are re-upserted later in the seed.
  212. await prisma.appSetting.deleteMany({ where: { organizationId: ORG_ID } });
  213. // Transient/accumulating records.
  214. await prisma.aiChat.deleteMany({ where: { organizationId: ORG_ID } });
  215. await prisma.notification.deleteMany({ where: { organizationId: ORG_ID } });
  216. await prisma.telegramMessage.deleteMany({ where: { organizationId: ORG_ID } });
  217. await prisma.customerMagicLink.deleteMany({ where: { organizationId: ORG_ID } });
  218. await prisma.customerSmsCode.deleteMany({ where: { organizationId: ORG_ID } });
  219. await prisma.auditLog.deleteMany({ where: { organizationId: ORG_ID } });
  220. // Any team member a visitor added — but never the demo owner, which
  221. // provisionDemoAccount() upserts just before this runs.
  222. await prisma.organizationMember.deleteMany({
  223. where: { organizationId: ORG_ID, userId: { not: USER_ID } },
  224. });
  225. // Custom roles; OrganizationMember.roleId is onDelete: SetNull, so safe.
  226. await prisma.role.deleteMany({ where: { organizationId: ORG_ID } });
  227. // Core CRUD data. ServiceRequest, CustomerSession and StatusReport cascade
  228. // from Vehicle/Customer/ServiceRecord. Inspections are already gone above.
  229. await prisma.technician.deleteMany({ where: { organizationId: ORG_ID } });
  230. await prisma.smsMessage.deleteMany({ where: { organizationId: ORG_ID } });
  231. await prisma.quote.deleteMany({ where: { organizationId: ORG_ID } });
  232. await prisma.serviceRecord.deleteMany({ where: { vehicle: { organizationId: ORG_ID } } });
  233. await prisma.fuelLog.deleteMany({ where: { vehicle: { organizationId: ORG_ID } } });
  234. await prisma.reminder.deleteMany({ where: { vehicle: { organizationId: ORG_ID } } });
  235. await prisma.note.deleteMany({ where: { vehicle: { organizationId: ORG_ID } } });
  236. await prisma.vehicle.deleteMany({ where: { organizationId: ORG_ID } });
  237. await prisma.customer.deleteMany({ where: { organizationId: ORG_ID } });
  238. await prisma.inventoryPart.deleteMany({ where: { organizationId: ORG_ID } });
  239. cleanupUploads();
  240. console.log(" Done.\n");
  241. }
  242. async function seed() {
  243. console.log("\nStarting seed...\n");
  244. await provisionDemoAccount();
  245. await cleanup();
  246. // Every row the app scopes by organisation needs the column set, not just a
  247. // parent that has it: work orders and reminders were created without it and
  248. // the app, which reads `where: { organizationId }`, answered "Service record
  249. // not found" for all 101 seeded jobs and listed none of the 28 reminders.
  250. // Populate vehicle images: prefer bundled assets → fall back to cached copy
  251. // in data volume → fall back to live download.
  252. console.log("Populating vehicle images...");
  253. if (!fs.existsSync(UPLOAD_DIR)) fs.mkdirSync(UPLOAD_DIR, { recursive: true });
  254. for (const [file, url] of Object.entries(vehicleImages)) {
  255. const dest = path.join(UPLOAD_DIR, file);
  256. const bundled = path.join(BUNDLED_IMAGE_DIR, file);
  257. if (fs.existsSync(bundled)) {
  258. fs.copyFileSync(bundled, dest);
  259. console.log(` [bundled] ${file}`);
  260. continue;
  261. }
  262. if (fs.existsSync(dest)) { console.log(` [cached] ${file}`); continue; }
  263. try { await downloadFile(url, dest); console.log(` [downloaded] ${file}`); }
  264. catch { console.warn(` [fail] ${file}`); }
  265. }
  266. // -- Customers (20) --
  267. console.log("\nCreating customers...");
  268. const customers = await Promise.all([
  269. /* 0 */ prisma.customer.create({ data: { name: "Summit Construction Inc.", email: "fleet@summitconstruction.com", phone: "+1 (555) 100-2000", address: "742 Industrial Pkwy, Denver, CO 80216", company: "Summit Construction Inc.", notes: "Major fleet customer. 15 vehicles + heavy machinery. Net-30 terms.", userId: USER_ID, organizationId: ORG_ID } }),
  270. /* 1 */ prisma.customer.create({ data: { name: "James Mitchell", email: "james.mitchell@gmail.com", phone: "+1 (555) 201-3344", address: "1824 Maple Ave, Austin, TX 78701", notes: "Personal vehicles. Prefers synthetic oil.", userId: USER_ID, organizationId: ORG_ID } }),
  271. /* 2 */ prisma.customer.create({ data: { name: "Pacific Freight Lines", email: "service@pacificfreight.com", phone: "+1 (555) 302-5566", address: "9100 Logistics Blvd, Portland, OR 97201", company: "Pacific Freight Lines LLC", notes: "Long-haul trucking company. 8 semi-trucks. Priority service.", userId: USER_ID, organizationId: ORG_ID } }),
  272. /* 3 */ prisma.customer.create({ data: { name: "Sarah Coleman", email: "sarah.coleman@outlook.com", phone: "+1 (555) 403-7788", address: "567 Oak Street, Nashville, TN 37203", notes: "BMW and Porsche owner. Always requests OEM parts.", userId: USER_ID, organizationId: ORG_ID } }),
  273. /* 4 */ prisma.customer.create({ data: { name: "Metro City Services", email: "fleet@metrocityservices.gov", phone: "+1 (555) 504-9900", address: "100 City Hall Plaza, Boston, MA 02108", company: "Metro City Services", notes: "Municipal fleet contract. Quarterly invoicing. Purchase order required.", userId: USER_ID, organizationId: ORG_ID } }),
  274. /* 5 */ prisma.customer.create({ data: { name: "Ryan Parker", email: "ryan.parker@icloud.com", phone: "+1 (555) 605-1122", address: "2250 Cedar Lane, Seattle, WA 98101", notes: "Tesla and Subaru owner. Tech-savvy.", userId: USER_ID, organizationId: ORG_ID } }),
  275. /* 6 */ prisma.customer.create({ data: { name: "Ironclad Equipment Co.", email: "parts@ironcladequip.com", phone: "+1 (555) 706-3344", address: "4500 Heavy Machinery Rd, Houston, TX 77001", company: "Ironclad Equipment Co.", notes: "Heavy equipment dealer. Sends us overflow work. Good referral source.", userId: USER_ID, organizationId: ORG_ID } }),
  276. /* 7 */ prisma.customer.create({ data: { name: "David Chen", email: "david.chen@gmail.com", phone: "+1 (555) 807-5566", address: "890 Pine Street, San Francisco, CA 94102", notes: "Audi and VW owner. Referred by James Mitchell.", userId: USER_ID, organizationId: ORG_ID } }),
  277. /* 8 */ prisma.customer.create({ data: { name: "Ridgeline Excavation LLC", email: "ops@ridgelineexcavation.com", phone: "+1 (555) 908-7788", address: "1200 Quarry Rd, Salt Lake City, UT 84101", company: "Ridgeline Excavation LLC", notes: "5 excavators, 2 wheel loaders, 3 dump trucks. Monthly maintenance contract.", userId: USER_ID, organizationId: ORG_ID } }),
  278. /* 9 */ prisma.customer.create({ data: { name: "Amanda Foster", email: "amanda.foster@hotmail.com", phone: "+1 (555) 109-9900", address: "334 Birch Drive, Charlotte, NC 28202", notes: "Honda Civic owner. Budget-conscious, prefers aftermarket.", userId: USER_ID, organizationId: ORG_ID } }),
  279. /* 10 */ prisma.customer.create({ data: { name: "Prairie Farms Co-op", email: "maintenance@prairiefarms.com", phone: "+1 (555) 210-1122", address: "Route 66 Farm Road, Omaha, NE 68101", company: "Prairie Farms Co-op", notes: "Agricultural equipment. Tractors, harvesters. Seasonal peaks spring/fall.", userId: USER_ID, organizationId: ORG_ID } }),
  280. /* 11 */ prisma.customer.create({ data: { name: "Mike Thompson", email: "mike.thompson@yahoo.com", phone: "+1 (555) 311-3344", address: "445 Elm Court, Minneapolis, MN 55401", notes: "Ford F-150 and Jeep owner. Off-road enthusiast.", userId: USER_ID, organizationId: ORG_ID } }),
  281. /* 12 */ prisma.customer.create({ data: { name: "Apex Contractors Group", email: "service@apexcontractors.com", phone: "+1 (555) 412-5566", address: "2800 Builder's Row, Atlanta, GA 30301", company: "Apex Contractors Group", notes: "Small contractor. 2 excavators, 1 dump truck, 2 vans.", userId: USER_ID, organizationId: ORG_ID } }),
  282. /* 13 */ prisma.customer.create({ data: { name: "Jessica Rivera", email: "jessica.r@protonmail.com", phone: "+1 (555) 513-7788", address: "1100 Sunset Blvd, Miami, FL 33101", notes: "Tesla Model Y owner. Referred by Ryan Parker.", userId: USER_ID, organizationId: ORG_ID } }),
  283. /* 14 */ prisma.customer.create({ data: { name: "Titan Building Corp.", email: "projects@titanbuildingcorp.com", phone: "+1 (555) 614-9900", address: "5000 Commerce Dr, Dallas, TX 75201", company: "Titan Building Corp.", notes: "Large construction firm. 20+ pieces of equipment. Net-45 terms.", userId: USER_ID, organizationId: ORG_ID } }),
  284. /* 15 */ prisma.customer.create({ data: { name: "Kevin O'Brien", email: "kevin.obrien@gmail.com", phone: "+1 (555) 715-1122", address: "678 Market Street, Philadelphia, PA 19101", notes: "Mercedes Sprinter van for his catering business.", userId: USER_ID, organizationId: ORG_ID } }),
  285. /* 16 */ prisma.customer.create({ data: { name: "Greenfield Waste Management", email: "dispatch@greenfieldwaste.com", phone: "+1 (555) 816-3344", address: "7700 Recycling Way, Phoenix, AZ 85001", company: "Greenfield Waste Management", notes: "Waste management fleet. 12 trucks. Quarterly PM schedule.", userId: USER_ID, organizationId: ORG_ID } }),
  286. /* 17 */ prisma.customer.create({ data: { name: "Robert Hughes", email: "robert.hughes@outlook.com", phone: "+1 (555) 917-5566", address: "2100 Lakeview Ave, Detroit, MI 48201", notes: "Ram truck and VW Golf owner. Weekend car guy.", userId: USER_ID, organizationId: ORG_ID } }),
  287. /* 17 */ prisma.customer.create({ data: { name: "Heartland Grain Co.", email: "ops@heartlandgrain.com", phone: "+1 (555) 018-7788", address: "4400 Harvest Rd, Des Moines, IA 50301", company: "Heartland Grain Co.", notes: "Large-scale farming. 6 tractors, 2 combines. Seasonal rush spring and fall.", userId: USER_ID, organizationId: ORG_ID } }),
  288. /* 19 */ prisma.customer.create({ data: { name: "Lisa Martinez", email: "lisa.martinez@icloud.com", phone: "+1 (555) 119-9900", address: "425 Ranch Road, San Antonio, TX 78201", notes: "Chevy Silverado and Toyota Tacoma. Ranch use.", userId: USER_ID, organizationId: ORG_ID } }),
  289. ]);
  290. console.log(` Created ${customers.length} customers`);
  291. // -- Vehicles (40) --
  292. console.log("\nCreating vehicles...");
  293. const vehicles = await Promise.all([
  294. // === Cars (0-17) ===
  295. /* 0 */ prisma.vehicle.create({ data: { make: "Toyota", model: "Camry XSE", year: 2023, vin: "4T1K61AK5PU083241", licensePlate: "TX-8821", color: "Midnight Black", mileage: 18500, fuelType: "gasoline", transmission: "automatic", engineSize: "2.5L", purchaseDate: new Date("2023-03-15"), purchasePrice: 35500, imageUrl: img("vehicles","toyota-camry.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[1].id } }),
  296. /* 1 */ prisma.vehicle.create({ data: { make: "Ford", model: "F-150 Lariat", year: 2022, vin: "1FTFW1E88NFC12345", licensePlate: "CO-4455", color: "Oxford White", mileage: 42300, fuelType: "gasoline", transmission: "automatic", engineSize: "3.5L EcoBoost", purchaseDate: new Date("2022-06-20"), purchasePrice: 58000, imageUrl: img("vehicles","ford-f150-white.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[0].id } }),
  297. /* 2 */ prisma.vehicle.create({ data: { make: "Ford", model: "F-150 XLT", year: 2021, vin: "1FTEW1EP5MKD56789", licensePlate: "MN-7766", color: "Carbonized Gray", mileage: 55000, fuelType: "gasoline", transmission: "automatic", engineSize: "2.7L EcoBoost", purchaseDate: new Date("2021-04-10"), purchasePrice: 45000, imageUrl: img("vehicles","ford-f150-grey.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[11].id } }),
  298. /* 3 */ prisma.vehicle.create({ data: { make: "Ford", model: "F-150 Platinum", year: 2024, vin: "1FTFW1E55RFA98765", licensePlate: "TX-1199", color: "Agate Black", mileage: 12000, fuelType: "gasoline", transmission: "automatic", engineSize: "3.5L EcoBoost V6", purchaseDate: new Date("2024-02-14"), purchasePrice: 72000, imageUrl: img("vehicles","ford-f150-black.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[4].id } }),
  299. /* 4 */ prisma.vehicle.create({ data: { make: "BMW", model: "330i xDrive", year: 2021, vin: "WBA5R1C55M7B98765", licensePlate: "TN-2233", color: "Alpine White", mileage: 55200, fuelType: "gasoline", transmission: "automatic", engineSize: "2.0L Turbo", purchaseDate: new Date("2021-01-10"), purchasePrice: 46000, imageUrl: img("vehicles","bmw-3series.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[3].id } }),
  300. /* 5 */ prisma.vehicle.create({ data: { make: "Honda", model: "Civic Sport", year: 2020, vin: "2HGFC2F63LH567890", licensePlate: "NC-6677", color: "Rallye Red", mileage: 67800, fuelType: "gasoline", transmission: "manual", engineSize: "2.0L", purchaseDate: new Date("2020-08-05"), purchasePrice: 26000, imageUrl: img("vehicles","honda-civic.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[9].id } }),
  301. /* 6 */ prisma.vehicle.create({ data: { make: "Tesla", model: "Model 3 Long Range", year: 2024, vin: "5YJ3E1EA3RF123456", licensePlate: "WA-9901", color: "Pearl White", mileage: 8200, fuelType: "electric", transmission: "automatic", engineSize: "Dual Motor", purchaseDate: new Date("2024-01-20"), purchasePrice: 47000, imageUrl: img("vehicles","tesla-model3.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[5].id } }),
  302. /* 7 */ prisma.vehicle.create({ data: { make: "Tesla", model: "Model Y Long Range", year: 2025, vin: "7SAYGDEE3SF123456", licensePlate: "FL-7720", color: "Quicksilver", mileage: 3200, fuelType: "electric", transmission: "automatic", engineSize: "Dual Motor AWD", purchaseDate: new Date("2025-06-10"), purchasePrice: 52000, imageUrl: img("vehicles","tesla-modely.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[13].id } }),
  303. /* 8 */ prisma.vehicle.create({ data: { make: "Chevrolet", model: "Silverado 2500HD", year: 2019, vin: "1GC4YREY5KF234567", licensePlate: "TX-3344", color: "Shadow Gray", mileage: 98400, fuelType: "diesel", transmission: "automatic", engineSize: "6.6L Duramax", purchaseDate: new Date("2019-04-12"), purchasePrice: 52000, imageUrl: img("vehicles","chevy-silverado.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[19].id } }),
  304. /* 9 */ prisma.vehicle.create({ data: { make: "Mercedes-Benz", model: "Sprinter 316 CDI", year: 2022, vin: "WDB9066331S789012", licensePlate: "PA-1122", color: "Arctic White", mileage: 35600, fuelType: "diesel", transmission: "automatic", engineSize: "2.1L CDI", purchaseDate: new Date("2022-09-01"), purchasePrice: 55000, imageUrl: img("vehicles","mercedes-sprinter.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[15].id } }),
  305. /* 10 */ prisma.vehicle.create({ data: { make: "Audi", model: "A4 Quattro", year: 2023, vin: "WAUDNAF44PN345678", licensePlate: "CA-5566", color: "Navarra Blue", mileage: 22100, fuelType: "gasoline", transmission: "automatic", engineSize: "2.0L TFSI", purchaseDate: new Date("2023-07-14"), purchasePrice: 45000, imageUrl: img("vehicles","audi-a4.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[7].id } }),
  306. /* 11 */ prisma.vehicle.create({ data: { make: "Jeep", model: "Wrangler Rubicon", year: 2022, vin: "1C4HJXFN3NW234567", licensePlate: "CO-8800", color: "Black", mileage: 28500, fuelType: "gasoline", transmission: "manual", engineSize: "3.6L Pentastar V6", purchaseDate: new Date("2022-05-18"), purchasePrice: 52000, imageUrl: img("vehicles","jeep-wrangler.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[11].id } }),
  307. /* 12 */ prisma.vehicle.create({ data: { make: "Jeep", model: "Wrangler Sport S", year: 2023, vin: "1C4GJXAG4PW345678", licensePlate: "GA-5511", color: "Punk'n Orange", mileage: 15200, fuelType: "gasoline", transmission: "automatic", engineSize: "2.0L Turbo", purchaseDate: new Date("2023-08-22"), purchasePrice: 42000, imageUrl: img("vehicles","jeep-wrangler-orange.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[12].id } }),
  308. /* 13 */ prisma.vehicle.create({ data: { make: "Porsche", model: "911 Carrera S", year: 2022, vin: "WP0AB2A94NS234567", licensePlate: "TN-9911", color: "White", mileage: 12800, fuelType: "gasoline", transmission: "automatic", engineSize: "3.0L Twin-Turbo Flat-6", purchaseDate: new Date("2022-11-05"), purchasePrice: 128000, imageUrl: img("vehicles","porsche-911.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[3].id } }),
  309. /* 14 */ prisma.vehicle.create({ data: { make: "Volkswagen", model: "Golf GTI", year: 2021, vin: "3VW6T7AU5MM123456", licensePlate: "CA-4422", color: "Tornado Red", mileage: 38500, fuelType: "gasoline", transmission: "manual", engineSize: "2.0L TSI", purchaseDate: new Date("2021-06-15"), purchasePrice: 32000, imageUrl: img("vehicles","vw-golf-gti-red.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[7].id } }),
  310. /* 15 */ prisma.vehicle.create({ data: { make: "Ram", model: "1500 Laramie", year: 2023, vin: "1C6SRFJT4PN456789", licensePlate: "MI-3322", color: "Billet Silver", mileage: 19800, fuelType: "gasoline", transmission: "automatic", engineSize: "5.7L HEMI V8", purchaseDate: new Date("2023-03-28"), purchasePrice: 62000, imageUrl: img("vehicles","ram-1500.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[17].id } }),
  311. /* 16 */ prisma.vehicle.create({ data: { make: "Toyota", model: "Tacoma TRD Off-Road", year: 2022, vin: "3TMCZ5AN5NM567890", licensePlate: "TX-6644", color: "Super White", mileage: 31200, fuelType: "gasoline", transmission: "automatic", engineSize: "3.5L V6", purchaseDate: new Date("2022-10-01"), purchasePrice: 42000, imageUrl: img("vehicles","toyota-tacoma.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[19].id } }),
  312. // === Trucks (17-21) ===
  313. /* 17 */ prisma.vehicle.create({ data: { make: "Kenworth", model: "T680 Next Gen", year: 2022, vin: "1XKYD49X4NJ456789", licensePlate: "OR-8899", color: "Red", mileage: 185000, fuelType: "diesel", transmission: "automatic", engineSize: "12.9L PACCAR MX-13", purchaseDate: new Date("2022-02-15"), purchasePrice: 175000, imageUrl: img("vehicles","kenworth-t680.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[2].id } }),
  314. /* 18 */ prisma.vehicle.create({ data: { make: "Volvo", model: "FH 640", year: 2023, vin: "YV2RT40A5PB567890", licensePlate: "IL-5567", color: "Blue", mileage: 92000, fuelType: "diesel", transmission: "automatic", engineSize: "12.8L D13TC", purchaseDate: new Date("2023-01-10"), purchasePrice: 210000, imageUrl: img("vehicles","volvo-fh640.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[2].id } }),
  315. /* 19 */ prisma.vehicle.create({ data: { make: "Mack", model: "Granite GR64F", year: 2020, vin: "1M2AX04C5LM012345", licensePlate: "AZ-9901", color: "Yellow", mileage: 156000, fuelType: "diesel", transmission: "automatic", engineSize: "13.0L MP7", purchaseDate: new Date("2020-11-08"), purchasePrice: 140000, imageUrl: img("vehicles","mack-granite.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[0].id } }),
  316. /* 20 */ prisma.vehicle.create({ data: { make: "Peterbilt", model: "567 Mixer", year: 2021, vin: "1NPCD49X1MD678901", licensePlate: "TX-7788", color: "White/Blue", mileage: 68000, fuelType: "diesel", transmission: "automatic", engineSize: "10.8L PACCAR MX-11", purchaseDate: new Date("2021-07-20"), purchasePrice: 165000, imageUrl: img("vehicles","concrete-mixer.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[14].id } }),
  317. /* 21 */ prisma.vehicle.create({ data: { make: "Kenworth", model: "T880 Dump Truck", year: 2022, vin: "1NKZX4TX8NJ789012", licensePlate: "CO-5544", color: "Yellow", mileage: 82000, fuelType: "diesel", transmission: "automatic", engineSize: "12.9L PACCAR MX-13", purchaseDate: new Date("2022-04-15"), purchasePrice: 185000, imageUrl: img("vehicles","dump-truck.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[8].id } }),
  318. // === Tractors (22-28) ===
  319. /* 22 */ prisma.vehicle.create({ data: { make: "John Deere", model: "6R 250", year: 2022, vin: "1L06250RCNR012345", licensePlate: "N/A", color: "John Deere Green", mileage: 2800, fuelType: "diesel", transmission: "powershift", engineSize: "6.8L PowerTech PVS", purchaseDate: new Date("2022-03-01"), purchasePrice: 185000, imageUrl: img("vehicles","john-deere-6r.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[10].id } }),
  320. /* 23 */ prisma.vehicle.create({ data: { make: "Fendt", model: "942 Vario", year: 2023, vin: "FEN942VARIO3N56789", licensePlate: "N/A", color: "Fendt Green", mileage: 1200, fuelType: "diesel", transmission: "CVT (Vario)", engineSize: "12.4L MAN D2676", purchaseDate: new Date("2023-06-15"), purchasePrice: 420000, imageUrl: img("vehicles","fendt-942.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[18].id } }),
  321. /* 24 */ prisma.vehicle.create({ data: { make: "Massey Ferguson", model: "8S.265", year: 2021, vin: "MF8S265A1LM234567", licensePlate: "N/A", color: "Red", mileage: 3600, fuelType: "diesel", transmission: "Dyna-VT CVT", engineSize: "8.4L AGCO Power", purchaseDate: new Date("2021-09-10"), purchasePrice: 245000, imageUrl: img("vehicles","massey-ferguson.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[10].id } }),
  322. /* 25 */ prisma.vehicle.create({ data: { make: "John Deere", model: "8R 410", year: 2024, vin: "1RW8410RPEN345678", licensePlate: "N/A", color: "Green/Yellow", mileage: 800, fuelType: "diesel", transmission: "e23 PowerShift", engineSize: "9.0L PowerTech PSS", purchaseDate: new Date("2024-01-20"), purchasePrice: 380000, imageUrl: img("vehicles","tractor-wheat.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[18].id } }),
  323. /* 26 */ prisma.vehicle.create({ data: { make: "New Holland", model: "T7.315", year: 2022, vin: "NH7315ACLM456789", licensePlate: "N/A", color: "New Holland Blue", mileage: 2100, fuelType: "diesel", transmission: "Auto Command CVT", engineSize: "6.7L NEF", purchaseDate: new Date("2022-08-05"), purchasePrice: 210000, imageUrl: img("vehicles","tractor-field.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[10].id } }),
  324. /* 27 */ prisma.vehicle.create({ data: { make: "John Deere", model: "S780 Combine", year: 2023, vin: "1H0S780SPN567890", licensePlate: "N/A", color: "Green/Yellow", mileage: 600, fuelType: "diesel", transmission: "hydrostatic", engineSize: "13.5L PowerTech PSS", purchaseDate: new Date("2023-05-10"), purchasePrice: 520000, imageUrl: img("vehicles","combine-harvester.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[18].id } }),
  325. /* 28 */ prisma.vehicle.create({ data: { make: "John Deere", model: "X9 1100 Combine", year: 2024, vin: "1H0X91100RN678901", licensePlate: "N/A", color: "Green/Yellow", mileage: 350, fuelType: "diesel", transmission: "hydrostatic", engineSize: "13.6L PowerTech", purchaseDate: new Date("2024-03-15"), purchasePrice: 680000, imageUrl: img("vehicles","combine-jd.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[18].id } }),
  326. // === Heavy Machinery (29-37) ===
  327. /* 29 */ prisma.vehicle.create({ data: { make: "Caterpillar", model: "D6 XE Bulldozer", year: 2021, vin: "CAT0D6XE2LM012345", licensePlate: "N/A", color: "CAT Yellow", mileage: 4200, fuelType: "diesel", transmission: "automatic", engineSize: "9.3L C9.3B", purchaseDate: new Date("2021-03-25"), purchasePrice: 320000, imageUrl: img("vehicles","cat-d6-bulldozer.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[0].id } }),
  328. /* 30 */ prisma.vehicle.create({ data: { make: "Caterpillar", model: "D8T Bulldozer", year: 2020, vin: "CAT0D8T2KM234567", licensePlate: "N/A", color: "CAT Yellow", mileage: 5800, fuelType: "diesel", transmission: "automatic", engineSize: "15.2L C15", purchaseDate: new Date("2020-06-10"), purchasePrice: 480000, imageUrl: img("vehicles","bulldozer-rocks.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[14].id } }),
  329. /* 31 */ prisma.vehicle.create({ data: { make: "Komatsu", model: "PC210LC-11 Excavator", year: 2022, vin: "KMTPC210LCN234567", licensePlate: "N/A", color: "Komatsu Blue/White", mileage: 3100, fuelType: "diesel", transmission: "hydraulic", engineSize: "6.7L SAA6D107E-3", purchaseDate: new Date("2022-07-12"), purchasePrice: 265000, imageUrl: img("vehicles","komatsu-excavator.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[8].id } }),
  330. /* 32 */ prisma.vehicle.create({ data: { make: "Komatsu", model: "PC490LC-11 Excavator", year: 2023, vin: "KMTPC490LCN345678", licensePlate: "N/A", color: "Komatsu Yellow", mileage: 1800, fuelType: "diesel", transmission: "hydraulic", engineSize: "15.2L SAA6D170E-7", purchaseDate: new Date("2023-01-20"), purchasePrice: 450000, imageUrl: img("vehicles","excavator-soil.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[8].id } }),
  331. /* 33 */ prisma.vehicle.create({ data: { make: "Volvo", model: "EC220E Excavator", year: 2023, vin: "VOLEC220EN3M345678", licensePlate: "N/A", color: "Volvo Yellow", mileage: 1500, fuelType: "diesel", transmission: "hydraulic", engineSize: "5.7L D6J", purchaseDate: new Date("2023-02-20"), purchasePrice: 280000, imageUrl: img("vehicles","volvo-ec220e.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[8].id } }),
  332. /* 34 */ prisma.vehicle.create({ data: { make: "Kubota", model: "KX040-4 Mini Excavator", year: 2023, vin: "KUB040KX4N3456789", licensePlate: "N/A", color: "Orange", mileage: 900, fuelType: "diesel", transmission: "hydraulic", engineSize: "1.8L D1803-CR-TE4", purchaseDate: new Date("2023-09-15"), purchasePrice: 62000, imageUrl: img("vehicles","mini-excavator.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[12].id } }),
  333. /* 35 */ prisma.vehicle.create({ data: { make: "Case", model: "621G Wheel Loader", year: 2023, vin: "CASE621GN3M456789", licensePlate: "N/A", color: "Power Tan", mileage: 1800, fuelType: "diesel", transmission: "automatic", engineSize: "6.7L FPT", purchaseDate: new Date("2023-04-18"), purchasePrice: 185000, imageUrl: img("vehicles","wheel-loader.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[4].id } }),
  334. /* 36 */ prisma.vehicle.create({ data: { make: "Liebherr", model: "LTM 1100-4.2 Crane", year: 2019, vin: "LBH1100LTM9K12345", licensePlate: "GA-2233", color: "Yellow", mileage: 12500, fuelType: "diesel", transmission: "automatic", engineSize: "10.7L D936", purchaseDate: new Date("2019-08-14"), purchasePrice: 850000, imageUrl: img("vehicles","liebherr-crane.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[14].id } }),
  335. /* 37 */ prisma.vehicle.create({ data: { make: "Toyota", model: "8FBE18 Forklift", year: 2022, vin: "TYT8FBE18N2M56789", licensePlate: "N/A", color: "Orange/Black", mileage: 4200, fuelType: "electric", transmission: "automatic", engineSize: "48V AC Motor", purchaseDate: new Date("2022-11-01"), purchasePrice: 35000, imageUrl: img("vehicles","forklift.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[6].id } }),
  336. // === Additional Vehicles (38-41) ===
  337. /* 38 */ prisma.vehicle.create({ data: { make: "Chevrolet", model: "Corvette Stingray", year: 2024, vin: "1G1YB2D48R5100234", licensePlate: "TN-0038", color: "Black", mileage: 6200, fuelType: "gasoline", transmission: "automatic", engineSize: "6.2L LT2 V8", purchaseDate: new Date("2024-05-10"), purchasePrice: 68000, imageUrl: img("vehicles","corvette-c8.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[3].id } }),
  338. /* 39 */ prisma.vehicle.create({ data: { make: "Land Rover", model: "Defender 110 S", year: 2023, vin: "SALE7EEU5P1234567", licensePlate: "CO-3911", color: "Santorini Black", mileage: 28500, fuelType: "gasoline", transmission: "automatic", engineSize: "3.0L I6 Turbo", purchaseDate: new Date("2023-06-22"), purchasePrice: 62000, imageUrl: img("vehicles","land-rover-defender.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[11].id } }),
  339. /* 40 */ prisma.vehicle.create({ data: { make: "Dodge", model: "Charger R/T", year: 2022, vin: "2C3CDXCT5NH234567", licensePlate: "MI-4022", color: "Go Mango Orange", mileage: 34800, fuelType: "gasoline", transmission: "automatic", engineSize: "5.7L HEMI V8", purchaseDate: new Date("2022-08-15"), purchasePrice: 45000, imageUrl: img("vehicles","dodge-charger.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[17].id } }),
  340. /* 41 */ prisma.vehicle.create({ data: { make: "Subaru", model: "WRX Premium", year: 2024, vin: "JF1VA1E68R9234567", licensePlate: "CA-4124", color: "WR Blue Pearl", mileage: 12400, fuelType: "gasoline", transmission: "manual", engineSize: "2.4L Turbo Boxer", purchaseDate: new Date("2024-03-01"), purchasePrice: 35000, imageUrl: img("vehicles","subaru-wrx.jpg"), userId: USER_ID, organizationId: ORG_ID, customerId: customers[7].id } }),
  341. ]);
  342. console.log(` Created ${vehicles.length} vehicles`);
  343. // -- Service Records (20) --
  344. console.log("\nCreating service records...");
  345. const svcData = [
  346. { vehicleId: vehicles[0].id, title: "Oil Change & Tire Rotation", description: "Regular 10,000 mi service. Synthetic 0W-20 oil. Rotated tires front to back.", type: "maintenance", status: "completed", serviceDate: new Date("2025-11-15"), mileage: 15000, techName: "Jake Wilson", shopName: "Egeland Auto",
  347. partItems: [{ name: "Synthetic Oil 0W-20 (5qt)", partNumber: "TOY-0W20-5Q", quantity: 1, unitPrice: 42, total: 42 }, { name: "Oil Filter", partNumber: "TOY-OF-2023", quantity: 1, unitPrice: 12, total: 12 }],
  348. laborItems: [{ description: "Oil change and filter replacement", hours: 0.5, rate: 95, total: 47.50 }, { description: "Tire rotation and pressure check", hours: 0.3, rate: 95, total: 28.50 }],
  349. subtotal: 130, taxRate: 8, taxAmount: 10.40, totalAmount: 140.40 },
  350. { vehicleId: vehicles[4].id, title: "50,000 Mile Major Service", description: "Major service interval. Replaced brake pads, rotors, spark plugs. Full inspection.", type: "maintenance", status: "completed", serviceDate: new Date("2025-10-20"), mileage: 50000, techName: "Chris Taylor", shopName: "Egeland Auto",
  351. partItems: [{ name: "Front Brake Pad Set", partNumber: "BMW-BP-F34", quantity: 1, unitPrice: 185, total: 185 }, { name: "Front Brake Rotors (pair)", partNumber: "BMW-BR-F34", quantity: 1, unitPrice: 320, total: 320 }, { name: "Spark Plugs (set of 4)", partNumber: "BMW-SP-N20", quantity: 1, unitPrice: 68, total: 68 }, { name: "Engine Oil 5W-30 (7qt)", partNumber: "BMW-5W30-7Q", quantity: 1, unitPrice: 89, total: 89 }],
  352. laborItems: [{ description: "Front brake pad and rotor replacement", hours: 2.0, rate: 110, total: 220 }, { description: "Spark plug replacement", hours: 1.0, rate: 110, total: 110 }, { description: "Oil change and multi-point inspection", hours: 1.0, rate: 110, total: 110 }],
  353. subtotal: 1102, taxRate: 8, taxAmount: 88.16, totalAmount: 1190.16 },
  354. { vehicleId: vehicles[6].id, title: "Tire Replacement - All Four", description: "Replaced all four tires. Michelin Pilot Sport 4S. Alignment check passed.", type: "repair", status: "completed", serviceDate: new Date("2026-01-08"), mileage: 7800, techName: "Jake Wilson", shopName: "Egeland Auto",
  355. partItems: [{ name: "Michelin Pilot Sport 4S 235/40R19", partNumber: "MICH-PS4S-2354019", quantity: 4, unitPrice: 310, total: 1240 }],
  356. laborItems: [{ description: "Mount and balance 4 tires", hours: 1.5, rate: 95, total: 142.50 }, { description: "Wheel alignment check", hours: 0.5, rate: 95, total: 47.50 }],
  357. subtotal: 1430, taxRate: 8, taxAmount: 114.40, totalAmount: 1544.40 },
  358. { vehicleId: vehicles[13].id, title: "Porsche 911 - Annual Service", description: "Annual service. Oil change, brake fluid flush, cabin filter. Full inspection.", type: "maintenance", status: "completed", serviceDate: new Date("2026-01-15"), mileage: 12500, techName: "Chris Taylor", shopName: "Egeland Auto",
  359. partItems: [{ name: "Porsche Approved Oil 0W-40 (9qt)", partNumber: "POR-0W40-9Q", quantity: 1, unitPrice: 165, total: 165 }, { name: "Oil Filter", partNumber: "POR-OF-992", quantity: 1, unitPrice: 28, total: 28 }, { name: "Brake Fluid DOT4 (1L)", partNumber: "POR-BF-DOT4", quantity: 2, unitPrice: 35, total: 70 }],
  360. laborItems: [{ description: "Oil and filter change", hours: 1.0, rate: 145, total: 145 }, { description: "Brake fluid flush all 4 corners", hours: 1.5, rate: 145, total: 217.50 }, { description: "Multi-point inspection", hours: 1.0, rate: 145, total: 145 }],
  361. subtotal: 770.50, taxRate: 8, taxAmount: 61.64, totalAmount: 832.14 },
  362. { vehicleId: vehicles[17].id, title: "150K Mile Engine Service - Kenworth", description: "Major engine service. Replaced fuel filters, air filters, coolant flush. DPF regen.", type: "maintenance", status: "completed", serviceDate: new Date("2025-12-05"), mileage: 180000, techName: "Marcus Reed", shopName: "Egeland Auto",
  363. partItems: [{ name: "PACCAR MX-13 Fuel Filter Kit", partNumber: "PAC-FF-MX13", quantity: 1, unitPrice: 125, total: 125 }, { name: "Air Filter Element", partNumber: "PAC-AF-MX13", quantity: 1, unitPrice: 85, total: 85 }, { name: "Coolant (5gal)", partNumber: "PAC-COOL-5G", quantity: 2, unitPrice: 65, total: 130 }, { name: "Engine Oil 15W-40 (10gal)", partNumber: "PAC-15W40-10G", quantity: 1, unitPrice: 280, total: 280 }],
  364. laborItems: [{ description: "Engine oil and filter change", hours: 2.0, rate: 125, total: 250 }, { description: "Fuel filter replacement", hours: 1.0, rate: 125, total: 125 }, { description: "Coolant flush and refill", hours: 1.5, rate: 125, total: 187.50 }, { description: "DPF regeneration and diagnostic", hours: 1.5, rate: 125, total: 187.50 }],
  365. subtotal: 1370, taxRate: 8, taxAmount: 109.60, totalAmount: 1479.60 },
  366. { vehicleId: vehicles[18].id, title: "Volvo FH 640 - DOT Inspection", description: "Full annual inspection per DOT regulations. Brake test, emissions, lights, safety.", type: "inspection", status: "in_progress", serviceDate: new Date("2026-02-18"), mileage: 92000, techName: "Marcus Reed", shopName: "Egeland Auto",
  367. partItems: [{ name: "Marker Light Bulbs (pack of 10)", partNumber: "VOL-MLB-10", quantity: 1, unitPrice: 35, total: 35 }, { name: "Wiper Blades (pair)", partNumber: "VOL-WB-FH", quantity: 1, unitPrice: 52, total: 52 }],
  368. laborItems: [{ description: "Full DOT inspection and documentation", hours: 4.0, rate: 125, total: 500 }, { description: "Minor repairs and adjustments", hours: 2.0, rate: 125, total: 250 }],
  369. subtotal: 837, taxRate: 8, taxAmount: 66.96, totalAmount: 903.96 },
  370. { vehicleId: vehicles[22].id, title: "John Deere 6R 250 - 500hr Service", description: "Scheduled 500-hour service. Engine oil, all filters, hydraulic fluid sample, PTO check.", type: "maintenance", status: "completed", serviceDate: new Date("2026-01-20"), mileage: 2500, techName: "Marcus Reed", shopName: "Egeland Auto",
  371. partItems: [{ name: "Engine Oil 15W-40 (5gal)", partNumber: "JD-15W40-5G", quantity: 1, unitPrice: 185, total: 185 }, { name: "Oil Filter", partNumber: "JD-OF-6R", quantity: 1, unitPrice: 32, total: 32 }, { name: "Fuel Filter Kit", partNumber: "JD-FFK-6R", quantity: 1, unitPrice: 68, total: 68 }, { name: "Hydraulic Filter", partNumber: "JD-HF-6R", quantity: 1, unitPrice: 55, total: 55 }, { name: "Air Filter Inner+Outer", partNumber: "JD-AF-6R", quantity: 1, unitPrice: 78, total: 78 }],
  372. laborItems: [{ description: "Engine oil and all filter replacement", hours: 2.0, rate: 140, total: 280 }, { description: "Hydraulic fluid sampling and analysis", hours: 0.5, rate: 140, total: 70 }, { description: "PTO and 3-point hitch inspection", hours: 1.0, rate: 140, total: 140 }, { description: "Grease all fittings (32 points)", hours: 1.5, rate: 140, total: 210 }],
  373. subtotal: 1118, taxRate: 8, taxAmount: 89.44, totalAmount: 1207.44 },
  374. { vehicleId: vehicles[23].id, title: "Fendt 942 - CVT Transmission Service", description: "CVT transmission fluid and filter change. Vario calibration and function test.", type: "maintenance", status: "completed", serviceDate: new Date("2025-11-10"), mileage: 1100, techName: "Chris Taylor", shopName: "Egeland Auto",
  375. partItems: [{ name: "Vario CVT Fluid (10gal)", partNumber: "FENDT-CVT-10G", quantity: 1, unitPrice: 420, total: 420 }, { name: "CVT Filter Kit", partNumber: "FENDT-CVTF-942", quantity: 1, unitPrice: 165, total: 165 }],
  376. laborItems: [{ description: "CVT transmission fluid drain and refill", hours: 3.0, rate: 150, total: 450 }, { description: "CVT filter replacement", hours: 1.5, rate: 150, total: 225 }, { description: "Vario transmission calibration", hours: 2.0, rate: 150, total: 300 }],
  377. subtotal: 1560, taxRate: 8, taxAmount: 124.80, totalAmount: 1684.80 },
  378. { vehicleId: vehicles[29].id, title: "CAT D6 - Hydraulic System Overhaul", description: "Complete hydraulic system service. Replaced main pump seals, flushed system, new filters.", type: "repair", status: "completed", serviceDate: new Date("2025-09-18"), mileage: 4000, techName: "Marcus Reed", shopName: "Egeland Auto",
  379. partItems: [{ name: "Hydraulic Pump Seal Kit", partNumber: "CAT-HPS-D6", quantity: 1, unitPrice: 450, total: 450 }, { name: "Hydraulic Oil (55gal drum)", partNumber: "CAT-HO-55G", quantity: 1, unitPrice: 850, total: 850 }, { name: "Hydraulic Filter Set", partNumber: "CAT-HF-D6", quantity: 2, unitPrice: 120, total: 240 }],
  380. laborItems: [{ description: "Hydraulic pump disassembly and seal replacement", hours: 6.0, rate: 140, total: 840 }, { description: "System flush and refill", hours: 3.0, rate: 140, total: 420 }, { description: "Pressure testing and calibration", hours: 2.0, rate: 140, total: 280 }],
  381. subtotal: 3080, taxRate: 8, taxAmount: 246.40, totalAmount: 3326.40 },
  382. { vehicleId: vehicles[31].id, title: "Komatsu PC210 - Track Chain Replacement", description: "Replaced both track chains and sprockets. Undercarriage inspection completed.", type: "repair", status: "completed", serviceDate: new Date("2026-01-22"), mileage: 3000, techName: "Chris Taylor", shopName: "Egeland Auto",
  383. partItems: [{ name: "Track Chain Assembly (left)", partNumber: "KOM-TC-PC210L", quantity: 1, unitPrice: 2800, total: 2800 }, { name: "Track Chain Assembly (right)", partNumber: "KOM-TC-PC210R", quantity: 1, unitPrice: 2800, total: 2800 }, { name: "Track Sprocket (pair)", partNumber: "KOM-TS-PC210", quantity: 1, unitPrice: 1200, total: 1200 }],
  384. laborItems: [{ description: "Track chain removal and installation (both sides)", hours: 8.0, rate: 140, total: 1120 }, { description: "Sprocket replacement", hours: 3.0, rate: 140, total: 420 }, { description: "Undercarriage inspection", hours: 2.0, rate: 140, total: 280 }],
  385. subtotal: 8620, taxRate: 8, taxAmount: 689.60, totalAmount: 9309.60 },
  386. { vehicleId: vehicles[33].id, title: "Volvo EC220E - 1000hr Full Service", description: "All fluids, filters, track tension, swing bearing inspection.", type: "maintenance", status: "in_progress", serviceDate: new Date("2026-02-25"), mileage: 1500, techName: "Chris Taylor", shopName: "Egeland Auto",
  387. partItems: [{ name: "Engine Oil 15W-40 (5gal)", partNumber: "VOL-15W40-5G", quantity: 1, unitPrice: 185, total: 185 }, { name: "Hydraulic Filter Set", partNumber: "VOL-HFS-EC220", quantity: 1, unitPrice: 120, total: 120 }, { name: "Fuel Filter Kit", partNumber: "VOL-FFK-EC220", quantity: 1, unitPrice: 58, total: 58 }],
  388. laborItems: [{ description: "Engine oil and all filter replacement", hours: 2.5, rate: 140, total: 350 }, { description: "Track tension adjustment", hours: 1.0, rate: 140, total: 140 }, { description: "Full grease service (48 points)", hours: 2.0, rate: 140, total: 280 }],
  389. subtotal: 1133, taxRate: 8, taxAmount: 90.64, totalAmount: 1223.64 },
  390. { vehicleId: vehicles[11].id, title: "Jeep Wrangler - Lift Kit Install", description: "2.5\" suspension lift, new shocks, extended brake lines. Alignment after.", type: "repair", status: "completed", serviceDate: new Date("2026-02-10"), mileage: 28000, techName: "Jake Wilson", shopName: "Egeland Auto",
  391. partItems: [{ name: "Mopar 2.5\" Lift Kit", partNumber: "JEEP-LK-25", quantity: 1, unitPrice: 1200, total: 1200 }, { name: "Bilstein 5100 Shocks (set of 4)", partNumber: "BIL-5100-JL4", quantity: 1, unitPrice: 680, total: 680 }, { name: "Extended Brake Lines", partNumber: "JEEP-EBL-JL", quantity: 1, unitPrice: 120, total: 120 }],
  392. laborItems: [{ description: "Suspension lift installation", hours: 6.0, rate: 110, total: 660 }, { description: "Brake line routing and bleed", hours: 1.0, rate: 110, total: 110 }, { description: "4-wheel alignment", hours: 1.5, rate: 110, total: 165 }],
  393. subtotal: 2935, taxRate: 8, taxAmount: 234.80, totalAmount: 3169.80 },
  394. { vehicleId: vehicles[9].id, title: "Sprinter - Turbocharger Replacement", description: "Turbo shaft play detected. Black smoke under boost. Replaced turbo assembly.", type: "repair", status: "in_progress", serviceDate: new Date("2026-02-19"), mileage: 35400, techName: "Chris Taylor", shopName: "Egeland Auto",
  395. partItems: [{ name: "Turbocharger Assembly - OM651", partNumber: "MB-TURBO-OM651", quantity: 1, unitPrice: 1280, total: 1280 }, { name: "Turbo Oil Feed Line", partNumber: "MB-TOFL-OM651", quantity: 1, unitPrice: 68, total: 68 }, { name: "Turbo Gasket Kit", partNumber: "MB-TGK-OM651", quantity: 1, unitPrice: 42, total: 42 }],
  396. laborItems: [{ description: "Turbocharger removal", hours: 3.0, rate: 125, total: 375 }, { description: "New turbo installation and oil line", hours: 2.5, rate: 125, total: 312.50 }],
  397. subtotal: 2077.50, taxRate: 8, taxAmount: 166.20, totalAmount: 2243.70 },
  398. { vehicleId: vehicles[24].id, title: "Massey Ferguson 8S - Hydraulic Pump", description: "Low hydraulic pressure. Replaced main pump and flushed system.", type: "repair", status: "completed", serviceDate: new Date("2026-02-05"), mileage: 3500, techName: "Marcus Reed", shopName: "Egeland Auto",
  399. partItems: [{ name: "Main Hydraulic Pump Assembly", partNumber: "MF-HPA-8S", quantity: 1, unitPrice: 1650, total: 1650 }, { name: "Hydraulic Oil (15gal)", partNumber: "HYD-ISO46-15G", quantity: 1, unitPrice: 280, total: 280 }, { name: "Hydraulic Filter Set", partNumber: "MF-HFS-8S", quantity: 1, unitPrice: 95, total: 95 }],
  400. laborItems: [{ description: "Hydraulic pump removal", hours: 4.0, rate: 140, total: 560 }, { description: "New pump installation", hours: 3.0, rate: 140, total: 420 }, { description: "System flush and pressure test", hours: 2.0, rate: 140, total: 280 }],
  401. subtotal: 3285, taxRate: 8, taxAmount: 262.80, totalAmount: 3547.80 },
  402. { vehicleId: vehicles[15].id, title: "Ram 1500 - Brake Service", description: "Front and rear brake pad replacement. Rotor resurface. Fluid flush.", type: "maintenance", status: "completed", serviceDate: new Date("2026-01-28"), mileage: 19500, techName: "Jake Wilson", shopName: "Egeland Auto",
  403. partItems: [{ name: "Front Brake Pad Set", partNumber: "RAM-BP-F-DS", quantity: 1, unitPrice: 145, total: 145 }, { name: "Rear Brake Pad Set", partNumber: "RAM-BP-R-DS", quantity: 1, unitPrice: 125, total: 125 }, { name: "Brake Fluid DOT4 (1L)", partNumber: "BF-DOT4-1L", quantity: 2, unitPrice: 18, total: 36 }],
  404. laborItems: [{ description: "Front brake pad replacement", hours: 1.5, rate: 110, total: 165 }, { description: "Rear brake pad replacement", hours: 1.0, rate: 110, total: 110 }, { description: "Rotor resurface (all 4)", hours: 1.0, rate: 110, total: 110 }, { description: "Brake fluid flush", hours: 0.5, rate: 110, total: 55 }],
  405. subtotal: 746, taxRate: 8, taxAmount: 59.68, totalAmount: 805.68 },
  406. { vehicleId: vehicles[14].id, title: "VW Golf GTI - DSG Service + Oil", description: "DSG transmission fluid/filter. Engine oil change. Cabin filter.", type: "maintenance", status: "completed", serviceDate: new Date("2025-12-20"), mileage: 38000, techName: "Jake Wilson", shopName: "Egeland Auto",
  407. partItems: [{ name: "DSG Fluid (7qt)", partNumber: "VW-DSG-7Q", quantity: 1, unitPrice: 145, total: 145 }, { name: "DSG Filter", partNumber: "VW-DSGF", quantity: 1, unitPrice: 52, total: 52 }, { name: "Engine Oil 5W-40 (5qt)", partNumber: "VW-5W40-5Q", quantity: 1, unitPrice: 58, total: 58 }],
  408. laborItems: [{ description: "DSG fluid and filter change", hours: 1.5, rate: 110, total: 165 }, { description: "Engine oil and filter change", hours: 0.5, rate: 110, total: 55 }],
  409. subtotal: 475, taxRate: 8, taxAmount: 38, totalAmount: 513 },
  410. { vehicleId: vehicles[19].id, title: "Mack Granite - PTO Pump Replacement", description: "PTO pump failed. No hydraulic pressure for dump body. Replaced and tested.", type: "repair", status: "completed", serviceDate: new Date("2025-12-28"), mileage: 154000, techName: "Marcus Reed", shopName: "Egeland Auto",
  411. partItems: [{ name: "PTO Hydraulic Pump", partNumber: "MACK-PTO-GR64", quantity: 1, unitPrice: 1450, total: 1450 }, { name: "PTO Mounting Gasket Kit", partNumber: "MACK-PTO-GK", quantity: 1, unitPrice: 85, total: 85 }, { name: "Hydraulic Oil (10gal)", partNumber: "HYD-ISO46-10G", quantity: 1, unitPrice: 180, total: 180 }],
  412. laborItems: [{ description: "PTO pump removal", hours: 3.0, rate: 140, total: 420 }, { description: "New pump installation", hours: 2.5, rate: 140, total: 350 }, { description: "System prime and dump cycle test", hours: 1.5, rate: 140, total: 210 }],
  413. subtotal: 2695, taxRate: 8, taxAmount: 215.60, totalAmount: 2910.60 },
  414. { vehicleId: vehicles[35].id, title: "Case 621G - Bucket Cylinder Reseal", description: "Bucket cylinder leaking. Resealed both cylinders. Tested under load.", type: "repair", status: "completed", serviceDate: new Date("2025-11-28"), mileage: 1700, techName: "Chris Taylor", shopName: "Egeland Auto",
  415. partItems: [{ name: "Bucket Cylinder Seal Kit (pair)", partNumber: "CASE-BCSK-621G", quantity: 1, unitPrice: 380, total: 380 }, { name: "Hydraulic Oil (5gal)", partNumber: "HYD-ISO46-5G", quantity: 2, unitPrice: 95, total: 190 }],
  416. laborItems: [{ description: "Cylinder removal and disassembly", hours: 3.0, rate: 140, total: 420 }, { description: "Reseal and reassembly", hours: 2.5, rate: 140, total: 350 }, { description: "System bleed and pressure test", hours: 1.5, rate: 140, total: 210 }],
  417. subtotal: 1550, taxRate: 8, taxAmount: 124, totalAmount: 1674 },
  418. { vehicleId: vehicles[1].id, title: "F-150 Transmission Fluid Flush", description: "Customer reported rough shifting. Flushed transmission fluid, replaced filter.", type: "repair", status: "completed", serviceDate: new Date("2026-02-01"), mileage: 41500, techName: "Jake Wilson", shopName: "Egeland Auto",
  419. partItems: [{ name: "Mercon ULV ATF (12qt)", partNumber: "FORD-ATF-ULV", quantity: 1, unitPrice: 185, total: 185 }, { name: "Transmission Filter Kit", partNumber: "FORD-TFK-10R80", quantity: 1, unitPrice: 68, total: 68 }],
  420. laborItems: [{ description: "Transmission fluid flush", hours: 2.0, rate: 110, total: 220 }, { description: "Filter and gasket replacement", hours: 1.5, rate: 110, total: 165 }],
  421. subtotal: 638, taxRate: 8, taxAmount: 51.04, totalAmount: 689.04 },
  422. { vehicleId: vehicles[38].id, title: "Corvette C8 - First Annual Service", description: "Annual oil change with performance inspection. Checked brake wear, tire depth, and suspension.", type: "maintenance", status: "completed", serviceDate: new Date("2026-01-22"), mileage: 5800, techName: "Chris Taylor", shopName: "Egeland Auto",
  423. partItems: [{ name: "Mobil 1 0W-40 Full Synthetic (8qt)", partNumber: "CHV-0W40-8Q", quantity: 1, unitPrice: 95, total: 95 }, { name: "Oil Filter (OEM)", partNumber: "CHV-OF-LT2", quantity: 1, unitPrice: 18, total: 18 }, { name: "Cabin Air Filter", partNumber: "CHV-CAF-C8", quantity: 1, unitPrice: 28, total: 28 }],
  424. laborItems: [{ description: "Oil and filter change (dry sump)", hours: 1.0, rate: 130, total: 130 }, { description: "Performance multi-point inspection", hours: 1.0, rate: 130, total: 130 }],
  425. subtotal: 401, taxRate: 8, taxAmount: 32.08, totalAmount: 433.08 },
  426. { vehicleId: vehicles[39].id, title: "Defender 110 - 30K Service + Off-Road Inspection", description: "30K mile service. Oil change, all filters, diff fluids. Extra inspection for off-road wear.", type: "maintenance", status: "completed", serviceDate: new Date("2025-12-10"), mileage: 27000, techName: "Erik Haugen", shopName: "Egeland Auto",
  427. partItems: [{ name: "Engine Oil 0W-20 (7qt)", partNumber: "LR-0W20-7Q", quantity: 1, unitPrice: 78, total: 78 }, { name: "Oil Filter", partNumber: "LR-OF-DEF", quantity: 1, unitPrice: 22, total: 22 }, { name: "Air Filter", partNumber: "LR-AF-DEF", quantity: 1, unitPrice: 45, total: 45 }, { name: "Front Diff Fluid (2qt)", partNumber: "LR-FDF-2Q", quantity: 1, unitPrice: 42, total: 42 }, { name: "Rear Diff Fluid (2.5qt)", partNumber: "LR-RDF-25Q", quantity: 1, unitPrice: 48, total: 48 }],
  428. laborItems: [{ description: "Oil and filter change", hours: 0.5, rate: 110, total: 55 }, { description: "Air filter replacement", hours: 0.3, rate: 110, total: 33 }, { description: "Front and rear differential fluid change", hours: 1.5, rate: 110, total: 165 }, { description: "Off-road undercarriage inspection", hours: 1.0, rate: 110, total: 110 }],
  429. subtotal: 598, taxRate: 8, taxAmount: 47.84, totalAmount: 645.84 },
  430. { vehicleId: vehicles[40].id, title: "Charger R/T - Brake Rotor Replacement", description: "Front rotors warped from aggressive driving. Replace rotors and pads.", type: "repair", status: "completed", serviceDate: new Date("2026-02-05"), mileage: 33500, techName: "Jake Wilson", shopName: "Egeland Auto",
  431. partItems: [{ name: "Front Brake Rotors (pair)", partNumber: "DOD-BR-CHG-F", quantity: 1, unitPrice: 280, total: 280 }, { name: "Front Brake Pad Set (performance)", partNumber: "DOD-BP-CHG-F", quantity: 1, unitPrice: 145, total: 145 }],
  432. laborItems: [{ description: "Front brake rotor and pad replacement", hours: 2.0, rate: 110, total: 220 }, { description: "Brake system bleed and road test", hours: 0.5, rate: 110, total: 55 }],
  433. subtotal: 700, taxRate: 8, taxAmount: 56, totalAmount: 756 },
  434. { vehicleId: vehicles[41].id, title: "WRX - Turbo Boost Leak Repair", description: "Customer reported loss of power under boost. Found cracked intercooler pipe.", type: "repair", status: "completed", serviceDate: new Date("2026-01-30"), mileage: 11800, techName: "Chris Taylor", shopName: "Egeland Auto",
  435. partItems: [{ name: "Intercooler Pipe + Couplers", partNumber: "SUB-ICP-WRX", quantity: 1, unitPrice: 165, total: 165 }, { name: "T-Bolt Clamps (set of 4)", partNumber: "SUB-TBC-4", quantity: 1, unitPrice: 28, total: 28 }],
  436. laborItems: [{ description: "Boost leak diagnosis and smoke test", hours: 1.0, rate: 120, total: 120 }, { description: "Intercooler pipe replacement", hours: 1.5, rate: 120, total: 180 }],
  437. subtotal: 493, taxRate: 8, taxAmount: 39.44, totalAmount: 532.44 },
  438. ];
  439. const serviceRecords = [];
  440. for (const sr of svcData) {
  441. const { partItems, laborItems, ...data } = sr;
  442. const record = await prisma.serviceRecord.create({ data: { ...data, organizationId: ORG_ID, cost: data.totalAmount, partItems: { create: partItems }, laborItems: { create: laborItems } } });
  443. serviceRecords.push(record);
  444. }
  445. console.log(` Created ${serviceRecords.length} service records`);
  446. // -- Quotes (15) --
  447. console.log("\nCreating quotes...");
  448. const qData = [
  449. { quoteNumber: "Q-2026-001", title: "Full Brake Overhaul - BMW 330i", status: "sent", validUntil: new Date("2026-03-15"), customerId: customers[3].id, vehicleId: vehicles[4].id,
  450. partItems: [{ name: "Front Brake Rotor Set (OEM)", partNumber: "BMW-BR-F34-OEM", quantity: 1, unitPrice: 480, total: 480 }, { name: "Rear Brake Rotor Set (OEM)", partNumber: "BMW-BR-R34-OEM", quantity: 1, unitPrice: 390, total: 390 }, { name: "Front Brake Pad Set (OEM)", partNumber: "BMW-BP-F34-OEM", quantity: 1, unitPrice: 220, total: 220 }],
  451. laborItems: [{ description: "Front brake rotor and pad replacement", hours: 2.5, rate: 110, total: 275 }, { description: "Rear brake rotor replacement", hours: 2.0, rate: 110, total: 220 }],
  452. subtotal: 1585, taxRate: 8, taxAmount: 126.80, totalAmount: 1711.80 },
  453. { quoteNumber: "Q-2026-002", title: "200K Engine Service - Kenworth T680", status: "accepted", validUntil: new Date("2026-03-01"), customerId: customers[2].id, vehicleId: vehicles[17].id,
  454. partItems: [{ name: "PACCAR MX-13 Overhaul Kit", partNumber: "PAC-OHK-MX13", quantity: 1, unitPrice: 850, total: 850 }, { name: "Injector Set (6)", partNumber: "PAC-INJ-MX13-6", quantity: 1, unitPrice: 1420, total: 1420 }],
  455. laborItems: [{ description: "Injector replacement (6 cylinders)", hours: 8.0, rate: 140, total: 1120 }, { description: "Valve adjustment", hours: 4.0, rate: 140, total: 560 }],
  456. subtotal: 3950, taxRate: 8, taxAmount: 316, totalAmount: 4266 },
  457. { quoteNumber: "Q-2026-003", title: "CAT D6 Undercarriage Rebuild", status: "sent", validUntil: new Date("2026-03-30"), customerId: customers[0].id, vehicleId: vehicles[29].id,
  458. partItems: [{ name: "Track Chain Assembly (pair)", partNumber: "CAT-TCA-D6", quantity: 1, unitPrice: 6500, total: 6500 }, { name: "Track Roller Set (14 pcs)", partNumber: "CAT-TR-D6-14", quantity: 1, unitPrice: 4200, total: 4200 }, { name: "Sprocket Set (pair)", partNumber: "CAT-SS-D6", quantity: 1, unitPrice: 1500, total: 1500 }],
  459. laborItems: [{ description: "Complete undercarriage disassembly", hours: 12.0, rate: 140, total: 1680 }, { description: "Component installation", hours: 16.0, rate: 140, total: 2240 }],
  460. subtotal: 16120, taxRate: 8, taxAmount: 1289.60, totalAmount: 17409.60 },
  461. { quoteNumber: "Q-2026-004", title: "John Deere 6R - Front Axle Overhaul", status: "sent", validUntil: new Date("2026-04-15"), customerId: customers[10].id, vehicleId: vehicles[22].id,
  462. partItems: [{ name: "Front Axle Bearing Kit", partNumber: "JD-FABK-6R", quantity: 1, unitPrice: 520, total: 520 }, { name: "CV Joint Assembly (pair)", partNumber: "JD-CVJ-6R", quantity: 1, unitPrice: 850, total: 850 }],
  463. laborItems: [{ description: "Front axle removal", hours: 5.0, rate: 140, total: 700 }, { description: "Bearing and CV replacement", hours: 4.0, rate: 140, total: 560 }],
  464. subtotal: 2630, taxRate: 8, taxAmount: 210.40, totalAmount: 2840.40 },
  465. { quoteNumber: "Q-2026-005", title: "Honda Civic - Clutch Replacement", status: "accepted", validUntil: new Date("2026-03-10"), customerId: customers[9].id, vehicleId: vehicles[5].id,
  466. partItems: [{ name: "Clutch Kit (disc, plate, bearing)", partNumber: "HON-CLK-FK7", quantity: 1, unitPrice: 380, total: 380 }],
  467. laborItems: [{ description: "Transmission removal and clutch replacement", hours: 5.0, rate: 110, total: 550 }, { description: "Reinstallation and test drive", hours: 2.0, rate: 110, total: 220 }],
  468. subtotal: 1150, taxRate: 8, taxAmount: 92, totalAmount: 1242 },
  469. { quoteNumber: "Q-2026-006", title: "Volvo FH 640 - Air Suspension Repair", status: "accepted", validUntil: new Date("2026-03-10"), customerId: customers[2].id, vehicleId: vehicles[18].id,
  470. partItems: [{ name: "Rear Air Spring (pair)", partNumber: "VOL-RAS-FH", quantity: 1, unitPrice: 560, total: 560 }, { name: "Height Sensor", partNumber: "VOL-HS-FH", quantity: 1, unitPrice: 240, total: 240 }],
  471. laborItems: [{ description: "Air bag replacement (both sides)", hours: 3.0, rate: 140, total: 420 }, { description: "Sensor replacement and calibration", hours: 1.5, rate: 140, total: 210 }],
  472. subtotal: 1430, taxRate: 8, taxAmount: 114.40, totalAmount: 1544.40 },
  473. { quoteNumber: "Q-2026-007", title: "Fendt 942 - A/C Compressor Repair", status: "draft", validUntil: new Date("2026-04-10"), customerId: customers[18].id, vehicleId: vehicles[23].id,
  474. partItems: [{ name: "A/C Compressor - Fendt 942", partNumber: "FENDT-ACC-942", quantity: 1, unitPrice: 890, total: 890 }, { name: "Condenser Assembly", partNumber: "FENDT-COND-942", quantity: 1, unitPrice: 450, total: 450 }],
  475. laborItems: [{ description: "Cab disassembly for A/C access", hours: 3.0, rate: 150, total: 450 }, { description: "Compressor and condenser replacement", hours: 4.0, rate: 150, total: 600 }],
  476. subtotal: 2390, taxRate: 8, taxAmount: 191.20, totalAmount: 2581.20 },
  477. { quoteNumber: "Q-2026-008", title: "Komatsu PC210 - Boom Cylinder Reseal", status: "sent", validUntil: new Date("2026-03-25"), customerId: customers[8].id, vehicleId: vehicles[31].id,
  478. partItems: [{ name: "Boom Cylinder Seal Kit (pair)", partNumber: "KOM-BCSK-PC210", quantity: 1, unitPrice: 520, total: 520 }, { name: "Hydraulic Oil (10gal)", partNumber: "HYD-ISO46-10G", quantity: 1, unitPrice: 180, total: 180 }],
  479. laborItems: [{ description: "Boom cylinder removal", hours: 4.0, rate: 140, total: 560 }, { description: "Disassembly and reseal", hours: 3.0, rate: 140, total: 420 }],
  480. subtotal: 1680, taxRate: 8, taxAmount: 134.40, totalAmount: 1814.40 },
  481. { quoteNumber: "Q-2026-009", title: "Liebherr Crane - Annual Certification", status: "sent", validUntil: new Date("2026-05-01"), customerId: customers[14].id, vehicleId: vehicles[36].id,
  482. partItems: [{ name: "Wire Rope Inspection Kit", partNumber: "LBH-WRIK", quantity: 1, unitPrice: 250, total: 250 }, { name: "Hydraulic Hose Set (safety critical)", partNumber: "LBH-HHS-SC", quantity: 1, unitPrice: 850, total: 850 }],
  483. laborItems: [{ description: "Full crane inspection per OSHA", hours: 8.0, rate: 160, total: 1280 }, { description: "Hydraulic hose replacement", hours: 4.0, rate: 160, total: 640 }, { description: "Load test and certification", hours: 4.0, rate: 160, total: 640 }],
  484. subtotal: 3660, taxRate: 8, taxAmount: 292.80, totalAmount: 3952.80 },
  485. { quoteNumber: "Q-2026-010", title: "Porsche 911 - Suspension Refresh", status: "draft", validUntil: new Date("2026-04-01"), customerId: customers[3].id, vehicleId: vehicles[13].id,
  486. partItems: [{ name: "Bilstein B8 Dampers (set of 4)", partNumber: "POR-BIL-B8-4", quantity: 1, unitPrice: 1800, total: 1800 }, { name: "H&R Sport Springs", partNumber: "POR-HR-SS-992", quantity: 1, unitPrice: 650, total: 650 }],
  487. laborItems: [{ description: "Suspension removal and install", hours: 5.0, rate: 145, total: 725 }, { description: "4-corner alignment", hours: 1.5, rate: 145, total: 217.50 }],
  488. subtotal: 3392.50, taxRate: 8, taxAmount: 271.40, totalAmount: 3663.90 },
  489. { quoteNumber: "Q-2026-011", title: "Jeep Wrangler - Winch Install", status: "accepted", validUntil: new Date("2026-03-20"), customerId: customers[11].id, vehicleId: vehicles[11].id,
  490. partItems: [{ name: "Warn VR EVO 10-S Winch", partNumber: "WARN-VR10S", quantity: 1, unitPrice: 850, total: 850 }, { name: "Winch Mounting Plate", partNumber: "JEEP-WMP-JL", quantity: 1, unitPrice: 220, total: 220 }],
  491. laborItems: [{ description: "Winch and plate installation", hours: 3.0, rate: 110, total: 330 }, { description: "Wiring and relay setup", hours: 1.5, rate: 110, total: 165 }],
  492. subtotal: 1565, taxRate: 8, taxAmount: 125.20, totalAmount: 1690.20 },
  493. { quoteNumber: "Q-2026-012", title: "Fleet Oil Change Package - 10 Trucks", status: "sent", validUntil: new Date("2026-03-15"), customerId: customers[16].id, notes: "Bulk fleet pricing. Drop off in batches of 3-4.",
  494. partItems: [{ name: "Synthetic Oil 5W-30 (5qt) x10", partNumber: "OIL-5W30-BULK", quantity: 10, unitPrice: 38, total: 380 }, { name: "Oil Filter Assorted x10", partNumber: "OF-ASSORTED-10", quantity: 10, unitPrice: 9.50, total: 95 }],
  495. laborItems: [{ description: "Oil change service x10 vehicles", hours: 5.0, rate: 85, total: 425 }],
  496. subtotal: 900, taxRate: 8, taxAmount: 72, totalAmount: 972 },
  497. { quoteNumber: "Q-2026-013", title: "S780 Combine - Pre-Season Check", status: "accepted", validUntil: new Date("2026-04-15"), customerId: customers[18].id, vehicleId: vehicles[27].id,
  498. partItems: [{ name: "Combine Service Kit (all filters)", partNumber: "JD-CSK-S780", quantity: 1, unitPrice: 420, total: 420 }, { name: "Sickle Blade Set", partNumber: "JD-SBS-S780", quantity: 1, unitPrice: 380, total: 380 }, { name: "Feeder Chain", partNumber: "JD-FC-S780", quantity: 1, unitPrice: 650, total: 650 }],
  499. laborItems: [{ description: "Full filter service and oil change", hours: 3.0, rate: 140, total: 420 }, { description: "Sickle replacement and header setup", hours: 4.0, rate: 140, total: 560 }, { description: "Feeder chain replacement", hours: 3.0, rate: 140, total: 420 }],
  500. subtotal: 2850, taxRate: 8, taxAmount: 228, totalAmount: 3078 },
  501. { quoteNumber: "Q-2026-015", title: "Toyota Tacoma - Suspension Upgrade", status: "sent", validUntil: new Date("2026-04-01"), customerId: customers[19].id, vehicleId: vehicles[16].id,
  502. partItems: [{ name: "Bilstein 5100 Front (pair)", partNumber: "BIL-5100-TAC-F", quantity: 1, unitPrice: 340, total: 340 }, { name: "Bilstein 5100 Rear (pair)", partNumber: "BIL-5100-TAC-R", quantity: 1, unitPrice: 280, total: 280 }, { name: "OME Leaf Springs", partNumber: "OME-LS-TAC", quantity: 1, unitPrice: 450, total: 450 }],
  503. laborItems: [{ description: "Front strut replacement", hours: 2.5, rate: 110, total: 275 }, { description: "Rear shock and leaf spring install", hours: 3.0, rate: 110, total: 330 }, { description: "Alignment", hours: 1.0, rate: 110, total: 110 }],
  504. subtotal: 1785, taxRate: 8, taxAmount: 142.80, totalAmount: 1927.80 },
  505. ];
  506. const quotes = [];
  507. for (const q of qData) {
  508. const { partItems, laborItems, customerId, vehicleId, ...fields } = q;
  509. const quote = await prisma.quote.create({ data: { ...fields, userId: USER_ID, organizationId: ORG_ID, ...(customerId ? { customerId } : {}), ...(vehicleId ? { vehicleId } : {}), partItems: { create: partItems }, laborItems: { create: laborItems } } });
  510. quotes.push(quote);
  511. }
  512. console.log(` Created ${quotes.length} quotes`);
  513. // -- Inventory Parts (25) --
  514. console.log("\nCreating inventory parts...");
  515. const invData = [
  516. { name: "Synthetic Engine Oil 5W-30 (5qt)", partNumber: "OIL-5W30-5Q", category: "Fluids & Lubricants", quantity: 24, minQuantity: 10, unitCost: 28, sellPrice: 45, supplier: "AutoZone Commercial", location: "Shelf A-1" },
  517. { name: "Synthetic Engine Oil 0W-20 (5qt)", partNumber: "OIL-0W20-5Q", category: "Fluids & Lubricants", quantity: 18, minQuantity: 8, unitCost: 31, sellPrice: 49, supplier: "AutoZone Commercial", location: "Shelf A-1" },
  518. { name: "Heavy Duty Engine Oil 15W-40 (5gal)", partNumber: "OIL-15W40-5G", category: "Fluids & Lubricants", quantity: 8, minQuantity: 4, unitCost: 120, sellPrice: 185, supplier: "Shell Fleet", location: "Shelf A-2" },
  519. { name: "Hydraulic Oil ISO 46 (55gal)", partNumber: "HYD-ISO46-55G", category: "Fluids & Lubricants", quantity: 3, minQuantity: 2, unitCost: 580, sellPrice: 850, supplier: "Shell Fleet", location: "Floor A-3" },
  520. { name: "Brake Pad Set - Universal Light Vehicle", partNumber: "BP-UNI-LV", category: "Brakes", quantity: 14, minQuantity: 6, unitCost: 38, sellPrice: 68, supplier: "NAPA Auto Parts", location: "Shelf B-1" },
  521. { name: "Brake Pad Set - Heavy Duty Truck", partNumber: "BP-HD-TRUCK", category: "Brakes", quantity: 6, minQuantity: 4, unitCost: 180, sellPrice: 320, supplier: "FleetPride", location: "Shelf B-2" },
  522. { name: "Oil Filter - European Vehicles", partNumber: "OF-EUR-01", category: "Filters", quantity: 30, minQuantity: 10, unitCost: 6.50, sellPrice: 15.50, supplier: "Mann-Filter USA", location: "Shelf C-1" },
  523. { name: "Oil Filter - Asian Vehicles", partNumber: "OF-ASN-01", category: "Filters", quantity: 25, minQuantity: 10, unitCost: 4.50, sellPrice: 12, supplier: "Mann-Filter USA", location: "Shelf C-1" },
  524. { name: "Hydraulic Filter - CAT/Komatsu", partNumber: "HF-CAT-KOM", category: "Filters", quantity: 5, minQuantity: 3, unitCost: 65, sellPrice: 120, supplier: "Cat Parts Direct", location: "Shelf C-3" },
  525. { name: "Spark Plug - Iridium (each)", partNumber: "SP-IRID-01", category: "Ignition", quantity: 40, minQuantity: 16, unitCost: 9.50, sellPrice: 17.50, supplier: "NGK USA", location: "Shelf D-1" },
  526. { name: "Car Battery 12V 700CCA", partNumber: "BAT-12V-700CCA", category: "Electrical", quantity: 6, minQuantity: 3, unitCost: 95, sellPrice: 165, supplier: "Interstate Batteries", location: "Floor D-2" },
  527. { name: "Truck Battery 12V 1000CCA", partNumber: "BAT-12V-1000CCA", category: "Electrical", quantity: 4, minQuantity: 2, unitCost: 240, sellPrice: 380, supplier: "Interstate Batteries", location: "Floor D-2" },
  528. { name: "Coolant Concentrate (1gal)", partNumber: "COOL-CONC-1G", category: "Fluids & Lubricants", quantity: 15, minQuantity: 6, unitCost: 18, sellPrice: 32, supplier: "AutoZone Commercial", location: "Shelf A-2" },
  529. { name: "ATF Transmission Fluid (1qt)", partNumber: "ATF-DEXVI-1Q", category: "Fluids & Lubricants", quantity: 20, minQuantity: 8, unitCost: 12, sellPrice: 22, supplier: "AutoZone Commercial", location: "Shelf A-2" },
  530. { name: "Serpentine Belt - Universal", partNumber: "SB-UNI-6PK", category: "Engine", quantity: 8, minQuantity: 4, unitCost: 22, sellPrice: 42, supplier: "Gates Corp", location: "Shelf D-3" },
  531. { name: "Hydraulic Hose - 1/2\" x 10ft", partNumber: "HH-12-10FT", category: "Hydraulics", quantity: 10, minQuantity: 4, unitCost: 45, sellPrice: 85, supplier: "Parker Hannifin", location: "Rack G-1" },
  532. { name: "Track Shoe Bolt Kit (set of 50)", partNumber: "TSB-KIT-50", category: "Undercarriage", quantity: 4, minQuantity: 2, unitCost: 180, sellPrice: 320, supplier: "Cat Parts Direct", location: "Floor G-2" },
  533. { name: "R-134a Refrigerant (30oz can)", partNumber: "R134A-30OZ", category: "HVAC", quantity: 8, minQuantity: 4, unitCost: 18, sellPrice: 32, supplier: "AutoZone Commercial", location: "Shelf H-1" },
  534. { name: "Fuel Filter - Diesel Universal", partNumber: "FF-DSL-UNI", category: "Filters", quantity: 12, minQuantity: 5, unitCost: 14, sellPrice: 29, supplier: "Mann-Filter USA", location: "Shelf C-2" },
  535. { name: "Air Filter - Heavy Equipment", partNumber: "AF-HE-UNI", category: "Filters", quantity: 6, minQuantity: 3, unitCost: 48, sellPrice: 85, supplier: "Cat Parts Direct", location: "Shelf C-3" },
  536. { name: "Tractor PTO Shaft Guard", partNumber: "PTO-SG-UNI", category: "Safety", quantity: 3, minQuantity: 2, unitCost: 85, sellPrice: 150, supplier: "Agri Supply Co.", location: "Rack G-3" },
  537. { name: "DPF Pressure Sensor", partNumber: "DPF-PS-UNI", category: "Emissions", quantity: 1, minQuantity: 3, unitCost: 65, sellPrice: 120, supplier: "Bosch USA", location: "Shelf D-5" },
  538. { name: "Grease Cartridge EP2 (box of 10)", partNumber: "GREASE-EP2-10", category: "Fluids & Lubricants", quantity: 12, minQuantity: 5, unitCost: 28, sellPrice: 48, supplier: "Shell Fleet", location: "Shelf A-3" },
  539. { name: "Combine Sickle Section (box of 25)", partNumber: "CSS-UNI-25", category: "Harvest Parts", quantity: 4, minQuantity: 2, unitCost: 65, sellPrice: 110, supplier: "Agri Supply Co.", location: "Rack G-4" },
  540. { name: "Wiper Blade 24\" Universal", partNumber: "WB-24-UNI", category: "Body & Exterior", quantity: 12, minQuantity: 6, unitCost: 11, sellPrice: 25, supplier: "Bosch USA", location: "Shelf E-1" },
  541. ];
  542. const inventoryParts = await Promise.all(invData.map(p => prisma.inventoryPart.create({ data: { ...p, userId: USER_ID, organizationId: ORG_ID } })));
  543. console.log(` Created ${inventoryParts.length} inventory parts`);
  544. // -- Fuel Logs --
  545. console.log("\nCreating fuel logs...");
  546. await Promise.all([
  547. prisma.fuelLog.create({ data: { vehicleId: vehicles[1].id, date: new Date("2026-01-05"), mileage: 40200, gallons: 26, pricePerGallon: 3.45, totalCost: 89.70, station: "Shell - I-25 & Hampden" } }),
  548. prisma.fuelLog.create({ data: { vehicleId: vehicles[1].id, date: new Date("2026-02-02"), mileage: 41500, gallons: 24, pricePerGallon: 3.48, totalCost: 83.52, station: "Costco Gas - Arvada" } }),
  549. prisma.fuelLog.create({ data: { vehicleId: vehicles[17].id, date: new Date("2026-01-10"), mileage: 182000, gallons: 120, pricePerGallon: 3.85, totalCost: 462.00, station: "Pilot Travel Center - Portland" } }),
  550. prisma.fuelLog.create({ data: { vehicleId: vehicles[8].id, date: new Date("2026-02-10"), mileage: 98000, gallons: 28, pricePerGallon: 3.65, totalCost: 102.20, station: "Buc-ee's - San Antonio" } }),
  551. prisma.fuelLog.create({ data: { vehicleId: vehicles[22].id, date: new Date("2026-02-15"), mileage: 2700, gallons: 35, pricePerGallon: 3.78, totalCost: 132.30, station: "Co-op Fuel - Omaha" } }),
  552. prisma.fuelLog.create({ data: { vehicleId: vehicles[23].id, date: new Date("2026-01-28"), mileage: 1180, gallons: 80, pricePerGallon: 3.82, totalCost: 305.60, station: "Farm Bureau Fuel - Des Moines" } }),
  553. prisma.fuelLog.create({ data: { vehicleId: vehicles[15].id, date: new Date("2026-02-20"), mileage: 19500, gallons: 22, pricePerGallon: 3.55, totalCost: 78.10, station: "Speedway - Detroit" } }),
  554. prisma.fuelLog.create({ data: { vehicleId: vehicles[11].id, date: new Date("2026-01-22"), mileage: 28200, gallons: 18, pricePerGallon: 3.62, totalCost: 65.16, station: "Shell - I-70 & Morrison" } }),
  555. ]);
  556. console.log(" Created 8 fuel logs");
  557. // -- Reminders --
  558. console.log("\nCreating reminders...");
  559. await Promise.all([
  560. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[0].id, title: "Next Oil Change", description: "Due at 25,000 mi or March 2026", dueDate: new Date("2026-03-15"), dueMileage: 25000 } }),
  561. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[4].id, title: "Brake Fluid Flush", description: "BMW recommends every 2 years", dueDate: new Date("2026-06-01") } }),
  562. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[17].id, title: "Annual DOT Inspection", description: "Kenworth T680 - annual inspection", dueDate: new Date("2026-02-28") } }),
  563. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[29].id, title: "Track Tension Check", description: "CAT D6 - check after 100 hours", dueMileage: 4500 } }),
  564. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[22].id, title: "1000hr Service", description: "John Deere 6R 250 - scheduled service", dueMileage: 3500 } }),
  565. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[23].id, title: "Spring Planting Prep", description: "Fendt 942 - full check before spring", dueDate: new Date("2026-04-01") } }),
  566. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[18].id, title: "Volvo FH 640 - Brake Inspection", description: "Check brakes before next long-haul", dueDate: new Date("2026-03-10") } }),
  567. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[13].id, title: "Porsche 911 - Track Day Prep", description: "Brake pads, fluid, tire pressure check before April track day", dueDate: new Date("2026-04-10") } }),
  568. ]);
  569. console.log(" Created 8 reminders");
  570. // -- Vehicle Notes --
  571. console.log("\nCreating vehicle notes...");
  572. await Promise.all([
  573. prisma.note.create({ data: { vehicleId: vehicles[4].id, title: "Customer preference", content: "Sarah always requests OEM BMW parts. No aftermarket. She prefers to wait while service is done.", isPinned: true } }),
  574. prisma.note.create({ data: { vehicleId: vehicles[29].id, title: "Hydraulic leak history", content: "This D6 has had recurring hydraulic leaks on the left blade cylinder. Last repaired Sept 2025. Monitor closely.", isPinned: true } }),
  575. prisma.note.create({ data: { vehicleId: vehicles[17].id, title: "Fleet note", content: "Pacific Freight unit #3. Driver: Tom Bradley. Call dispatch at (555) 302-5566 for scheduling.", isPinned: false } }),
  576. prisma.note.create({ data: { vehicleId: vehicles[6].id, title: "Charging note", content: "Customer reports occasional slow charging at home. Suggested checking home charger firmware. Not a vehicle issue.", isPinned: false } }),
  577. prisma.note.create({ data: { vehicleId: vehicles[36].id, title: "Outrigger issue", content: "Right rear outrigger cylinder slow to extend. May need seal replacement at next service.", isPinned: true } }),
  578. prisma.note.create({ data: { vehicleId: vehicles[22].id, title: "Warranty info", content: "John Deere 6R 250 still under manufacturer warranty until March 2027. Contact JD dealer for warranty claims.", isPinned: true } }),
  579. prisma.note.create({ data: { vehicleId: vehicles[23].id, title: "Operator preference", content: "Fendt 942 - Operator prefers front linkage set to position control, not draft. Do not change settings after service.", isPinned: true } }),
  580. prisma.note.create({ data: { vehicleId: vehicles[18].id, title: "Volvo FH 640 fleet note", content: "Pacific Freight unit #5. Long-haul Portland to Chicago route. D13TC engine with I-Shift dual clutch.", isPinned: true } }),
  581. prisma.note.create({ data: { vehicleId: vehicles[11].id, title: "Lift kit installed", content: "2.5\" Mopar lift with Bilstein 5100 shocks installed Feb 2026. Customer plans to add 35\" tires next.", isPinned: false } }),
  582. ]);
  583. console.log(" Created 9 vehicle notes");
  584. // -- Additional vehicle notes (customer preferences, reminders, history) --
  585. console.log("\nCreating additional vehicle notes...");
  586. const additionalNotes = await Promise.all([
  587. prisma.note.create({ data: { vehicleId: vehicles[0].id, title: "Customer preference", content: "James prefers Mobil 1 full synthetic 0W-20 on every oil change. Do not substitute.", isPinned: true } }),
  588. prisma.note.create({ data: { vehicleId: vehicles[0].id, title: "Key location", content: "Spare key in lockbox #4 (code 4412). Customer drops off after hours sometimes.", isPinned: false } }),
  589. prisma.note.create({ data: { vehicleId: vehicles[1].id, title: "Fleet maintenance policy", content: "Summit Construction requires photo documentation of all brake and tire work. Upload to service record.", isPinned: true } }),
  590. prisma.note.create({ data: { vehicleId: vehicles[1].id, title: "Aftermarket bed liner", content: "Spray-in bed liner installed 2023. Don't pressure wash interior of bed at close range.", isPinned: false } }),
  591. prisma.note.create({ data: { vehicleId: vehicles[2].id, title: "Off-road use", content: "Mike uses this for hunting trips. Undercarriage gets a lot of mud - always inspect skid plates.", isPinned: false } }),
  592. prisma.note.create({ data: { vehicleId: vehicles[3].id, title: "Municipal contract vehicle", content: "Metro City Services - invoicing via purchase order only. PO required before work starts.", isPinned: true } }),
  593. prisma.note.create({ data: { vehicleId: vehicles[5].id, title: "Budget-conscious customer", content: "Amanda prefers aftermarket parts where safe. Always provide OEM vs aftermarket pricing options.", isPinned: true } }),
  594. prisma.note.create({ data: { vehicleId: vehicles[5].id, title: "Check AC vents", content: "Musty smell reported last visit. Recommended cabin filter + evaporator clean at next service.", isPinned: false } }),
  595. prisma.note.create({ data: { vehicleId: vehicles[7].id, title: "Referral source", content: "Jessica was referred by Ryan Parker. Offer referral discount on next service.", isPinned: false } }),
  596. prisma.note.create({ data: { vehicleId: vehicles[8].id, title: "Ranch use", content: "Silverado used for cattle hauling. Check hitch and trailer plug every visit.", isPinned: false } }),
  597. prisma.note.create({ data: { vehicleId: vehicles[9].id, title: "Commercial use", content: "Kevin uses this daily for catering. Needs quick turnaround - try to get him in/out same day.", isPinned: true } }),
  598. prisma.note.create({ data: { vehicleId: vehicles[10].id, title: "OEM parts only", content: "David insists on genuine Audi parts. No VAG knockoffs. He'll ask to see part numbers.", isPinned: true } }),
  599. prisma.note.create({ data: { vehicleId: vehicles[12].id, title: "Soft top care", content: "Customer has both hard and soft top. Store removed top carefully, document any scratches.", isPinned: false } }),
  600. prisma.note.create({ data: { vehicleId: vehicles[14].id, title: "Manual transmission", content: "David is the primary driver. Wife drives occasionally but doesn't like manual - clutch wear expected.", isPinned: false } }),
  601. prisma.note.create({ data: { vehicleId: vehicles[15].id, title: "Weekend vehicle", content: "Robert uses this mainly weekends for towing his boat. Look at trailer brakes in spring.", isPinned: false } }),
  602. prisma.note.create({ data: { vehicleId: vehicles[16].id, title: "TRD package notes", content: "TRD Off-Road suspension - use correct alignment specs (different from base Tacoma).", isPinned: true } }),
  603. prisma.note.create({ data: { vehicleId: vehicles[19].id, title: "Dump body maintenance", content: "Body floor develops cracks at 150k+ mi. Inspect weld seams during every service.", isPinned: false } }),
  604. prisma.note.create({ data: { vehicleId: vehicles[20].id, title: "Concrete mixer drum", content: "Drum drive motor is a known weak point on this unit. Monitor for sluggish rotation.", isPinned: true } }),
  605. prisma.note.create({ data: { vehicleId: vehicles[24].id, title: "Seasonal use", content: "Massey Ferguson is the backup tractor for Prairie Farms. Heavy use spring/fall only.", isPinned: false } }),
  606. prisma.note.create({ data: { vehicleId: vehicles[25].id, title: "Warranty active", content: "John Deere 8R 410 still under warranty until Jan 2027. Contact JD dealer for anything covered.", isPinned: true } }),
  607. prisma.note.create({ data: { vehicleId: vehicles[27].id, title: "Harvest critical", content: "S780 combine is CRITICAL for fall harvest. Any work needs to be done before September.", isPinned: true } }),
  608. prisma.note.create({ data: { vehicleId: vehicles[30].id, title: "D8T parts lead time", content: "CAT D8T parts often take 2-3 weeks. Order ahead. Titan Building will wait if told up front.", isPinned: false } }),
  609. prisma.note.create({ data: { vehicleId: vehicles[32].id, title: "Undercarriage wear", content: "Track chains due for replacement around 2000hr. Currently at 1800hr — budget planning.", isPinned: false } }),
  610. prisma.note.create({ data: { vehicleId: vehicles[35].id, title: "Metro City asset tag", content: "City asset tag #WL-014. Include in all invoices for their records.", isPinned: false } }),
  611. prisma.note.create({ data: { vehicleId: vehicles[37].id, title: "Indoor use only", content: "Electric forklift used indoors at Ironclad warehouse. Tire compound is non-marking.", isPinned: false } }),
  612. prisma.note.create({ data: { vehicleId: vehicles[38].id, title: "Track car", content: "Sarah takes this to HPDE track days 3-4 times a year. Always check brake pads and fluid before/after.", isPinned: true } }),
  613. prisma.note.create({ data: { vehicleId: vehicles[38].id, title: "Dry sump oil system", content: "C8 Corvette has a dry sump system. Takes 8 quarts of 0W-40. Use GM-approved Mobil 1 only.", isPinned: false } }),
  614. prisma.note.create({ data: { vehicleId: vehicles[39].id, title: "Heavy off-road use", content: "Mike takes this on trails every weekend. Always inspect skid plates, check for rock damage underneath.", isPinned: true } }),
  615. prisma.note.create({ data: { vehicleId: vehicles[40].id, title: "Mopar parts preference", content: "Robert wants Mopar or performance-equivalent parts. No economy parts on this car.", isPinned: true } }),
  616. prisma.note.create({ data: { vehicleId: vehicles[41].id, title: "Modified intake", content: "Customer installed aftermarket cold air intake. Note: may trigger P0171 lean code - not a fault. Recheck with stock intake if persistent.", isPinned: true } }),
  617. prisma.note.create({ data: { vehicleId: vehicles[41].id, title: "Catback exhaust", content: "Invidia Q300 catback exhaust installed by customer. Stock exhaust stored at his garage.", isPinned: false } }),
  618. ]);
  619. console.log(` Created ${additionalNotes.length} additional vehicle notes`);
  620. // -- Additional reminders --
  621. console.log("\nCreating additional reminders...");
  622. const additionalReminders = await Promise.all([
  623. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[1].id, title: "Timing belt replacement", description: "Interval-based - EcoBoost timing chain inspection due", dueMileage: 60000 } }),
  624. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[2].id, title: "Annual inspection", description: "Minnesota state safety inspection", dueDate: new Date("2026-05-15") } }),
  625. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[5].id, title: "Brake fluid flush", description: "Honda recommends every 3 years", dueMileage: 72000, dueDate: new Date("2026-06-01") } }),
  626. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[8].id, title: "Registration renewal", description: "Texas registration expires June 2026", dueDate: new Date("2026-06-30") } }),
  627. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[9].id, title: "Next oil change", description: "Sprinter service B interval", dueMileage: 40000 } }),
  628. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[10].id, title: "Haldex service", description: "Quattro rear diff fluid change - 40K interval", dueMileage: 40000, isCompleted: true } }),
  629. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[11].id, title: "Front diff fluid", description: "After lift kit, recommend fluid change at 35K", dueMileage: 35000 } }),
  630. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[12].id, title: "Annual inspection", description: "Georgia annual safety inspection", dueDate: new Date("2026-08-22") } }),
  631. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[14].id, title: "DSG service interval", description: "Next DSG fluid/filter at 78K", dueMileage: 78000 } }),
  632. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[17].id, title: "CVT fluid check", description: "Subaru CVT recommended drain/fill", dueMileage: 30000 } }),
  633. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[20].id, title: "Mixer drum inspection", description: "Annual drum wear/bolt check", dueDate: new Date("2026-07-01") } }),
  634. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[25].id, title: "250hr service", description: "John Deere 8R scheduled interval", dueMileage: 1000 } }),
  635. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[28].id, title: "Pre-harvest prep", description: "X9 1100 combine full inspection before harvest", dueDate: new Date("2026-08-15") } }),
  636. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[30].id, title: "Blade edge replacement", description: "Check wear on cutting edge", dueMileage: 6500, isCompleted: true } }),
  637. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[32].id, title: "Undercarriage inspection", description: "2000hr interval for track chain inspection", dueMileage: 2000 } }),
  638. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[36].id, title: "OSHA crane certification", description: "Annual load test and certification due", dueDate: new Date("2026-05-01") } }),
  639. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[38].id, title: "Corvette annual service", description: "GM recommended annual service with performance inspection", dueDate: new Date("2027-01-22") } }),
  640. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[39].id, title: "Transfer case fluid", description: "Land Rover recommends 40K interval for transfer case fluid", dueMileage: 40000 } }),
  641. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[40].id, title: "Transmission fluid change", description: "8-speed auto - ZF recommends fluid change at 50K", dueMileage: 50000 } }),
  642. prisma.reminder.create({ data: { organizationId: ORG_ID, vehicleId: vehicles[41].id, title: "Timing belt inspection", description: "FA24 engine - inspect timing chain tensioner at 60K", dueMileage: 60000 } }),
  643. ]);
  644. console.log(` Created ${additionalReminders.length} additional reminders`);
  645. // -- Vehicle Findings (observations from service) --
  646. console.log("\nCreating vehicle findings...");
  647. const findings = await Promise.all([
  648. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[4].id, description: "Front brake pads at 3mm, recommend replacement within 5,000 miles", severity: "needs_work", status: "open", serviceRecordId: serviceRecords[1].id, notes: "Customer informed during 50K service. Quoted separately.", imageUrls: [] } }),
  649. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[5].id, description: "CV boot torn on driver side, grease leaking onto suspension components", severity: "urgent", status: "open", notes: "Needs attention soon - will fail CV joint if not addressed.", imageUrls: [] } }),
  650. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[1].id, description: "Slight oil seepage from valve cover gasket, monitor at next service", severity: "monitor", status: "open", serviceRecordId: serviceRecords[18].id, notes: "Not dripping yet - just damp. Re-check in 6 months.", imageUrls: [] } }),
  651. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[8].id, description: "Battery testing at 78% capacity, recommend replacement before winter", severity: "monitor", status: "open", notes: "Still starts reliably. Load test shows degraded CCA.", imageUrls: [] } }),
  652. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[2].id, description: "Tire tread below 4/32 on front tires, will need replacement soon", severity: "needs_work", status: "open", notes: "Rears still have 6/32. Recommend rotating and planning fronts soon.", imageUrls: [] } }),
  653. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[9].id, description: "Coolant appears contaminated with oil traces, consider flush and inspection", severity: "needs_work", status: "open", serviceRecordId: serviceRecords[13].id, notes: "Found during turbo job. May be related to oil cooler seal.", imageUrls: [] } }),
  654. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[11].id, description: "Death wobble symptoms reported - track bar bushings worn", severity: "urgent", status: "resolved", notes: "Customer reported highway death wobble. Replaced steering stabilizer and tie rods.", imageUrls: [] } }),
  655. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[13].id, description: "Rear tire wear uneven - alignment suspected after track use", severity: "needs_work", status: "open", serviceRecordId: serviceRecords[3].id, notes: "Right rear shows inner edge wear consistent with toe-out.", imageUrls: [] } }),
  656. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[17].id, description: "DEF tank heater intermittent - low DEF temperature warning in cold weather", severity: "monitor", status: "open", serviceRecordId: serviceRecords[4].id, notes: "Only acts up below 20F. Monitor and replace if it fails completely.", imageUrls: [] } }),
  657. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[18].id, description: "Charge air cooler pipe cracked, boost leak confirmed", severity: "urgent", status: "open", notes: "Part ordered. Causing low-power complaint from driver.", imageUrls: [] } }),
  658. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[19].id, description: "Dump body floor showing stress cracks near rear hinge", severity: "needs_work", status: "open", notes: "Will need weld repair within 10,000 miles to avoid structural failure.", imageUrls: [] } }),
  659. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[22].id, description: "Front loader pins showing excessive play, bushings worn", severity: "needs_work", status: "open", notes: "Noticeable play when boom is fully extended. Replace at next service.", imageUrls: [] } }),
  660. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[23].id, description: "A/C condenser fins damaged, reduced cooling efficiency", severity: "monitor", status: "open", notes: "Fins bent from field debris. Combing/straightening recommended.", imageUrls: [] } }),
  661. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[29].id, description: "Left blade cylinder showing slow seepage at rod seal", severity: "monitor", status: "resolved", serviceRecordId: serviceRecords[8].id, resolvedServiceRecordId: serviceRecords[8].id, notes: "Resealed during Sept 2025 hydraulic overhaul.", imageUrls: [] } }),
  662. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[31].id, description: "Boom cylinder showing 2 inch drift over 10 minutes under load", severity: "needs_work", status: "open", notes: "Cylinder reseal scheduled in unassigned work.", imageUrls: [] } }),
  663. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[32].id, description: "Track shoe bolts loosening, retorque recommended", severity: "monitor", status: "open", notes: "Checked 8 of 42 shoes - 3 required retorque. Full inspection next service.", imageUrls: [] } }),
  664. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[36].id, description: "Right rear outrigger extending slower than left", severity: "needs_work", status: "open", notes: "Likely valve or cylinder seal. Scheduled for inspection.", imageUrls: [] } }),
  665. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[24].id, description: "Overheating under heavy PTO load - radiator partially blocked with chaff", severity: "needs_work", status: "open", notes: "Cleaned out what we could. Recommend pull radiator for deep clean.", imageUrls: [] } }),
  666. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[34].id, description: "Hydraulic hose chafing against frame rail near pivot point", severity: "needs_work", status: "open", notes: "Protective sleeve worn through. Will fail if not rerouted.", imageUrls: [] } }),
  667. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[16].id, description: "Leaf spring bushings dry and cracking, suspension noise reported", severity: "needs_work", status: "open", notes: "Customer scheduled for leaf spring replacement.", imageUrls: [] } }),
  668. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[38].id, description: "Rear brake pads showing uneven wear from track use, inner pad thinner than outer", severity: "needs_work", status: "open", notes: "Likely caliper slide pins need cleaning and relubing. Recommend high-performance pads for track use.", imageUrls: [] } }),
  669. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[39].id, description: "Front left CV boot starting to crack, no grease leaking yet", severity: "monitor", status: "open", notes: "Off-road flex likely contributing. Replace before it tears and contaminates the joint.", imageUrls: [] } }),
  670. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[40].id, description: "Rear tires wearing faster on inside edge, alignment needed", severity: "needs_work", status: "open", notes: "Aggressive driving habit. Rear camber may be out of spec after pothole.", imageUrls: [] } }),
  671. prisma.vehicleFinding.create({ data: { vehicleId: vehicles[41].id, description: "Exhaust manifold stud #3 showing early surface corrosion", severity: "monitor", status: "open", notes: "Not leaking yet. Anti-seize on next service. Watch for exhaust tick on cold start.", imageUrls: [] } }),
  672. ]);
  673. console.log(` Created ${findings.length} vehicle findings`);
  674. // -- Repeat service history for predicted maintenance --
  675. // Pick 6 vehicles, give each 3-4 completed service records with increasing mileage
  676. // spanning 2-3 years so the predictedMaintenanceActions has regression data.
  677. console.log("\nCreating repeat service history for predicted maintenance...");
  678. type HistEntry = { offsetDays: number; mileage: number; title: string; desc: string; type: string; techName: string };
  679. const predMaintHistory: { vehicleId: string; entries: HistEntry[] }[] = [
  680. {
  681. vehicleId: vehicles[1].id, // Ford F-150 Lariat white (Summit Construction, current 42300)
  682. entries: [
  683. { offsetDays: -820, mileage: 10500, title: "F-150 - 10K Oil Change", desc: "First service. Synthetic 5W-30, oil filter, tire rotation.", type: "maintenance", techName: "Jake Wilson" },
  684. { offsetDays: -540, mileage: 20200, title: "F-150 - 20K Service", desc: "Oil change, cabin filter, brake inspection, tire rotation.", type: "maintenance", techName: "Jake Wilson" },
  685. { offsetDays: -280, mileage: 30100, title: "F-150 - 30K Major Service", desc: "Full fluid service, spark plugs, transfer case fluid.", type: "maintenance", techName: "Chris Taylor" },
  686. { offsetDays: -90, mileage: 40800, title: "F-150 - 40K Service", desc: "Oil change, brake fluid flush, differential service.", type: "maintenance", techName: "Jake Wilson" },
  687. ],
  688. },
  689. {
  690. vehicleId: vehicles[4].id, // BMW 330i xDrive (Sarah Coleman, current 55200)
  691. entries: [
  692. { offsetDays: -900, mileage: 22000, title: "BMW 330i - 22K Oil Service", desc: "OEM oil, filter, inspection. OEM parts only per customer.", type: "maintenance", techName: "Chris Taylor" },
  693. { offsetDays: -600, mileage: 32500, title: "BMW 330i - 32K Service", desc: "Oil, cabin filter, brake inspection. All OEM BMW parts.", type: "maintenance", techName: "Chris Taylor" },
  694. { offsetDays: -300, mileage: 43800, title: "BMW 330i - 43K Service", desc: "Oil change, tire rotation, 4-wheel alignment.", type: "maintenance", techName: "Chris Taylor" },
  695. ],
  696. },
  697. {
  698. vehicleId: vehicles[5].id, // Honda Civic Sport (Amanda Foster, current 67800)
  699. entries: [
  700. { offsetDays: -960, mileage: 28500, title: "Civic - 28K Oil Change", desc: "Synthetic oil, filter, tire rotation.", type: "maintenance", techName: "Jake Wilson" },
  701. { offsetDays: -680, mileage: 39200, title: "Civic - 39K Service", desc: "Oil change, cabin filter, engine air filter.", type: "maintenance", techName: "Jake Wilson" },
  702. { offsetDays: -360, mileage: 52000, title: "Civic - 52K Major Service", desc: "Oil, coolant flush, transmission fluid, belt inspection.", type: "maintenance", techName: "Sofia Andersen" },
  703. { offsetDays: -110, mileage: 64500, title: "Civic - 64K Service", desc: "Oil change, brake pad inspection, alignment check.", type: "maintenance", techName: "Jake Wilson" },
  704. ],
  705. },
  706. {
  707. vehicleId: vehicles[8].id, // Silverado 2500HD (Lisa Martinez, current 98400)
  708. entries: [
  709. { offsetDays: -850, mileage: 62000, title: "Silverado - 62K Oil Service", desc: "Duramax diesel oil, fuel filters, DEF top-off.", type: "maintenance", techName: "Marcus Reed" },
  710. { offsetDays: -560, mileage: 75500, title: "Silverado - 75K Service", desc: "Oil, fuel filters, DEF fluid, tire rotation.", type: "maintenance", techName: "Marcus Reed" },
  711. { offsetDays: -290, mileage: 87200, title: "Silverado - 87K Major Service", desc: "Oil, coolant flush, transmission service, DPF regen.", type: "maintenance", techName: "Marcus Reed" },
  712. { offsetDays: -60, mileage: 96100, title: "Silverado - 96K Service", desc: "Oil change, fuel filter, brake inspection.", type: "maintenance", techName: "Jake Wilson" },
  713. ],
  714. },
  715. {
  716. vehicleId: vehicles[17].id, // Kenworth T680 (Pacific Freight, current 185000)
  717. entries: [
  718. { offsetDays: -780, mileage: 92000, title: "Kenworth - 92K PM", desc: "Full PM - oil, fuel filters, air filters, inspection.", type: "maintenance", techName: "Marcus Reed" },
  719. { offsetDays: -520, mileage: 118000, title: "Kenworth - 118K PM", desc: "Engine oil, all filters, DEF, grease service.", type: "maintenance", techName: "Marcus Reed" },
  720. { offsetDays: -260, mileage: 148000, title: "Kenworth - 148K PM", desc: "Engine oil, all filters, coolant check, brake adjust.", type: "maintenance", techName: "Marcus Reed" },
  721. ],
  722. },
  723. {
  724. vehicleId: vehicles[16].id, // Tacoma TRD Off-Road (Lisa Martinez, current 31200)
  725. entries: [
  726. { offsetDays: -790, mileage: 8500, title: "Tacoma - 8K Oil Change", desc: "First service. Synthetic oil, filter, tire rotation.", type: "maintenance", techName: "Jake Wilson" },
  727. { offsetDays: -520, mileage: 15800, title: "Tacoma - 15K Service", desc: "Oil change, cabin filter, brake inspection.", type: "maintenance", techName: "Jake Wilson" },
  728. { offsetDays: -250, mileage: 24200, title: "Tacoma - 24K Service", desc: "Oil, tire rotation, differential fluid check.", type: "maintenance", techName: "Erik Haugen" },
  729. ],
  730. },
  731. ];
  732. const today = new Date("2026-04-05");
  733. const predMaintRecords = [];
  734. for (const hist of predMaintHistory) {
  735. for (const entry of hist.entries) {
  736. const serviceDate = new Date(today);
  737. serviceDate.setDate(serviceDate.getDate() + entry.offsetDays);
  738. const rec = await prisma.serviceRecord.create({
  739. data: {
  740. organizationId: ORG_ID,
  741. vehicleId: hist.vehicleId,
  742. title: entry.title,
  743. description: entry.desc,
  744. type: entry.type,
  745. status: "completed",
  746. serviceDate,
  747. mileage: entry.mileage,
  748. techName: entry.techName,
  749. shopName: "Egeland Auto",
  750. subtotal: 180,
  751. taxRate: 8,
  752. taxAmount: 14.40,
  753. totalAmount: 194.40,
  754. cost: 194.40,
  755. partItems: { create: [{ name: "Synthetic Oil (5qt)", partNumber: "OIL-SYN-5Q", quantity: 1, unitPrice: 45, total: 45 }, { name: "Oil Filter", partNumber: "OF-UNI", quantity: 1, unitPrice: 12, total: 12 }] },
  756. laborItems: { create: [{ description: "Service and inspection", hours: 1.2, rate: 102.50, total: 123 }] },
  757. },
  758. });
  759. predMaintRecords.push(rec);
  760. }
  761. }
  762. console.log(` Created ${predMaintRecords.length} historical service records across ${predMaintHistory.length} vehicles`);
  763. // Enable predicted maintenance feature setting
  764. console.log("\nEnabling predicted maintenance feature...");
  765. await Promise.all([
  766. prisma.appSetting.upsert({
  767. where: { organizationId_key: { organizationId: ORG_ID, key: "maintenance.enabled" } },
  768. create: { organizationId: ORG_ID, key: "maintenance.enabled", value: "true", userId: USER_ID },
  769. update: { value: "true" },
  770. }),
  771. prisma.appSetting.upsert({
  772. where: { organizationId_key: { organizationId: ORG_ID, key: "maintenance.serviceInterval" } },
  773. create: { organizationId: ORG_ID, key: "maintenance.serviceInterval", value: "15000", userId: USER_ID },
  774. update: { value: "15000" },
  775. }),
  776. prisma.appSetting.upsert({
  777. where: { organizationId_key: { organizationId: ORG_ID, key: "maintenance.approachingThreshold" } },
  778. create: { organizationId: ORG_ID, key: "maintenance.approachingThreshold", value: "1000", userId: USER_ID },
  779. update: { value: "1000" },
  780. }),
  781. ]);
  782. console.log(" Enabled predicted maintenance (interval: 15,000 mi, approaching: 1,000 mi)");
  783. // -- SMS Messages --
  784. console.log("\nCreating SMS messages...");
  785. const shopNumber = "+15551234567";
  786. await Promise.all([
  787. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15551002000", body: "Hi Summit Construction, your Ford F-150 (CO-4455) transmission flush is complete. Total: $689.04. Ready for pickup.", status: "delivered", organizationId: ORG_ID, customerId: customers[0].id } }),
  788. prisma.smsMessage.create({ data: { direction: "inbound", fromNumber: "+15551002000", toNumber: shopNumber, body: "Thanks! We'll send someone before 4pm. Can you look at the D6 bulldozer next week? Blade cylinder is leaking again.", status: "received", organizationId: ORG_ID, customerId: customers[0].id, createdAt: new Date(Date.now() - 3500000) } }),
  789. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15551002000", body: "Absolutely, we can fit the D6 in on Tuesday. We'll order the seal kit ahead of time.", status: "delivered", organizationId: ORG_ID, customerId: customers[0].id, createdAt: new Date(Date.now() - 3400000) } }),
  790. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15552013344", body: "Hi James, your Toyota Camry is due for its 30K service. We have Thursday or Friday availability.", status: "delivered", organizationId: ORG_ID, customerId: customers[1].id, createdAt: new Date(Date.now() - 86400000) } }),
  791. prisma.smsMessage.create({ data: { direction: "inbound", fromNumber: "+15552013344", toNumber: shopNumber, body: "Thursday morning works. Synthetic oil like last time please.", status: "received", organizationId: ORG_ID, customerId: customers[1].id, createdAt: new Date(Date.now() - 82800000) } }),
  792. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15552013344", body: "Thursday 8am confirmed. Full synthetic 0W-20 as always. See you then!", status: "delivered", organizationId: ORG_ID, customerId: customers[1].id, createdAt: new Date(Date.now() - 82000000) } }),
  793. prisma.smsMessage.create({ data: { direction: "inbound", fromNumber: "+15553025566", toNumber: shopNumber, body: "Our Volvo FH 640 (unit #5) is showing a check engine light. Can you get it in ASAP?", status: "received", organizationId: ORG_ID, customerId: customers[2].id, createdAt: new Date(Date.now() - 172800000) } }),
  794. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15553025566", body: "We can take the Volvo FH 640 first thing tomorrow. Have the driver bring it in by 7am.", status: "delivered", organizationId: ORG_ID, customerId: customers[2].id, createdAt: new Date(Date.now() - 172000000) } }),
  795. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15553025566", body: "Update on the Volvo FH 640: DOT inspection in progress. Minor issues with marker lights and wipers. Done by 3pm.", status: "delivered", organizationId: ORG_ID, customerId: customers[2].id, createdAt: new Date(Date.now() - 86400000) } }),
  796. prisma.smsMessage.create({ data: { direction: "inbound", fromNumber: "+15552101122", toNumber: shopNumber, body: "Our John Deere 6R is running rough and hydraulics feel sluggish. Planting season starts in 3 weeks!", status: "received", organizationId: ORG_ID, customerId: customers[10].id, createdAt: new Date(Date.now() - 432000000) } }),
  797. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15552101122", body: "Bring the John Deere 6R in this week, we'll bump it to priority. Likely needs 500hr service + hydraulic analysis.", status: "delivered", organizationId: ORG_ID, customerId: customers[10].id, createdAt: new Date(Date.now() - 428400000) } }),
  798. prisma.smsMessage.create({ data: { direction: "inbound", fromNumber: "+15552101122", toNumber: shopNumber, body: "Great. The Massey Ferguson 8S has low hydraulic pressure too. Can you look at both?", status: "received", organizationId: ORG_ID, customerId: customers[10].id, createdAt: new Date(Date.now() - 424800000) } }),
  799. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15552101122", body: "Bring both Wednesday. JD done same day, Massey Thursday. Both ready before planting.", status: "delivered", organizationId: ORG_ID, customerId: customers[10].id, createdAt: new Date(Date.now() - 421200000) } }),
  800. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15557151122", body: "Kevin, your Sprinter turbo has excessive shaft play causing black smoke. Replacement: $1,280 + labor. Proceed?", status: "delivered", organizationId: ORG_ID, customerId: customers[15].id, createdAt: new Date(Date.now() - 345600000) } }),
  801. prisma.smsMessage.create({ data: { direction: "inbound", fromNumber: "+15557151122", toNumber: shopNumber, body: "Ouch. Yeah go ahead, I need the van for catering events next week.", status: "received", organizationId: ORG_ID, customerId: customers[15].id, createdAt: new Date(Date.now() - 342000000) } }),
  802. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15557151122", body: "Parts arrive Thursday, done Friday afternoon. Total: $2,243.70 including oil change.", status: "delivered", organizationId: ORG_ID, customerId: customers[15].id, createdAt: new Date(Date.now() - 338400000) } }),
  803. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15559087788", body: "Ridgeline, the Komatsu PC210 track chains are done. Both sides + new sprockets. Total: $9,309.60. Ready for transport.", status: "delivered", organizationId: ORG_ID, customerId: customers[8].id, createdAt: new Date(Date.now() - 604800000) } }),
  804. prisma.smsMessage.create({ data: { direction: "inbound", fromNumber: "+15559087788", toNumber: shopNumber, body: "Excellent work. Sending the lowboy tomorrow. Also sending the Volvo EC220E for 1000hr service.", status: "received", organizationId: ORG_ID, customerId: customers[8].id, createdAt: new Date(Date.now() - 601200000) } }),
  805. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15559087788", body: "We have Volvo EC220E filters in stock. 1-2 day turnaround once it arrives.", status: "delivered", organizationId: ORG_ID, customerId: customers[8].id, createdAt: new Date(Date.now() - 597600000) } }),
  806. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15554037788", body: "Hi Sarah, your Porsche 911 annual service is complete. Total: $832.14. All OEM parts as always.", status: "delivered", organizationId: ORG_ID, customerId: customers[3].id, createdAt: new Date(Date.now() - 259200000) } }),
  807. prisma.smsMessage.create({ data: { direction: "inbound", fromNumber: "+15554037788", toNumber: shopNumber, body: "Perfect, thank you. I also want to get a quote on the BMW brake job with OEM rotors.", status: "received", organizationId: ORG_ID, customerId: customers[3].id, createdAt: new Date(Date.now() - 255600000) } }),
  808. prisma.smsMessage.create({ data: { direction: "outbound", fromNumber: shopNumber, toNumber: "+15554037788", body: "Quote sent to your email - $1,711.80 for the full brake overhaul with OEM rotors and pads. Valid until March 15.", status: "delivered", organizationId: ORG_ID, customerId: customers[3].id, createdAt: new Date(Date.now() - 254000000) } }),
  809. ]);
  810. console.log(" Created 22 SMS messages");
  811. // -- Technicians & Work Board --
  812. console.log("\nCreating technicians...");
  813. // Clean up existing workboard data
  814. await prisma.technician.deleteMany({ where: { organizationId: ORG_ID } });
  815. const technicians = await Promise.all([
  816. prisma.technician.create({ data: { name: "Jake Wilson", color: "#3b82f6", sortOrder: 0, organizationId: ORG_ID } }),
  817. prisma.technician.create({ data: { name: "Chris Taylor", color: "#22c55e", sortOrder: 1, organizationId: ORG_ID } }),
  818. prisma.technician.create({ data: { name: "Marcus Reed", color: "#f59e0b", sortOrder: 2, organizationId: ORG_ID } }),
  819. prisma.technician.create({ data: { name: "Sofia Andersen", color: "#ec4899", sortOrder: 3, organizationId: ORG_ID } }),
  820. prisma.technician.create({ data: { name: "Erik Haugen", color: "#8b5cf6", sortOrder: 4, organizationId: ORG_ID } }),
  821. prisma.technician.create({ data: { name: "Lars Johansen", color: "#06b6d4", sortOrder: 5, organizationId: ORG_ID } }),
  822. prisma.technician.create({ data: { name: "Nina Berglund", color: "#f97316", sortOrder: 6, organizationId: ORG_ID } }),
  823. prisma.technician.create({ data: { name: "Tom Bradley", color: "#14b8a6", sortOrder: 7, organizationId: ORG_ID } }),
  824. prisma.technician.create({ data: { name: "Kari Moen", color: "#a855f7", sortOrder: 8, organizationId: ORG_ID } }),
  825. prisma.technician.create({ data: { name: "Daniel Eriksen", color: "#ef4444", sortOrder: 9, organizationId: ORG_ID } }),
  826. // Demo Owner (index 10) — linked to the demo user so dashboard "My Active Jobs" populates
  827. prisma.technician.create({ data: { name: "Demo Owner", color: "#0ea5e9", sortOrder: 10, organizationId: ORG_ID, userId: USER_ID } }),
  828. ]);
  829. console.log(` Created ${technicians.length} technicians`);
  830. // Board assignments - spread across the current week
  831. console.log("\nCreating board assignments...");
  832. // Anchor to 2026-03-09 (Monday) so the work board day view looks great
  833. const monday = new Date("2026-03-09T00:00:00");
  834. const day = (offset: number) => {
  835. const d = new Date(monday);
  836. d.setDate(d.getDate() + offset);
  837. return d;
  838. };
  839. // Helper: create a datetime on a given day offset at a specific hour:minute
  840. const dt = (dayOffset: number, hour: number, minute = 0) => {
  841. const d = new Date(monday);
  842. d.setDate(d.getDate() + dayOffset);
  843. d.setHours(hour, minute, 0, 0);
  844. return d;
  845. };
  846. // Helper to create service record with parts + labor
  847. const sr = (base: Record<string, unknown>, parts: { name: string; partNumber: string; quantity: number; unitPrice: number; total: number }[], labor: { description: string; hours: number; rate: number; total: number }[], notes?: string) => {
  848. const subtotal = parts.reduce((s, p) => s + p.total, 0) + labor.reduce((s, l) => s + l.total, 0);
  849. const taxAmount = Math.round(subtotal * 0.08 * 100) / 100;
  850. return prisma.serviceRecord.create({ data: { ...base, organizationId: ORG_ID, subtotal, taxRate: 8, taxAmount, totalAmount: subtotal + taxAmount, cost: subtotal + taxAmount, diagnosticNotes: notes || null, partItems: { create: parts }, laborItems: { create: labor } } as never });
  851. };
  852. // Create service records for the board (assigned ones)
  853. const boardServiceRecords = await Promise.all([
  854. // 0: Honda Civic AC
  855. sr({ vehicleId: vehicles[5].id, title: "Honda Civic - AC Compressor", description: "AC not blowing cold. Compressor clutch not engaging.", type: "repair", status: "pending", serviceDate: day(0), mileage: 45200, techName: "Jake Wilson", shopName: "Egeland Auto" },
  856. [{ name: "AC Compressor Assembly", partNumber: "HON-ACC-10G", quantity: 1, unitPrice: 480, total: 480 }, { name: "Refrigerant R-134a (2 cans)", partNumber: "REF-134A-2", quantity: 1, unitPrice: 45, total: 45 }],
  857. [{ description: "AC compressor removal and replacement", hours: 2.5, rate: 110, total: 275 }, { description: "System evacuate, recharge and leak test", hours: 1.0, rate: 110, total: 110 }],
  858. "Compressor clutch not engaging. Checked voltage at clutch connector - 12V present. Clutch coil resistance out of spec. Replace compressor assembly."),
  859. // 1: Audi A4 timing belt
  860. sr({ vehicleId: vehicles[10].id, title: "Audi A4 - Timing Belt Service", description: "Scheduled timing belt and water pump replacement at 60K miles.", type: "maintenance", status: "scheduled", serviceDate: day(0), mileage: 60000, techName: "Chris Taylor", shopName: "Egeland Auto" },
  861. [{ name: "Timing Belt Kit w/ Water Pump", partNumber: "AUD-TBK-A4", quantity: 1, unitPrice: 385, total: 385 }, { name: "Thermostat Assembly", partNumber: "AUD-TH-A4", quantity: 1, unitPrice: 65, total: 65 }, { name: "Coolant G13 (5L)", partNumber: "AUD-COOL-G13", quantity: 1, unitPrice: 42, total: 42 }],
  862. [{ description: "Timing belt and water pump replacement", hours: 4.5, rate: 120, total: 540 }, { description: "Coolant flush and bleed", hours: 1.0, rate: 120, total: 120 }]),
  863. // 2: Tesla Model Y suspension
  864. sr({ vehicleId: vehicles[7].id, title: "Tesla Model Y - Suspension Noise", description: "Customer reports clunking from front left over bumps.", type: "repair", status: "pending", serviceDate: day(1), mileage: 32000, techName: "Sofia Andersen", shopName: "Egeland Auto" },
  865. [{ name: "Front Lower Control Arm (L)", partNumber: "TES-LCA-MY-L", quantity: 1, unitPrice: 290, total: 290 }],
  866. [{ description: "Diagnose suspension noise", hours: 0.5, rate: 110, total: 55 }, { description: "Control arm replacement and alignment", hours: 2.0, rate: 110, total: 220 }],
  867. "Play found in front left lower control arm ball joint. No other issues found. Recommend alignment after replacement."),
  868. // 3: Silverado 60K
  869. sr({ vehicleId: vehicles[8].id, title: "Silverado - 60K Service", description: "60,000 mile major service. Transmission fluid, spark plugs, coolant flush.", type: "maintenance", status: "scheduled", serviceDate: day(1), mileage: 60000, techName: "Jake Wilson", shopName: "Egeland Auto" },
  870. [{ name: "ATF Dexron VI (12qt)", partNumber: "GM-ATF-DEX6", quantity: 1, unitPrice: 120, total: 120 }, { name: "Spark Plugs ACDelco (8)", partNumber: "ACD-SP-53", quantity: 8, unitPrice: 12, total: 96 }, { name: "Coolant Dex-Cool (2gal)", partNumber: "GM-COOL-DC", quantity: 1, unitPrice: 38, total: 38 }],
  871. [{ description: "Transmission fluid exchange", hours: 1.5, rate: 110, total: 165 }, { description: "Spark plug replacement (V8)", hours: 1.5, rate: 110, total: 165 }, { description: "Coolant flush and refill", hours: 1.0, rate: 110, total: 110 }]),
  872. // 4: Tacoma leaf springs
  873. sr({ vehicleId: vehicles[16].id, title: "Toyota Tacoma - Leaf Spring Replacement", description: "Rear leaf springs sagging. Replace with upgraded OEM springs.", type: "repair", status: "pending", serviceDate: day(1), mileage: 55000, techName: "Erik Haugen", shopName: "Egeland Auto" },
  874. [{ name: "Rear Leaf Spring Pack (pair)", partNumber: "TOY-LS-TAC", quantity: 1, unitPrice: 520, total: 520 }, { name: "U-Bolt Kit", partNumber: "TOY-UB-TAC", quantity: 1, unitPrice: 85, total: 85 }],
  875. [{ description: "Leaf spring removal and installation (both sides)", hours: 3.5, rate: 110, total: 385 }]),
  876. // 5: Bobcat S650 annual
  877. sr({ vehicleId: vehicles[32].id, title: "Bobcat S650 - Annual Service", description: "Full annual service. Engine oil, hydraulic filters, drive belt.", type: "maintenance", status: "scheduled", serviceDate: day(2), mileage: 2200, techName: "Marcus Reed", shopName: "Egeland Auto" },
  878. [{ name: "Engine Oil 15W-40 (2gal)", partNumber: "BOB-15W40-2G", quantity: 1, unitPrice: 68, total: 68 }, { name: "Oil Filter", partNumber: "BOB-OF-S650", quantity: 1, unitPrice: 22, total: 22 }, { name: "Hydraulic Filter Set", partNumber: "BOB-HFS-S650", quantity: 1, unitPrice: 95, total: 95 }, { name: "Drive Belt", partNumber: "BOB-DB-S650", quantity: 1, unitPrice: 48, total: 48 }],
  879. [{ description: "Engine oil and filter change", hours: 1.0, rate: 130, total: 130 }, { description: "Hydraulic filter replacement", hours: 1.0, rate: 130, total: 130 }, { description: "Drive belt inspection and replacement", hours: 0.5, rate: 130, total: 65 }]),
  880. // 6: CAT 745 transmission rebuild
  881. sr({ vehicleId: vehicles[34].id, title: "CAT 745 - Transmission Rebuild", description: "Slipping in 3rd gear under load. Full transmission rebuild.", type: "repair", status: "in_progress", serviceDate: day(0), mileage: 8500, techName: "Marcus Reed", shopName: "Egeland Auto" },
  882. [{ name: "Transmission Rebuild Kit", partNumber: "CAT-TRK-745", quantity: 1, unitPrice: 4200, total: 4200 }, { name: "Torque Converter", partNumber: "CAT-TC-745", quantity: 1, unitPrice: 2800, total: 2800 }, { name: "Transmission Oil (20gal)", partNumber: "CAT-TO-20G", quantity: 1, unitPrice: 480, total: 480 }],
  883. [{ description: "Transmission removal", hours: 8.0, rate: 150, total: 1200 }, { description: "Rebuild and reassembly", hours: 16.0, rate: 150, total: 2400 }, { description: "Installation and calibration", hours: 6.0, rate: 150, total: 900 }],
  884. "3rd gear clutch pack worn beyond spec. Torque converter showing excessive slip. Full rebuild recommended over clutch pack only due to hours on unit."),
  885. // 7: F-150 exhaust
  886. sr({ vehicleId: vehicles[3].id, title: "Ford F-150 - Exhaust Leak Repair", description: "Exhaust manifold gasket leak. Replace gasket and inspect cat.", type: "repair", status: "pending", serviceDate: day(2), mileage: 52000, techName: "Jake Wilson", shopName: "Egeland Auto" },
  887. [{ name: "Exhaust Manifold Gasket Set", partNumber: "FORD-EMG-5L", quantity: 1, unitPrice: 85, total: 85 }, { name: "Exhaust Manifold Bolts (set)", partNumber: "FORD-EMB-5L", quantity: 1, unitPrice: 42, total: 42 }],
  888. [{ description: "Manifold removal and gasket replacement", hours: 2.5, rate: 110, total: 275 }, { description: "Cat converter inspection", hours: 0.5, rate: 110, total: 55 }]),
  889. // 8: Ram transfer case
  890. sr({ vehicleId: vehicles[16].id, title: "Ram 1500 - Transfer Case Service", description: "Transfer case fluid change. Customer reports 4WD engagement delay.", type: "maintenance", status: "pending", serviceDate: day(3), mileage: 45000, techName: "Sofia Andersen", shopName: "Egeland Auto" },
  891. [{ name: "Transfer Case Fluid (2qt)", partNumber: "RAM-TCF-2Q", quantity: 1, unitPrice: 48, total: 48 }, { name: "Transfer Case Drain Plug Gasket", partNumber: "RAM-DPG-TC", quantity: 1, unitPrice: 8, total: 8 }],
  892. [{ description: "Transfer case fluid drain and refill", hours: 1.0, rate: 110, total: 110 }, { description: "4WD engagement test and inspection", hours: 0.5, rate: 110, total: 55 }],
  893. "Fluid was dark and slightly burnt. Delay was from low fluid level. Refilled and tested - engages promptly now. Monitor."),
  894. // 9: Combine pre-season
  895. sr({ vehicleId: vehicles[27].id, title: "Combine Harvester - Pre-Season Prep", description: "Full pre-season inspection. Header, feeder chain, sieve adjustments, all fluids.", type: "maintenance", status: "scheduled", serviceDate: day(4), mileage: 2800, techName: "Marcus Reed", shopName: "Egeland Auto" },
  896. [{ name: "Engine Oil 15W-40 (5gal)", partNumber: "CMB-15W40-5G", quantity: 1, unitPrice: 185, total: 185 }, { name: "Hydraulic Filter Set", partNumber: "CMB-HFS", quantity: 1, unitPrice: 110, total: 110 }, { name: "Feeder Chain", partNumber: "CMB-FC-1", quantity: 1, unitPrice: 380, total: 380 }, { name: "Sieve Section (2)", partNumber: "CMB-SS-2", quantity: 2, unitPrice: 145, total: 290 }],
  897. [{ description: "Engine oil and filter change", hours: 1.5, rate: 140, total: 210 }, { description: "Feeder chain replacement", hours: 2.5, rate: 140, total: 350 }, { description: "Sieve adjustment and replacement", hours: 2.0, rate: 140, total: 280 }, { description: "Full system inspection and grease", hours: 2.0, rate: 140, total: 280 }]),
  898. // 10: Jeep axle seal
  899. sr({ vehicleId: vehicles[12].id, title: "Jeep Wrangler - Axle Seal Replacement", description: "Rear axle seal leaking. Replace seals and check diff fluid.", type: "repair", status: "pending", serviceDate: day(4), mileage: 62000, techName: "Chris Taylor", shopName: "Egeland Auto" },
  900. [{ name: "Rear Axle Seal Kit", partNumber: "JEEP-ASK-JL", quantity: 1, unitPrice: 65, total: 65 }, { name: "Differential Fluid 75W-140 (2.5qt)", partNumber: "JEEP-DF-75W", quantity: 1, unitPrice: 52, total: 52 }],
  901. [{ description: "Axle seal replacement (both sides)", hours: 2.5, rate: 110, total: 275 }, { description: "Differential fluid top-off and inspection", hours: 0.5, rate: 110, total: 55 }]),
  902. // 11: Ram oil change (Lars)
  903. sr({ vehicleId: vehicles[15].id, title: "Ram 1500 - Oil Change & Inspection", description: "Regular 10K mile service. Check brakes and tires.", type: "maintenance", status: "scheduled", serviceDate: day(0), mileage: 30000, techName: "Lars Johansen", shopName: "Egeland Auto" },
  904. [{ name: "Engine Oil 5W-20 (7qt)", partNumber: "RAM-5W20-7Q", quantity: 1, unitPrice: 52, total: 52 }, { name: "Oil Filter", partNumber: "RAM-OF-HEMI", quantity: 1, unitPrice: 14, total: 14 }],
  905. [{ description: "Oil and filter change", hours: 0.5, rate: 110, total: 55 }, { description: "Brake and tire inspection", hours: 0.5, rate: 110, total: 55 }]),
  906. // 12: F-150 wheel bearing (Nina)
  907. sr({ vehicleId: vehicles[2].id, title: "Ford F-150 - Wheel Bearing", description: "Front left wheel bearing noise. Replace bearing assembly.", type: "repair", status: "pending", serviceDate: day(1), mileage: 68000, techName: "Nina Berglund", shopName: "Egeland Auto" },
  908. [{ name: "Front Wheel Bearing Hub Assembly", partNumber: "FORD-WBH-F150", quantity: 1, unitPrice: 285, total: 285 }],
  909. [{ description: "Wheel bearing hub replacement", hours: 2.0, rate: 110, total: 220 }, { description: "Road test and verify", hours: 0.5, rate: 110, total: 55 }],
  910. "Confirmed bearing noise from front left. Bearing has play when checked on lift. Right side OK for now."),
  911. // 13: Concrete mixer (Tom)
  912. sr({ vehicleId: vehicles[20].id, title: "Concrete Mixer - Drum Motor Service", description: "Hydraulic motor service for drum rotation. Sluggish under load.", type: "repair", status: "in_progress", serviceDate: day(0), mileage: 75000, techName: "Tom Bradley", shopName: "Egeland Auto" },
  913. [{ name: "Hydraulic Motor Seal Kit", partNumber: "MIX-HMSK", quantity: 1, unitPrice: 280, total: 280 }, { name: "Hydraulic Oil ISO 46 (10gal)", partNumber: "HYD-ISO46-10G", quantity: 1, unitPrice: 180, total: 180 }, { name: "Hydraulic Hose Assembly", partNumber: "MIX-HHA-12", quantity: 2, unitPrice: 95, total: 190 }],
  914. [{ description: "Hydraulic motor removal and reseal", hours: 4.0, rate: 140, total: 560 }, { description: "Hose replacement and system flush", hours: 2.0, rate: 140, total: 280 }, { description: "Load test drum rotation", hours: 1.0, rate: 140, total: 140 }]),
  915. // 14: Tractor PTO (Kari)
  916. sr({ vehicleId: vehicles[25].id, title: "Tractor - PTO Clutch Adjustment", description: "PTO slipping under heavy load. Adjust clutch pack and inspect.", type: "repair", status: "pending", serviceDate: day(2), mileage: 3200, techName: "Kari Moen", shopName: "Egeland Auto" },
  917. [{ name: "PTO Clutch Friction Disc Set", partNumber: "TRC-PTO-FDS", quantity: 1, unitPrice: 165, total: 165 }],
  918. [{ description: "PTO clutch pack inspection and adjustment", hours: 2.0, rate: 130, total: 260 }],
  919. "Clutch pack within adjustment range. Adjusted gap to spec. If slipping persists, full clutch pack replacement needed."),
  920. // 15: Dump truck tailgate (Daniel)
  921. sr({ vehicleId: vehicles[21].id, title: "Dump Truck - Tailgate Cylinder", description: "Tailgate cylinder leaking. Reseal and test.", type: "repair", status: "scheduled", serviceDate: day(1), mileage: 120000, techName: "Daniel Eriksen", shopName: "Egeland Auto" },
  922. [{ name: "Tailgate Cylinder Seal Kit", partNumber: "DMP-TCSK", quantity: 1, unitPrice: 145, total: 145 }, { name: "Hydraulic Oil ISO 46 (5gal)", partNumber: "HYD-ISO46-5G", quantity: 1, unitPrice: 95, total: 95 }],
  923. [{ description: "Cylinder removal and reseal", hours: 3.0, rate: 130, total: 390 }, { description: "Reinstall and cycle test", hours: 1.0, rate: 130, total: 130 }]),
  924. // 16: Forklift mast chain (Lars)
  925. sr({ vehicleId: vehicles[37].id, title: "Forklift - Mast Chain Replace", description: "Mast chain stretched beyond spec. Replace chains and adjust.", type: "repair", status: "pending", serviceDate: day(3), mileage: 5500, techName: "Lars Johansen", shopName: "Egeland Auto" },
  926. [{ name: "Mast Chain (pair)", partNumber: "FRK-MC-PAIR", quantity: 1, unitPrice: 420, total: 420 }, { name: "Chain Anchor Pins", partNumber: "FRK-CAP-4", quantity: 1, unitPrice: 35, total: 35 }],
  927. [{ description: "Mast chain removal and replacement", hours: 2.5, rate: 120, total: 300 }, { description: "Chain tension adjustment and mast alignment", hours: 1.0, rate: 120, total: 120 }]),
  928. // 17: VW Golf clutch (Nina)
  929. sr({ vehicleId: vehicles[14].id, title: "VW Golf GTI - Clutch Replace", description: "Clutch slipping at high RPM. Replace disc, pressure plate, throwout bearing.", type: "repair", status: "scheduled", serviceDate: day(2), mileage: 72000, techName: "Nina Berglund", shopName: "Egeland Auto" },
  930. [{ name: "Clutch Kit (disc, plate, bearing)", partNumber: "VW-CK-GTI", quantity: 1, unitPrice: 480, total: 480 }, { name: "Flywheel Bolts (set)", partNumber: "VW-FWB-GTI", quantity: 1, unitPrice: 32, total: 32 }],
  931. [{ description: "Transmission removal", hours: 3.5, rate: 120, total: 420 }, { description: "Clutch replacement and installation", hours: 2.5, rate: 120, total: 300 }, { description: "Bleed hydraulic clutch and road test", hours: 1.0, rate: 120, total: 120 }]),
  932. // 18: Combine header knives (Tom)
  933. sr({ vehicleId: vehicles[28].id, title: "Combine - Header Knife Sharpen", description: "Sharpen and replace worn header knives. 4 sections need new blades.", type: "maintenance", status: "pending", serviceDate: day(4), mileage: 2900, techName: "Tom Bradley", shopName: "Egeland Auto" },
  934. [{ name: "Header Knife Sections (pack of 10)", partNumber: "CMB-HKS-10", quantity: 1, unitPrice: 85, total: 85 }, { name: "Knife Rivets (50-pack)", partNumber: "CMB-KR-50", quantity: 1, unitPrice: 22, total: 22 }],
  935. [{ description: "Remove header knives", hours: 1.0, rate: 120, total: 120 }, { description: "Sharpen and replace worn sections", hours: 2.0, rate: 120, total: 240 }, { description: "Reinstall and test", hours: 1.0, rate: 120, total: 120 }]),
  936. // 19: Kenworth clutch (Kari)
  937. sr({ vehicleId: vehicles[17].id, title: "Kenworth T680 - Clutch Adjustment", description: "Driver reports clutch engagement point too high. Adjust and inspect.", type: "repair", status: "pending", serviceDate: day(3), mileage: 185000, techName: "Kari Moen", shopName: "Egeland Auto" },
  938. [{ name: "Clutch Adjustment Hardware", partNumber: "KW-CAH-T680", quantity: 1, unitPrice: 45, total: 45 }],
  939. [{ description: "Clutch linkage inspection and adjustment", hours: 1.5, rate: 140, total: 210 }, { description: "Road test under load", hours: 0.5, rate: 140, total: 70 }]),
  940. // 20: Jeep steering stabilizer (Daniel)
  941. sr({ vehicleId: vehicles[11].id, title: "Jeep Wrangler - Steering Stabilizer", description: "Death wobble at highway speed. Replace stabilizer and check tie rods.", type: "repair", status: "scheduled", serviceDate: day(4), mileage: 31000, techName: "Daniel Eriksen", shopName: "Egeland Auto" },
  942. [{ name: "Steering Stabilizer", partNumber: "JEEP-SS-JL", quantity: 1, unitPrice: 125, total: 125 }, { name: "Tie Rod End (pair)", partNumber: "JEEP-TRE-JL", quantity: 1, unitPrice: 140, total: 140 }],
  943. [{ description: "Steering stabilizer replacement", hours: 0.5, rate: 110, total: 55 }, { description: "Tie rod end inspection and replacement", hours: 1.5, rate: 110, total: 165 }]),
  944. // Friday extras (20–29)
  945. // 21: Camry cabin filter (Jake)
  946. sr({ vehicleId: vehicles[0].id, title: "Toyota Camry - Cabin Filter + Wipers", description: "Replace cabin air filter and wiper blades. Quick service.", type: "maintenance", status: "scheduled", serviceDate: day(4), mileage: 16500, techName: "Jake Wilson", shopName: "Egeland Auto" },
  947. [{ name: "Cabin Air Filter", partNumber: "TOY-CAF-CAM", quantity: 1, unitPrice: 22, total: 22 }, { name: "Wiper Blade Set (front)", partNumber: "TOY-WB-CAM", quantity: 1, unitPrice: 38, total: 38 }],
  948. [{ description: "Cabin filter and wiper replacement", hours: 0.3, rate: 95, total: 28.50 }]),
  949. // 22: Honda brakes (Jake)
  950. sr({ vehicleId: vehicles[5].id, title: "Honda Civic - Brake Pad Replace", description: "Front pads worn to 2mm. Replace front brake pads.", type: "repair", status: "pending", serviceDate: day(4), mileage: 46000, techName: "Jake Wilson", shopName: "Egeland Auto" },
  951. [{ name: "Front Brake Pad Set", partNumber: "HON-BP-CIV", quantity: 1, unitPrice: 85, total: 85 }, { name: "Brake Cleaner (2 cans)", partNumber: "BC-CLEAN-2", quantity: 1, unitPrice: 12, total: 12 }],
  952. [{ description: "Front brake pad replacement", hours: 1.0, rate: 95, total: 95 }, { description: "Brake inspection and road test", hours: 0.3, rate: 95, total: 28.50 }]),
  953. // 23: Silverado taillight (Jake)
  954. sr({ vehicleId: vehicles[8].id, title: "Silverado - Taillight Assembly", description: "Cracked right taillight from parking lot bump. Replace assembly.", type: "repair", status: "pending", serviceDate: day(4), mileage: 60500, techName: "Jake Wilson", shopName: "Egeland Auto" },
  955. [{ name: "Taillight Assembly (right)", partNumber: "GM-TLA-SIL-R", quantity: 1, unitPrice: 125, total: 125 }],
  956. [{ description: "Taillight assembly replacement", hours: 0.5, rate: 95, total: 47.50 }]),
  957. // 24: Sprinter oil (Chris)
  958. sr({ vehicleId: vehicles[9].id, title: "Sprinter - Oil Service + Inspection", description: "Regular oil change with full inspection. Check brake wear sensors.", type: "maintenance", status: "scheduled", serviceDate: day(4), mileage: 37000, techName: "Chris Taylor", shopName: "Egeland Auto" },
  959. [{ name: "Engine Oil 5W-30 (8qt)", partNumber: "MB-5W30-8Q", quantity: 1, unitPrice: 78, total: 78 }, { name: "Oil Filter", partNumber: "MB-OF-SPR", quantity: 1, unitPrice: 18, total: 18 }],
  960. [{ description: "Oil and filter change", hours: 0.5, rate: 110, total: 55 }, { description: "Multi-point inspection", hours: 1.0, rate: 110, total: 110 }]),
  961. // 25: BMW coolant (Chris)
  962. sr({ vehicleId: vehicles[4].id, title: "BMW 330i - Coolant Flush", description: "Coolant due. Flush and refill with BMW-approved coolant.", type: "maintenance", status: "scheduled", serviceDate: day(4), mileage: 52000, techName: "Chris Taylor", shopName: "Egeland Auto" },
  963. [{ name: "BMW Coolant Concentrate (2L)", partNumber: "BMW-COOL-2L", quantity: 2, unitPrice: 32, total: 64 }, { name: "Thermostat Gasket", partNumber: "BMW-TG-N20", quantity: 1, unitPrice: 12, total: 12 }],
  964. [{ description: "Coolant flush and refill", hours: 1.0, rate: 120, total: 120 }, { description: "Bleed cooling system", hours: 0.5, rate: 120, total: 60 }]),
  965. // 26: Ram alignment (Sofia)
  966. sr({ vehicleId: vehicles[15].id, title: "Ram 1500 - Alignment Check", description: "Pulling to the right after pothole. Full 4-wheel alignment.", type: "maintenance", status: "pending", serviceDate: day(4), mileage: 20000, techName: "Sofia Andersen", shopName: "Egeland Auto" },
  967. [],
  968. [{ description: "4-wheel alignment", hours: 1.0, rate: 110, total: 110 }]),
  969. // 27: Audi spark plugs (Sofia)
  970. sr({ vehicleId: vehicles[10].id, title: "Audi A4 - Spark Plug Replace", description: "Misfire on cylinder 2. Replace all 4 spark plugs.", type: "repair", status: "pending", serviceDate: day(4), mileage: 62000, techName: "Sofia Andersen", shopName: "Egeland Auto" },
  971. [{ name: "Spark Plugs NGK (set of 4)", partNumber: "AUD-SP-NGK4", quantity: 1, unitPrice: 68, total: 68 }, { name: "Ignition Coil (cyl 2)", partNumber: "AUD-IC-A4", quantity: 1, unitPrice: 52, total: 52 }],
  972. [{ description: "Spark plug replacement (4 cyl)", hours: 1.0, rate: 120, total: 120 }, { description: "Diagnose misfire and replace coil", hours: 0.5, rate: 120, total: 60 }],
  973. "P0302 - misfire cyl 2. Coil swap test confirmed faulty coil on cyl 2. Replace coil and all 4 plugs."),
  974. // 28: Tesla tire rotation (Sofia)
  975. sr({ vehicleId: vehicles[7].id, title: "Tesla Model Y - Tire Rotation", description: "Rotate tires front to rear. Check tread depth and tire pressure.", type: "maintenance", status: "scheduled", serviceDate: day(4), mileage: 33000, techName: "Sofia Andersen", shopName: "Egeland Auto" },
  976. [],
  977. [{ description: "Tire rotation front to rear", hours: 0.5, rate: 95, total: 47.50 }, { description: "Tread depth measurement and pressure set", hours: 0.2, rate: 95, total: 19 }]),
  978. // 29: Massey Ferguson radiator (Erik)
  979. sr({ vehicleId: vehicles[24].id, title: "Massey Ferguson - Radiator Flush", description: "Overheating under load. Flush radiator and check thermostat.", type: "maintenance", status: "pending", serviceDate: day(4), mileage: 3800, techName: "Erik Haugen", shopName: "Egeland Auto" },
  980. [{ name: "Coolant (5gal)", partNumber: "MF-COOL-5G", quantity: 1, unitPrice: 65, total: 65 }, { name: "Thermostat", partNumber: "MF-TH-8S", quantity: 1, unitPrice: 48, total: 48 }],
  981. [{ description: "Radiator flush and refill", hours: 1.5, rate: 130, total: 195 }, { description: "Thermostat replacement", hours: 1.0, rate: 130, total: 130 }]),
  982. // 30: Mack mirror (Nina)
  983. sr({ vehicleId: vehicles[19].id, title: "Mack Granite - Mirror Replacement", description: "Left side mirror housing cracked. Replace complete mirror assembly.", type: "repair", status: "pending", serviceDate: day(4), mileage: 157000, techName: "Nina Berglund", shopName: "Egeland Auto" },
  984. [{ name: "Complete Mirror Assembly (left)", partNumber: "MACK-MA-L-GR", quantity: 1, unitPrice: 285, total: 285 }],
  985. [{ description: "Mirror assembly replacement", hours: 1.0, rate: 120, total: 120 }]),
  986. // 31: Ram battery (Kari)
  987. sr({ vehicleId: vehicles[16].id, title: "Ram 1500 - Battery Replace", description: "Slow cranking. Battery tested bad. Replace with OEM spec.", type: "repair", status: "pending", serviceDate: day(4), mileage: 45500, techName: "Kari Moen", shopName: "Egeland Auto" },
  988. [{ name: "Battery Group 65 AGM", partNumber: "BAT-G65-AGM", quantity: 1, unitPrice: 185, total: 185 }],
  989. [{ description: "Battery replacement and terminal cleaning", hours: 0.5, rate: 95, total: 47.50 }, { description: "Charging system test", hours: 0.2, rate: 95, total: 19 }]),
  990. // === Monday extras to fill the timeline ===
  991. // 32: Erik - Porsche oil change (Monday)
  992. sr({ vehicleId: vehicles[13].id, title: "Porsche 911 - Oil Change", description: "Synthetic oil change with OEM filter. Check brake wear sensors.", type: "maintenance", status: "scheduled", serviceDate: day(0), mileage: 13200, techName: "Erik Haugen", shopName: "Egeland Auto" },
  993. [{ name: "Porsche Approved Oil 0W-40 (9qt)", partNumber: "POR-0W40-9Q", quantity: 1, unitPrice: 165, total: 165 }, { name: "Oil Filter", partNumber: "POR-OF-992", quantity: 1, unitPrice: 28, total: 28 }],
  994. [{ description: "Oil and filter change", hours: 1.0, rate: 145, total: 145 }, { description: "Multi-point inspection", hours: 0.5, rate: 145, total: 72.50 }]),
  995. // 33: Nina - BMW coolant hose (Monday)
  996. sr({ vehicleId: vehicles[4].id, title: "BMW 330i - Coolant Hose Replacement", description: "Upper radiator hose cracked. Replace hose and top off coolant.", type: "repair", status: "pending", serviceDate: day(0), mileage: 56000, techName: "Nina Berglund", shopName: "Egeland Auto" },
  997. [{ name: "Upper Radiator Hose", partNumber: "BMW-URH-N20", quantity: 1, unitPrice: 85, total: 85 }, { name: "Coolant G13 (1L)", partNumber: "BMW-COOL-1L", quantity: 2, unitPrice: 18, total: 36 }],
  998. [{ description: "Radiator hose replacement", hours: 1.5, rate: 120, total: 180 }, { description: "Coolant bleed and pressure test", hours: 0.5, rate: 120, total: 60 }]),
  999. // 34: Nina - Jeep brake inspection (Monday)
  1000. sr({ vehicleId: vehicles[11].id, title: "Jeep Wrangler - Brake Inspection", description: "Customer reports squealing. Inspect pads, rotors, and calipers.", type: "inspection", status: "scheduled", serviceDate: day(0), mileage: 29000, techName: "Nina Berglund", shopName: "Egeland Auto" },
  1001. [],
  1002. [{ description: "Full brake system inspection", hours: 1.0, rate: 110, total: 110 }, { description: "Document findings and recommend", hours: 0.5, rate: 110, total: 55 }]),
  1003. // 35: Kari - Fendt hydraulic filter (Monday)
  1004. sr({ vehicleId: vehicles[23].id, title: "Fendt 942 - Hydraulic Filter Service", description: "Scheduled hydraulic filter change. Check system pressure.", type: "maintenance", status: "scheduled", serviceDate: day(0), mileage: 1250, techName: "Kari Moen", shopName: "Egeland Auto" },
  1005. [{ name: "Hydraulic Filter Set", partNumber: "FENDT-HFS-942", quantity: 1, unitPrice: 165, total: 165 }, { name: "Hydraulic Oil Sample Kit", partNumber: "OIL-SAMPLE", quantity: 1, unitPrice: 15, total: 15 }],
  1006. [{ description: "Hydraulic filter replacement", hours: 1.5, rate: 150, total: 225 }, { description: "Pressure test and oil sample", hours: 1.0, rate: 150, total: 150 }]),
  1007. // 36: Kari - Excavator grease service (Monday)
  1008. sr({ vehicleId: vehicles[31].id, title: "Komatsu PC210 - Full Grease Service", description: "Complete grease service all 24 fittings. Check pin play.", type: "maintenance", status: "scheduled", serviceDate: day(0), mileage: 3150, techName: "Kari Moen", shopName: "Egeland Auto" },
  1009. [{ name: "Grease Cartridges (box of 10)", partNumber: "GRZ-EP2-10", quantity: 1, unitPrice: 42, total: 42 }],
  1010. [{ description: "Grease all fittings (24 points)", hours: 2.0, rate: 130, total: 260 }, { description: "Pin and bushing play inspection", hours: 0.5, rate: 130, total: 65 }]),
  1011. // 37: Daniel - Volvo FH brake adjustment (Monday)
  1012. sr({ vehicleId: vehicles[18].id, title: "Volvo FH 640 - Brake Adjustment", description: "Annual brake adjustment. Check linings and drums.", type: "maintenance", status: "scheduled", serviceDate: day(0), mileage: 93000, techName: "Daniel Eriksen", shopName: "Egeland Auto" },
  1013. [{ name: "Brake Lining Wear Indicators (set)", partNumber: "VOL-BLWI-FH", quantity: 1, unitPrice: 45, total: 45 }],
  1014. [{ description: "Brake adjustment all axles", hours: 2.5, rate: 140, total: 350 }, { description: "Lining measurement and documentation", hours: 1.0, rate: 140, total: 140 }]),
  1015. // 38: Daniel - Dump truck hydraulic hose (Monday)
  1016. sr({ vehicleId: vehicles[21].id, title: "Dump Truck - Hydraulic Hose Replace", description: "Hose bulging near fitting. Replace before failure.", type: "repair", status: "pending", serviceDate: day(0), mileage: 83000, techName: "Daniel Eriksen", shopName: "Egeland Auto" },
  1017. [{ name: "Hydraulic Hose Assembly 3/4\"", partNumber: "HYD-HA-34", quantity: 2, unitPrice: 120, total: 240 }, { name: "Hose Fittings (4-pack)", partNumber: "HYD-FIT-4", quantity: 1, unitPrice: 65, total: 65 }],
  1018. [{ description: "Hose removal and replacement", hours: 2.0, rate: 130, total: 260 }, { description: "System bleed and pressure test", hours: 0.5, rate: 130, total: 65 }]),
  1019. // 39: Lars - Kenworth air filter (Monday)
  1020. sr({ vehicleId: vehicles[17].id, title: "Kenworth T680 - Air Filter Service", description: "Replace primary and secondary air filters. Clean intake ducting.", type: "maintenance", status: "scheduled", serviceDate: day(0), mileage: 186500, techName: "Lars Johansen", shopName: "Egeland Auto" },
  1021. [{ name: "Primary Air Filter", partNumber: "KW-PAF-T680", quantity: 1, unitPrice: 85, total: 85 }, { name: "Secondary Air Filter", partNumber: "KW-SAF-T680", quantity: 1, unitPrice: 55, total: 55 }],
  1022. [{ description: "Air filter replacement (both)", hours: 0.5, rate: 130, total: 65 }, { description: "Intake system inspection and clean", hours: 0.5, rate: 130, total: 65 }]),
  1023. // 40: Sofia - Honda Civic tire rotation (Monday)
  1024. sr({ vehicleId: vehicles[5].id, title: "Honda Civic - Tire Rotation + Check", description: "Rotate tires. Customer also reports slight vibration at highway speed.", type: "maintenance", status: "pending", serviceDate: day(0), mileage: 68500, techName: "Sofia Andersen", shopName: "Egeland Auto" },
  1025. [],
  1026. [{ description: "Tire rotation", hours: 0.5, rate: 95, total: 47.50 }, { description: "Wheel balance check (4 wheels)", hours: 0.5, rate: 95, total: 47.50 }, { description: "Road test for vibration", hours: 0.3, rate: 95, total: 28.50 }]),
  1027. ]);
  1028. // Unassigned jobs (NOT on the board - will show in unassigned panel)
  1029. console.log("\nCreating unassigned service records...");
  1030. const unassignedRecords = await Promise.all([
  1031. sr({ vehicleId: vehicles[0].id, title: "Toyota Camry - Check Engine Light", description: "P0171 - System Too Lean. Diagnose and repair. Customer reports rough idle.", type: "repair", status: "pending", mileage: 16200, shopName: "Egeland Auto" },
  1032. [{ name: "MAF Sensor", partNumber: "TOY-MAF-CAM", quantity: 1, unitPrice: 145, total: 145 }, { name: "Air Filter", partNumber: "TOY-AF-CAM", quantity: 1, unitPrice: 18, total: 18 }],
  1033. [{ description: "Diagnostic scan and smoke test", hours: 1.0, rate: 110, total: 110 }, { description: "MAF sensor replacement", hours: 0.5, rate: 110, total: 55 }],
  1034. "P0171 lean code. Inspected intake for vacuum leaks - none found. MAF sensor reading low. Suspect contaminated MAF."),
  1035. sr({ vehicleId: vehicles[9].id, title: "Sprinter - Sliding Door Repair", description: "Sliding door sticking halfway. Roller mechanism needs replacement.", type: "repair", status: "pending", mileage: 36500, shopName: "Egeland Auto" },
  1036. [{ name: "Sliding Door Roller Assembly", partNumber: "MB-SDRA-SPR", quantity: 1, unitPrice: 220, total: 220 }, { name: "Door Track Lubricant", partNumber: "LUB-DTL-1", quantity: 1, unitPrice: 15, total: 15 }],
  1037. [{ description: "Roller mechanism removal and replacement", hours: 2.0, rate: 110, total: 220 }]),
  1038. sr({ vehicleId: vehicles[13].id, title: "Porsche 911 - Pre-Track Inspection", description: "Full safety inspection before April track day. Brakes, fluids, suspension, tires.", type: "inspection", status: "pending", mileage: 13000, shopName: "Egeland Auto" },
  1039. [{ name: "Brake Fluid DOT4 Racing (1L)", partNumber: "POR-BF-R-1L", quantity: 2, unitPrice: 48, total: 96 }],
  1040. [{ description: "Full multi-point track safety inspection", hours: 2.0, rate: 145, total: 290 }, { description: "Brake fluid flush with racing fluid", hours: 1.5, rate: 145, total: 217.50 }]),
  1041. sr({ vehicleId: vehicles[19].id, title: "Mack Granite - Dump Body Weld Repair", description: "Cracks in dump body floor. Weld repair and reinforce high-stress areas.", type: "repair", status: "pending", mileage: 156000, shopName: "Egeland Auto" },
  1042. [{ name: "Steel Plate 3/8\" (2 sheets)", partNumber: "STL-PLT-38", quantity: 2, unitPrice: 120, total: 240 }, { name: "Welding Wire (10lb)", partNumber: "WLD-WIRE-10", quantity: 1, unitPrice: 45, total: 45 }],
  1043. [{ description: "Grind and prep crack areas", hours: 2.0, rate: 130, total: 260 }, { description: "Weld repair and reinforce", hours: 4.0, rate: 130, total: 520 }]),
  1044. sr({ vehicleId: vehicles[22].id, title: "John Deere 6R - Front Loader Pins", description: "Excessive play in front loader attachment pins. Replace pins and bushings.", type: "repair", status: "pending", mileage: 2800, shopName: "Egeland Auto" },
  1045. [{ name: "Loader Pin Kit", partNumber: "JD-LPK-6R", quantity: 1, unitPrice: 185, total: 185 }, { name: "Bronze Bushings (set of 4)", partNumber: "JD-BB-6R-4", quantity: 1, unitPrice: 120, total: 120 }],
  1046. [{ description: "Pin and bushing removal", hours: 2.0, rate: 140, total: 280 }, { description: "New bushing press-in and pin installation", hours: 2.0, rate: 140, total: 280 }]),
  1047. sr({ vehicleId: vehicles[31].id, title: "Komatsu PC210 - Boom Cylinder Reseal", description: "Slow drift on boom cylinder. Reseal required.", type: "repair", status: "pending", mileage: 3200, shopName: "Egeland Auto" },
  1048. [{ name: "Boom Cylinder Seal Kit", partNumber: "KOM-BCSK-PC210", quantity: 1, unitPrice: 320, total: 320 }, { name: "Hydraulic Oil (5gal)", partNumber: "HYD-ISO46-5G", quantity: 1, unitPrice: 95, total: 95 }],
  1049. [{ description: "Boom cylinder removal", hours: 3.0, rate: 140, total: 420 }, { description: "Reseal and reinstall", hours: 2.5, rate: 140, total: 350 }]),
  1050. sr({ vehicleId: vehicles[36].id, title: "Liebherr LTM 1100 - Outrigger Service", description: "Right rear outrigger slow to extend. Inspect valve and cylinder seals.", type: "repair", status: "pending", mileage: 4200, shopName: "Egeland Auto" },
  1051. [{ name: "Outrigger Cylinder Seal Kit", partNumber: "LIE-OCSK-1100", quantity: 1, unitPrice: 450, total: 450 }, { name: "Outrigger Control Valve", partNumber: "LIE-OCV-1100", quantity: 1, unitPrice: 680, total: 680 }],
  1052. [{ description: "Diagnose outrigger hydraulic circuit", hours: 2.0, rate: 150, total: 300 }, { description: "Cylinder reseal or valve replacement", hours: 4.0, rate: 150, total: 600 }]),
  1053. sr({ vehicleId: vehicles[6].id, title: "Tesla Model 3 - 12V Battery Replace", description: "Low voltage warning. Replace 12V auxiliary battery.", type: "repair", status: "pending", mileage: 8200, shopName: "Egeland Auto" },
  1054. [{ name: "12V Lithium Battery (Tesla OEM)", partNumber: "TES-12V-M3", quantity: 1, unitPrice: 110, total: 110 }],
  1055. [{ description: "12V battery replacement", hours: 0.5, rate: 110, total: 55 }]),
  1056. sr({ vehicleId: vehicles[23].id, title: "Fendt 942 - GPS Autosteer Calibration", description: "Autosteer drifting right by 6 inches. Recalibrate GPS receiver and steering controller.", type: "maintenance", status: "scheduled", mileage: 1200, shopName: "Egeland Auto" },
  1057. [],
  1058. [{ description: "GPS receiver calibration", hours: 1.5, rate: 150, total: 225 }, { description: "Steering controller calibration and field test", hours: 2.0, rate: 150, total: 300 }],
  1059. "RTK base station signal verified. GPS receiver antenna checked - mounting bracket slightly loose causing drift. Tighten and recalibrate."),
  1060. sr({ vehicleId: vehicles[33].id, title: "Volvo EC220E - Bucket Teeth Replace", description: "3 worn bucket teeth. Replace full set of 5 for even wear.", type: "maintenance", status: "pending", mileage: 1600, shopName: "Egeland Auto" },
  1061. [{ name: "Bucket Teeth Set (5)", partNumber: "VOL-BTS-EC220", quantity: 1, unitPrice: 340, total: 340 }, { name: "Retainer Pins (5-pack)", partNumber: "VOL-RP-5", quantity: 1, unitPrice: 45, total: 45 }],
  1062. [{ description: "Bucket teeth removal and replacement", hours: 1.5, rate: 130, total: 195 }]),
  1063. sr({ vehicleId: vehicles[18].id, title: "Volvo FH 640 - Turbo Boost Leak", description: "Low power complaint. Suspect charge air cooler pipe leak. Diagnose.", type: "repair", status: "pending", mileage: 93500, shopName: "Egeland Auto" },
  1064. [{ name: "Charge Air Cooler Pipe + Clamps", partNumber: "VOL-CACP-FH", quantity: 1, unitPrice: 185, total: 185 }],
  1065. [{ description: "Boost leak diagnosis and smoke test", hours: 1.5, rate: 140, total: 210 }, { description: "Pipe replacement and clamp tightening", hours: 1.0, rate: 140, total: 140 }],
  1066. "Smoke test confirmed leak at charge air cooler pipe connection. Clamp was loose and pipe boot cracked."),
  1067. sr({ vehicleId: vehicles[17].id, title: "Kenworth T680 - Sleeper AC Repair", description: "Sleeper AC not cooling. Likely low refrigerant or compressor issue.", type: "repair", status: "waiting-parts", mileage: 186000, shopName: "Egeland Auto" },
  1068. [{ name: "Sleeper AC Compressor", partNumber: "KW-SAC-T680", quantity: 1, unitPrice: 580, total: 580 }, { name: "Refrigerant R-134a (3 cans)", partNumber: "REF-134A-3", quantity: 1, unitPrice: 65, total: 65 }, { name: "AC Condenser", partNumber: "KW-COND-T680", quantity: 1, unitPrice: 320, total: 320 }],
  1069. [{ description: "Sleeper AC system diagnosis", hours: 1.5, rate: 140, total: 210 }, { description: "Compressor and condenser replacement", hours: 3.5, rate: 140, total: 490 }, { description: "Evacuate, recharge and leak test", hours: 1.0, rate: 140, total: 140 }],
  1070. "Compressor seized. Condenser contaminated with metal debris from failed compressor. Both need replacement. Parts on order - ETA Wednesday."),
  1071. sr({ vehicleId: vehicles[38].id, title: "Corvette C8 - Pre-Track Brake Service", description: "Customer has track day in 2 weeks. Flush brake fluid, inspect pads, check tire wear.", type: "maintenance", status: "pending", mileage: 6200, shopName: "Egeland Auto" },
  1072. [{ name: "Brake Fluid DOT4 Racing (1L)", partNumber: "BF-DOT4R-1L", quantity: 3, unitPrice: 48, total: 144 }],
  1073. [{ description: "Brake fluid flush all 4 corners", hours: 1.5, rate: 130, total: 195 }, { description: "Brake pad measurement and inspection", hours: 0.5, rate: 130, total: 65 }, { description: "Tire tread depth and pressure check", hours: 0.3, rate: 130, total: 39 }]),
  1074. sr({ vehicleId: vehicles[39].id, title: "Defender 110 - Air Suspension Warning", description: "Dashboard warning light for air suspension. Possible compressor or height sensor issue.", type: "repair", status: "pending", mileage: 28500, shopName: "Egeland Auto" },
  1075. [{ name: "Air Suspension Height Sensor", partNumber: "LR-ASHS-DEF", quantity: 1, unitPrice: 210, total: 210 }],
  1076. [{ description: "Diagnose air suspension fault codes", hours: 1.0, rate: 120, total: 120 }, { description: "Height sensor replacement and calibration", hours: 1.5, rate: 120, total: 180 }]),
  1077. sr({ vehicleId: vehicles[40].id, title: "Charger R/T - Rear Alignment + Tire Replace", description: "Inner edge tire wear on rears. Alignment and new rear tires needed.", type: "repair", status: "pending", mileage: 35000, shopName: "Egeland Auto" },
  1078. [{ name: "Firestone Firehawk Indy 500 275/40R20 (pair)", partNumber: "FS-FH500-27540-2", quantity: 1, unitPrice: 380, total: 380 }],
  1079. [{ description: "Rear tire mount and balance (2)", hours: 0.5, rate: 95, total: 47.50 }, { description: "4-wheel alignment", hours: 1.0, rate: 110, total: 110 }]),
  1080. sr({ vehicleId: vehicles[41].id, title: "WRX - Clutch Adjustment + Inspection", description: "Customer reports high clutch engagement point. Inspect clutch wear and adjust.", type: "repair", status: "pending", mileage: 12400, shopName: "Egeland Auto" },
  1081. [{ name: "Clutch Master Cylinder Fluid", partNumber: "SUB-CMF-DOT4", quantity: 1, unitPrice: 15, total: 15 }],
  1082. [{ description: "Clutch pedal adjustment and bleed", hours: 0.5, rate: 110, total: 55 }, { description: "Clutch wear inspection via inspection port", hours: 0.5, rate: 110, total: 55 }],
  1083. "Clutch engagement point higher than normal but disc still within spec. Bled hydraulic line - air found. Pedal feel improved. Monitor."),
  1084. ]);
  1085. console.log(` Created ${unassignedRecords.length} unassigned service records`);
  1086. const jobUpdates = await Promise.all([
  1087. // ============ MONDAY (day 0) - 2026-03-09 - Primary showcase day ============
  1088. // Jake Wilson [0]: Honda AC (8:00-11:30) + F-150 trans flush (12:30-15:00)
  1089. prisma.serviceRecord.update({ where: { id: boardServiceRecords[0].id }, data: { technicianId: technicians[0].id, sortOrder: 0, startDateTime: dt(0, 8, 0), endDateTime: dt(0, 11, 30) } }),
  1090. prisma.serviceRecord.update({ where: { id: serviceRecords[18].id }, data: { technicianId: technicians[0].id, sortOrder: 1, startDateTime: dt(0, 12, 30), endDateTime: dt(0, 15, 0) } }),
  1091. // Chris Taylor [1]: Audi timing belt (7:30-13:00)
  1092. prisma.serviceRecord.update({ where: { id: boardServiceRecords[1].id }, data: { technicianId: technicians[1].id, sortOrder: 0, startDateTime: dt(0, 7, 30), endDateTime: dt(0, 13, 0) } }),
  1093. // Marcus Reed [2]: CAT 745 transmission rebuild (7:00-16:00, multi-day spans Mon-Wed)
  1094. prisma.serviceRecord.update({ where: { id: boardServiceRecords[6].id }, data: { technicianId: technicians[2].id, sortOrder: 0, startDateTime: dt(0, 7, 0), endDateTime: dt(2, 16, 0) } }),
  1095. // Sofia Andersen [3]: Tesla suspension (9:00-11:30)
  1096. prisma.serviceRecord.update({ where: { id: boardServiceRecords[2].id }, data: { technicianId: technicians[3].id, sortOrder: 0, startDateTime: dt(0, 9, 0), endDateTime: dt(0, 11, 30) } }),
  1097. // Lars Johansen [5]: Ram oil change (8:00-9:00)
  1098. prisma.serviceRecord.update({ where: { id: boardServiceRecords[11].id }, data: { technicianId: technicians[5].id, sortOrder: 0, startDateTime: dt(0, 8, 0), endDateTime: dt(0, 9, 0) } }),
  1099. // Tom Bradley [7]: Concrete mixer drum motor (7:30-14:30)
  1100. prisma.serviceRecord.update({ where: { id: boardServiceRecords[13].id }, data: { technicianId: technicians[7].id, sortOrder: 0, startDateTime: dt(0, 7, 30), endDateTime: dt(0, 14, 30) } }),
  1101. prisma.serviceRecord.update({ where: { id: boardServiceRecords[32].id }, data: { technicianId: technicians[4].id, sortOrder: 1, startDateTime: dt(0, 11, 0), endDateTime: dt(0, 12, 30) } }),
  1102. // Nina Berglund [6]: BMW coolant hose (7:30-9:30) + Jeep brake inspection (10:00-11:30)
  1103. prisma.serviceRecord.update({ where: { id: boardServiceRecords[33].id }, data: { technicianId: technicians[6].id, sortOrder: 0, startDateTime: dt(0, 7, 30), endDateTime: dt(0, 9, 30) } }),
  1104. prisma.serviceRecord.update({ where: { id: boardServiceRecords[34].id }, data: { technicianId: technicians[6].id, sortOrder: 1, startDateTime: dt(0, 10, 0), endDateTime: dt(0, 11, 30) } }),
  1105. // Kari Moen [8]: Fendt hydraulic filter (8:00-10:30) + Komatsu grease (11:00-13:30)
  1106. prisma.serviceRecord.update({ where: { id: boardServiceRecords[35].id }, data: { technicianId: technicians[8].id, sortOrder: 0, startDateTime: dt(0, 8, 0), endDateTime: dt(0, 10, 30) } }),
  1107. prisma.serviceRecord.update({ where: { id: boardServiceRecords[36].id }, data: { technicianId: technicians[8].id, sortOrder: 1, startDateTime: dt(0, 11, 0), endDateTime: dt(0, 13, 30) } }),
  1108. // Daniel Eriksen [9]: Volvo brake adjustment (7:30-11:00) + Dump truck hose (11:30-14:00)
  1109. prisma.serviceRecord.update({ where: { id: boardServiceRecords[37].id }, data: { technicianId: technicians[9].id, sortOrder: 0, startDateTime: dt(0, 7, 30), endDateTime: dt(0, 11, 0) } }),
  1110. prisma.serviceRecord.update({ where: { id: boardServiceRecords[38].id }, data: { technicianId: technicians[9].id, sortOrder: 1, startDateTime: dt(0, 11, 30), endDateTime: dt(0, 14, 0) } }),
  1111. prisma.serviceRecord.update({ where: { id: boardServiceRecords[39].id }, data: { technicianId: technicians[5].id, sortOrder: 2, startDateTime: dt(0, 10, 30), endDateTime: dt(0, 11, 30) } }),
  1112. // Sofia Andersen [3]: (already has Tesla 9-11:30) + Honda tire rotation (12:00-13:15)
  1113. prisma.serviceRecord.update({ where: { id: boardServiceRecords[40].id }, data: { technicianId: technicians[3].id, sortOrder: 1, startDateTime: dt(0, 12, 0), endDateTime: dt(0, 13, 15) } }),
  1114. // ============ TUESDAY (day 1) ============
  1115. // Jake [0]: Silverado 60K (8:00-11:30)
  1116. prisma.serviceRecord.update({ where: { id: boardServiceRecords[3].id }, data: { technicianId: technicians[0].id, sortOrder: 0, startDateTime: dt(1, 8, 0), endDateTime: dt(1, 11, 30) } }),
  1117. // Chris [1]: Sprinter turbo (7:30-13:00)
  1118. prisma.serviceRecord.update({ where: { id: serviceRecords[12].id }, data: { technicianId: technicians[1].id, sortOrder: 0, startDateTime: dt(1, 7, 30), endDateTime: dt(1, 13, 0) } }),
  1119. // Marcus [2]: CAT 745 continued (multi-day job spans from Monday)
  1120. // Erik [4]: Tacoma leaf springs (8:00-11:30)
  1121. prisma.serviceRecord.update({ where: { id: boardServiceRecords[4].id }, data: { technicianId: technicians[4].id, sortOrder: 0, startDateTime: dt(1, 8, 0), endDateTime: dt(1, 11, 30) } }),
  1122. // Nina [6]: F-150 wheel bearing (9:00-11:30)
  1123. prisma.serviceRecord.update({ where: { id: boardServiceRecords[12].id }, data: { technicianId: technicians[6].id, sortOrder: 0, startDateTime: dt(1, 9, 0), endDateTime: dt(1, 11, 30) } }),
  1124. // Daniel [9]: Dump truck tailgate (8:00-12:00)
  1125. prisma.serviceRecord.update({ where: { id: boardServiceRecords[15].id }, data: { technicianId: technicians[9].id, sortOrder: 0, startDateTime: dt(1, 8, 0), endDateTime: dt(1, 12, 0) } }),
  1126. // ============ WEDNESDAY (day 2) ============
  1127. // Jake [0]: F-150 exhaust (8:00-11:00)
  1128. prisma.serviceRecord.update({ where: { id: boardServiceRecords[7].id }, data: { technicianId: technicians[0].id, sortOrder: 0, startDateTime: dt(2, 8, 0), endDateTime: dt(2, 11, 0) } }),
  1129. // Marcus [2]: Bobcat annual (13:00-15:30, after CAT 745 wraps up)
  1130. prisma.serviceRecord.update({ where: { id: boardServiceRecords[5].id }, data: { technicianId: technicians[2].id, sortOrder: 1, startDateTime: dt(2, 13, 0), endDateTime: dt(2, 15, 30) } }),
  1131. // Chris [1]: Volvo EC220E (7:30-13:00)
  1132. prisma.serviceRecord.update({ where: { id: serviceRecords[10].id }, data: { technicianId: technicians[1].id, sortOrder: 0, startDateTime: dt(2, 7, 30), endDateTime: dt(2, 13, 0) } }),
  1133. // Kari [8]: Tractor PTO clutch (8:30-10:30)
  1134. prisma.serviceRecord.update({ where: { id: boardServiceRecords[14].id }, data: { technicianId: technicians[8].id, sortOrder: 0, startDateTime: dt(2, 8, 30), endDateTime: dt(2, 10, 30) } }),
  1135. // Nina [6]: VW Golf clutch (7:30-14:30)
  1136. prisma.serviceRecord.update({ where: { id: boardServiceRecords[17].id }, data: { technicianId: technicians[6].id, sortOrder: 0, startDateTime: dt(2, 7, 30), endDateTime: dt(2, 14, 30) } }),
  1137. // ============ THURSDAY (day 3) ============
  1138. // Sofia [3]: Ram transfer case (9:00-10:30)
  1139. prisma.serviceRecord.update({ where: { id: boardServiceRecords[8].id }, data: { technicianId: technicians[3].id, sortOrder: 0, startDateTime: dt(3, 9, 0), endDateTime: dt(3, 10, 30) } }),
  1140. // Jake [0]: Volvo FH DOT inspection (7:30-13:30)
  1141. prisma.serviceRecord.update({ where: { id: serviceRecords[5].id }, data: { technicianId: technicians[0].id, sortOrder: 0, startDateTime: dt(3, 7, 30), endDateTime: dt(3, 13, 30) } }),
  1142. // Lars [5]: Forklift mast chain (8:00-11:30)
  1143. prisma.serviceRecord.update({ where: { id: boardServiceRecords[16].id }, data: { technicianId: technicians[5].id, sortOrder: 0, startDateTime: dt(3, 8, 0), endDateTime: dt(3, 11, 30) } }),
  1144. // Kari [8]: Kenworth clutch adjust (8:00-10:00)
  1145. prisma.serviceRecord.update({ where: { id: boardServiceRecords[19].id }, data: { technicianId: technicians[8].id, sortOrder: 0, startDateTime: dt(3, 8, 0), endDateTime: dt(3, 10, 0) } }),
  1146. // ============ FRIDAY (day 4) ============
  1147. // Jake [0] (3 jobs): Camry cabin filter (8:00-8:30), Honda brakes (8:45-10:00), Silverado taillight (10:15-10:45)
  1148. prisma.serviceRecord.update({ where: { id: boardServiceRecords[21].id }, data: { technicianId: technicians[0].id, sortOrder: 0, startDateTime: dt(4, 8, 0), endDateTime: dt(4, 8, 30) } }),
  1149. prisma.serviceRecord.update({ where: { id: boardServiceRecords[22].id }, data: { technicianId: technicians[0].id, sortOrder: 1, startDateTime: dt(4, 8, 45), endDateTime: dt(4, 10, 0) } }),
  1150. prisma.serviceRecord.update({ where: { id: boardServiceRecords[23].id }, data: { technicianId: technicians[0].id, sortOrder: 2, startDateTime: dt(4, 10, 15), endDateTime: dt(4, 10, 45) } }),
  1151. // Chris [1] (3 jobs): Jeep axle seal (7:30-10:30), Sprinter oil (11:00-12:30), BMW coolant (13:00-14:30)
  1152. prisma.serviceRecord.update({ where: { id: boardServiceRecords[10].id }, data: { technicianId: technicians[1].id, sortOrder: 0, startDateTime: dt(4, 7, 30), endDateTime: dt(4, 10, 30) } }),
  1153. prisma.serviceRecord.update({ where: { id: boardServiceRecords[24].id }, data: { technicianId: technicians[1].id, sortOrder: 1, startDateTime: dt(4, 11, 0), endDateTime: dt(4, 12, 30) } }),
  1154. prisma.serviceRecord.update({ where: { id: boardServiceRecords[25].id }, data: { technicianId: technicians[1].id, sortOrder: 2, startDateTime: dt(4, 13, 0), endDateTime: dt(4, 14, 30) } }),
  1155. // Marcus [2]: Combine pre-season (7:00-15:00)
  1156. prisma.serviceRecord.update({ where: { id: boardServiceRecords[9].id }, data: { technicianId: technicians[2].id, sortOrder: 0, startDateTime: dt(4, 7, 0), endDateTime: dt(4, 15, 0) } }),
  1157. // Sofia [3] (3 jobs): Ram alignment (8:00-9:00), Audi spark plugs (9:30-11:00), Tesla tire rotation (11:30-12:15)
  1158. prisma.serviceRecord.update({ where: { id: boardServiceRecords[26].id }, data: { technicianId: technicians[3].id, sortOrder: 0, startDateTime: dt(4, 8, 0), endDateTime: dt(4, 9, 0) } }),
  1159. prisma.serviceRecord.update({ where: { id: boardServiceRecords[27].id }, data: { technicianId: technicians[3].id, sortOrder: 1, startDateTime: dt(4, 9, 30), endDateTime: dt(4, 11, 0) } }),
  1160. prisma.serviceRecord.update({ where: { id: boardServiceRecords[28].id }, data: { technicianId: technicians[3].id, sortOrder: 2, startDateTime: dt(4, 11, 30), endDateTime: dt(4, 12, 15) } }),
  1161. // Erik [4]: Massey Ferguson radiator (8:00-10:30)
  1162. prisma.serviceRecord.update({ where: { id: boardServiceRecords[29].id }, data: { technicianId: technicians[4].id, sortOrder: 0, startDateTime: dt(4, 8, 0), endDateTime: dt(4, 10, 30) } }),
  1163. // Nina [6]: Mack mirror replacement (9:00-10:00)
  1164. prisma.serviceRecord.update({ where: { id: boardServiceRecords[30].id }, data: { technicianId: technicians[6].id, sortOrder: 0, startDateTime: dt(4, 9, 0), endDateTime: dt(4, 10, 0) } }),
  1165. // Tom [7]: Combine header knives (7:30-11:30)
  1166. prisma.serviceRecord.update({ where: { id: boardServiceRecords[18].id }, data: { technicianId: technicians[7].id, sortOrder: 0, startDateTime: dt(4, 7, 30), endDateTime: dt(4, 11, 30) } }),
  1167. // Kari [8]: Ram battery replace (8:00-8:45)
  1168. prisma.serviceRecord.update({ where: { id: boardServiceRecords[31].id }, data: { technicianId: technicians[8].id, sortOrder: 0, startDateTime: dt(4, 8, 0), endDateTime: dt(4, 8, 45) } }),
  1169. // Daniel [9]: Jeep steering stabilizer (8:00-10:00)
  1170. prisma.serviceRecord.update({ where: { id: boardServiceRecords[20].id }, data: { technicianId: technicians[9].id, sortOrder: 0, startDateTime: dt(4, 8, 0), endDateTime: dt(4, 10, 0) } }),
  1171. ]);
  1172. console.log(` Updated ${jobUpdates.length} service records with technician assignments and time slots`);
  1173. // -- Assign the Demo Owner a few active jobs so the dashboard "My Active Jobs" populates --
  1174. console.log("\nAssigning active jobs to the Demo Owner technician...");
  1175. const demoOwnerTech = technicians[10]; // Demo Owner
  1176. const demoOwnerJobs = await Promise.all([
  1177. // Tesla Model Y suspension (pending) — reassign from Sofia
  1178. prisma.serviceRecord.update({ where: { id: boardServiceRecords[2].id }, data: { technicianId: demoOwnerTech.id } }),
  1179. // F-150 exhaust leak repair (pending) — reassign from Jake
  1180. prisma.serviceRecord.update({ where: { id: boardServiceRecords[7].id }, data: { technicianId: demoOwnerTech.id } }),
  1181. // Jeep axle seal replacement (pending) — reassign from Chris
  1182. prisma.serviceRecord.update({ where: { id: boardServiceRecords[10].id }, data: { technicianId: demoOwnerTech.id } }),
  1183. // Kenworth T680 Sleeper AC repair (waiting-parts) — previously unassigned
  1184. prisma.serviceRecord.update({ where: { id: unassignedRecords[11].id }, data: { technicianId: demoOwnerTech.id } }),
  1185. // Porsche 911 Pre-Track Inspection (pending) — previously unassigned
  1186. prisma.serviceRecord.update({ where: { id: unassignedRecords[2].id }, data: { technicianId: demoOwnerTech.id } }),
  1187. ]);
  1188. console.log(` Assigned ${demoOwnerJobs.length} active jobs to ${demoOwnerTech.name}`);
  1189. // -- Summary --
  1190. console.log("\n" + "=".repeat(50));
  1191. console.log("Seed completed!");
  1192. console.log("=".repeat(50));
  1193. console.log(` Customers: ${customers.length}`);
  1194. console.log(` Vehicles: ${vehicles.length}`);
  1195. console.log(` Service Records: ${serviceRecords.length + boardServiceRecords.length + unassignedRecords.length + predMaintRecords.length}`);
  1196. console.log(` Quotes: ${quotes.length}`);
  1197. console.log(` Inventory Parts: ${inventoryParts.length}`);
  1198. console.log(` Technicians: ${technicians.length}`);
  1199. console.log(` Board Assignments: (removed - technicianId set directly on service records)`);
  1200. console.log(` Unassigned Jobs: ${unassignedRecords.length}`);
  1201. console.log(` Notes: ${9 + additionalNotes.length}`);
  1202. console.log(` Reminders: ${8 + additionalReminders.length}`);
  1203. console.log(` Findings: ${findings.length}`);
  1204. console.log(` SMS Messages: 22`);
  1205. console.log("=".repeat(50));
  1206. }
  1207. seed()
  1208. .then(async () => { await prisma.$disconnect(); process.exit(0); })
  1209. .catch(async (e) => { console.error("Seed failed:", e); await prisma.$disconnect(); process.exit(1); });