Files
dyolink/backend/prisma/seed.ts

268 lines
7.1 KiB
TypeScript
Raw Normal View History

// backend/prisma/seed.ts
import { PrismaClient } from '@prisma/client';
import { randomUUID } from 'crypto';
import { config } from 'dotenv';
import path from 'path';
import {
TREATMENT_TYPES,
LEGACY_TREATMENT_TYPES,
LAB_WORKFLOW_STEPS,
PROSTHESIS_TYPES,
CATALOG_TRANSLATIONS,
buildProsthesisStepCodes,
} from './catalog-seed-data';
// Load environment variables from the correct path
const envPath = path.join(__dirname, '..', '.env');
console.log('Loading .env from:', envPath);
config({ path: envPath });
// Verify DATABASE_URL is loaded
if (!process.env.DATABASE_URL) {
console.error('❌ DATABASE_URL is not set in environment');
console.log('Current directory:', process.cwd());
console.log('.env path:', envPath);
process.exit(1);
}
console.log('✅ DATABASE_URL found:', process.env.DATABASE_URL.substring(0, 30) + '...');
const prisma = new PrismaClient();
async function main() {
console.log('🌱 Starting seeding...');
// Test the connection
await prisma.$connect();
console.log('✅ Database connected successfully');
// Create organization types
await prisma.organizationType.upsert({
where: { name: 'CLINIC' },
update: {},
create: { name: 'CLINIC' },
});
console.log('✅ Created clinic type');
await prisma.organizationType.upsert({
where: { name: 'LAB' },
update: {},
create: { name: 'LAB' },
});
console.log('✅ Created lab type');
// Create plans
const plans = [
{ name: 'trial', maxUsers: 5, price: 0, features: {} },
{ name: 'Small', maxUsers: 5, price: 150, features: {} },
{ name: 'Medium', maxUsers: 10, price: 250, features: {} },
{ name: 'Large', maxUsers: 15, price: 400, features: {} },
{ name: 'Enterprise', maxUsers: 999999, price: 1000, features: {} },
];
for (const plan of plans) {
await prisma.plan.upsert({
where: { name: plan.name },
update: {},
create: plan,
});
}
console.log('✅ Created plans');
// Minimal permission model (confirmed):
// - Sidebar tabs use READ/EDIT
// - EDIT implies READ in app logic
// - Owners effectively get all permissions
const features = [
{
name: 'Today',
permissions: ['TAB_TODAY_READ', 'TAB_TODAY_EDIT'],
},
2026-04-30 18:49:23 +03:30
{
name: 'Staff',
permissions: ['TAB_STAFF_READ', 'TAB_STAFF_EDIT'],
},
{
name: 'Organizations',
permissions: ['TAB_ORGANIZATIONS_READ', 'TAB_ORGANIZATIONS_EDIT'],
2026-04-30 18:49:23 +03:30
},
{
name: 'Patients',
permissions: ['TAB_PATIENTS_READ', 'TAB_PATIENTS_EDIT'],
},
{
2026-04-30 18:49:23 +03:30
name: 'Appointment',
permissions: ['TAB_APPOINTMENTS_READ', 'TAB_APPOINTMENTS_EDIT'],
},
{
2026-04-30 18:49:23 +03:30
name: 'Treatment',
permissions: ['TAB_TREATMENT_READ', 'TAB_TREATMENT_EDIT'],
},
{
name: 'Cases',
permissions: ['TAB_CASES_READ', 'TAB_CASES_EDIT'],
},
{
name: 'Tasks',
permissions: ['TAB_TASKS_READ', 'TAB_TASKS_EDIT'],
},
{
name: 'Billing',
permissions: ['TAB_BILLING_READ', 'TAB_BILLING_EDIT'],
},
{
name: 'Reports',
permissions: ['TAB_REPORTS_READ', 'TAB_REPORTS_EDIT'],
},
];
for (const feature of features) {
const createdFeature = await prisma.feature.upsert({
where: { name: feature.name },
update: {},
create: { name: feature.name },
});
for (const permissionName of feature.permissions) {
await prisma.permission.upsert({
where: { name: permissionName },
update: {},
create: {
name: permissionName,
featureId: createdFeature.id,
},
});
}
}
console.log('✅ Created features and permissions');
for (const type of [...TREATMENT_TYPES, ...LEGACY_TREATMENT_TYPES]) {
const isActive = TREATMENT_TYPES.some((t) => t.code === type.code);
const availableInAppointments = type.availableInAppointments ?? true;
const availableInTreatment = type.availableInTreatment ?? true;
await prisma.treatmentType.upsert({
where: { code: type.code },
update: {
labDependent: type.labDependent,
sortOrder: type.sortOrder,
isActive,
availableInAppointments,
availableInTreatment,
},
create: {
id: randomUUID(),
code: type.code,
labDependent: type.labDependent,
sortOrder: type.sortOrder,
isActive,
availableInAppointments,
availableInTreatment,
},
});
}
console.log('✅ Seeded treatment type catalog');
for (const step of LAB_WORKFLOW_STEPS) {
await prisma.labWorkflowStep.upsert({
where: { code: step.code },
update: { sortOrder: step.sortOrder },
create: {
id: randomUUID(),
code: step.code,
sortOrder: step.sortOrder,
},
});
}
console.log('✅ Seeded lab workflow steps');
const workflowStepByCode = new Map(
(
await prisma.labWorkflowStep.findMany({
select: { id: true, code: true },
})
).map((s) => [s.code, s.id]),
);
for (const type of PROSTHESIS_TYPES) {
const prosthesisType = await prisma.prosthesisType.upsert({
where: { code: type.code },
update: {
sortOrder: type.sortOrder,
skipPackingShipping: type.skipPackingShipping ?? false,
isActive: true,
},
create: {
id: randomUUID(),
code: type.code,
sortOrder: type.sortOrder,
skipPackingShipping: type.skipPackingShipping ?? false,
isActive: true,
},
});
const stepCodes = buildProsthesisStepCodes(type);
for (const [index, stepCode] of stepCodes.entries()) {
const labWorkflowStepId = workflowStepByCode.get(stepCode);
if (!labWorkflowStepId) {
throw new Error(`Unknown workflow step code: ${stepCode}`);
}
await prisma.prosthesisTypeStep.upsert({
where: {
prosthesisTypeId_stepOrder: {
prosthesisTypeId: prosthesisType.id,
stepOrder: index + 1,
},
},
update: { labWorkflowStepId },
create: {
id: randomUUID(),
prosthesisTypeId: prosthesisType.id,
labWorkflowStepId,
stepOrder: index + 1,
},
});
}
}
console.log('✅ Seeded prosthesis types and workflow mappings');
for (const tr of CATALOG_TRANSLATIONS) {
const existing = await prisma.catalogTranslation.findFirst({
where: {
entityKind: tr.entityKind,
entityCode: tr.entityCode,
locale: tr.locale,
},
});
if (existing) {
await prisma.catalogTranslation.update({
where: { id: existing.id },
data: { label: tr.label },
});
} else {
await prisma.catalogTranslation.create({
data: {
id: randomUUID(),
entityKind: tr.entityKind,
entityCode: tr.entityCode,
locale: tr.locale,
label: tr.label,
},
});
}
}
console.log('✅ Seeded catalog translations');
console.log('🌱 Seeding completed successfully!');
}
main()
.catch((e) => {
console.error('❌ Seeding failed:', e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});