interface EhrMigrationPlan {
sourceEhr: 'epic' | 'athena' | 'cerner' | 'eclinicalworks';
targetEhr: 'epic' | 'athena' | 'cerner' | 'eclinicalworks';
migrationDate: Date;
providerCount: number;
steps: MigrationStep[];
}
interface MigrationStep {
order: number;
name: string;
description: string;
rollbackable: boolean;
estimatedMinutes: number;
}
function generateMigrationPlan(source: string, target: string): EhrMigrationPlan {
return {
sourceEhr: source as any,
targetEhr: target as any,
migrationDate: new Date(),
providerCount: 0,
steps: [
{ order: 1, name: 'Freeze new enrollments', description: 'Stop new provider enrollments on source EHR', rollbackable: true, estimatedMinutes: 5 },
{ order: 2, name: 'Export note templates', description: 'Export all custom note templates and SmartPhrases', rollbackable: true, estimatedMinutes: 30 },
{ order: 3, name: 'Configure target EHR', description: 'Set up FHIR endpoints and OAuth for target EHR', rollbackable: true, estimatedMinutes: 60 },
{ order: 4, name: 'Parallel run', description: 'Run both EHRs for 1 week — compare note output', rollbackable: true, estimatedMinutes: 10080 },
{ order: 5, name: 'Provider re-enrollment', description: 'Re-enroll providers on target EHR', rollbackable: true, estimatedMinutes: 120 },
{ order: 6, name: 'Cutover', description: 'Switch primary EHR integration to target', rollbackable: true, estimatedMinutes: 15 },
{ order: 7, name: 'Decommission source', description: 'Disable source EHR integration after 30-day soak', rollbackable: false, estimatedMinutes: 30 },
],
};
}
interface NoteTemplate {
id: string;
name: string;
specialty: string;
sections: string[];
smartPhrases: Record<string, string>;
}
async function migrateTemplates(
sourceApi: any,
targetApi: any,
): Promise<{ migrated: number; failed: string[] }> {
const { data: templates } = await sourceApi.get('/note-templates');
const failed: string[] = [];
let migrated = 0;
for (const template of templates) {
try {
const { smartPhrases, ...portable } = template;
await targetApi.post('/note-templates', {
...portable,
});
migrated++;
} catch (err) {
failed.push(template.id);
}
}
return { migrated, failed };
}