/** * Production seed — Pelagia Marine Services * * Idempotent: safe to run multiple times (all operations are upsert). * Run with: pnpm db:seed:prod * * Seeds: * - Users (SSO, no password) * - Sites * - Vessels (assigned to sites) * - Accounting codes (full hierarchy from Rev. 01/251227) */ import { PrismaClient, Role } from "@prisma/client"; import { ACCOUNTING_CODES } from "./accounting-codes-data"; import bcrypt from "bcryptjs"; const hash = (p: string) => bcrypt.hash(p, 12); const db = new PrismaClient(); // ─── Users ──────────────────────────────────────────────────────────────────── const USERS: { employeeId: string; name: string; email: string; role: Role }[] = [ { employeeId: "ACC-001", name: "Akshata Teli", email: "akshata@pelagiamarine.com", role: Role.ACCOUNTS }, { employeeId: "ACC-002", name: "Dipali K", email: "dipali.k@pelagiamarine.com", role: Role.ACCOUNTS }, { employeeId: "ACC-003", name: "Nikita Accounts", email: "nikita.m@pelagiamarine.com", role: Role.ACCOUNTS }, { employeeId: "ACC-004", name: "Shailesh B", email: "shailesh.b@pelagiamarine.com", role: Role.ACCOUNTS }, { employeeId: "MGR-001", name: "Chhagan Sarang", email: "chhagan.sarang@pelagiamarine.com", role: Role.MANAGER }, { employeeId: "MGR-002", name: "Kaushal Pal Singh", email: "kps@pelagiamarine.com", role: Role.MANAGER }, { employeeId: "MGR-003", name: "Rakesh Kumar Pandey", email: "rkp@pelagiamarine.com", role: Role.MANAGER }, { employeeId: "MGR-004", name: "Tajinder Kaur", email: "tajinder.kaur@pelagiamarine.com", role: Role.MANAGER }, { employeeId: "MAN-001", name: "Mayur Deore", email: "mayur@pelagiamarine.com", role: Role.MANNING }, { employeeId: "MAN-002", name: "Sunil Gupta", email: "sunil.gupta@pelagiamarine.com", role: Role.MANNING }, { employeeId: "TCH-001", name: "Eeshan Singh", email: "eeshan.singh@pelagiamarine.com", role: Role.TECHNICAL }, { employeeId: "TCH-002", name: "Manjuprasad B", email: "manjuprasad.b@pelagiamarine.com", role: Role.TECHNICAL }, { employeeId: "TCH-003", name: "Shrikant T", email: "shrikant.t@pelagiamarine.com", role: Role.TECHNICAL }, { employeeId: "TCH-004", name: "Supriya Sutar", email: "supriya.s@pelagiamarine.com", role: Role.TECHNICAL }, ]; // ─── Sites ──────────────────────────────────────────────────────────────────── type SiteEntry = { code: string; name: string; address?: string; latitude?: number; longitude?: number }; const SITES: SiteEntry[] = [ { code: "HOFC", name: "Head Office Mumbai", address: "ZION, 409-410, Sector 10, Kharghar, Panvel, Maharashtra 410210", latitude: 19.0449, longitude: 73.0758, }, { code: "HLDA", name: "Haldia Port", address: "Haldia Dock Complex, Haldia, West Bengal 721604", latitude: 22.0286, longitude: 88.0780, }, { code: "KCHI", name: "Kochi", address: "LNG Terminal, Survey No. 347, Puthuvype, Kochi, Kerala 682508", latitude: 10.0261, longitude: 76.2193, }, { code: "PTNA", name: "Patna", address: "Gaighat, Ashok Rajpath, Gulzarbagh, Patna, Bihar 800007", latitude: 25.6097, longitude: 85.1376, }, ]; // ─── Vessels (code, name, site code) ───────────────────────────────────────── const VESSELS: { code: string; name: string }[] = [ { name: "Head Office", code: "HOFC" }, { name: "CSD PMS KOCHI", code: "PMSK" }, { name: "CSD H&R 1", code: "HNR1" }, { name: "CSD H&R 3", code: "HNR3" }, { name: "CSD H&R 4", code: "HNR4" }, { name: "CSD CHAMPION", code: "CHMP" }, { name: "CSD HANUMAN", code: "HANU" }, { name: "KAVARATTI", code: "KVRT" }, { name: "LACCADIVES", code: "LACD" }, { name: "THINNAKARA", code: "THNK" }, { name: "THILLAAKAM", code: "THKM" }, { name: "GD3000", code: "GD30" }, ]; // ─── Main ───────────────────────────────────────────────────────────────────── async function main() { console.log("🌱 Pelagia production seed starting…\n"); // ── Users ────────────────────────────────────────────────────────────────── console.log("👤 Seeding users…"); for (const u of USERS) { await db.user.upsert({ where: { email: u.email }, update: { name: u.name, role: u.role }, create: { employeeId: u.employeeId, email: u.email, name: u.name, role: u.role, // No passwordHash — SSO-only login }, }); console.log(` ✓ ${u.name} <${u.email}> [${u.role}]`); } const admin = await db.user.upsert({ where: { email: "admin@pelagiamarine.com" }, update: {}, create: { employeeId: "ADM-001", email: "admin@pelagiamarine.com", name: "System Admin", passwordHash: await hash("admin1234"), role: Role.ADMIN }, }); // ── Sites ────────────────────────────────────────────────────────────────── console.log("\n📍 Seeding sites…"); for (const s of SITES) { const data = { name: s.name, address: s.address ?? null, latitude: s.latitude ?? null, longitude: s.longitude ?? null, }; await db.site.upsert({ where: { code: s.code }, update: data, create: { code: s.code, ...data }, }); const geo = s.latitude ? ` (${s.latitude.toFixed(4)}, ${s.longitude!.toFixed(4)})` : ""; console.log(` ✓ ${s.name} (${s.code})${geo}`); } // ── Vessels ──────────────────────────────────────────────────────────────── console.log("\n🚢 Seeding vessels…"); for (const v of VESSELS) { await db.vessel.upsert({ where: { code: v.code }, update: { name: v.name }, create: { code: v.code, name: v.name }, }); console.log(` ✓ ${v.name} (${v.code})`); } // ── Accounting Codes ─────────────────────────────────────────────────────── console.log("\n📊 Seeding accounting codes…"); const codeIdMap = new Map(); // Pass 1 — upsert every entry without parent links for (const entry of ACCOUNTING_CODES) { const rec = await db.account.upsert({ where: { code: entry.code }, update: { name: entry.name }, create: { code: entry.code, name: entry.name }, }); codeIdMap.set(entry.code, rec.id); } // Pass 2 — wire up parent relationships for (const entry of ACCOUNTING_CODES) { if (entry.parentCode) { const parentId = codeIdMap.get(entry.parentCode); if (parentId) { await db.account.update({ where: { code: entry.code }, data: { parentId }, }); } } } const leafCount = ACCOUNTING_CODES.filter((e) => { return !ACCOUNTING_CODES.some((other) => other.parentCode === e.code); }).length; console.log(` ✓ ${ACCOUNTING_CODES.length} codes (${leafCount} selectable leaf items)`); console.log("\n✅ Production seed complete."); } main() .catch((e) => { console.error("❌ Seed failed:", e); process.exit(1); }) .finally(() => db.$disconnect());