mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-11 10:23:27 +00:00
feat: Ramaiah hospital seed script — 195 doctors from website data
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
117
scripts/seed-ramaiah.ts
Normal file
117
scripts/seed-ramaiah.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Helix Engage — Ramaiah Hospital Data Seeder
|
||||
*
|
||||
* Seeds clinic + 195 doctors from scraped website data.
|
||||
* Run: cd helix-engage && SEED_GQL=https://ramaiah.app.healix360.net/graphql SEED_SUB=ramaiah SEED_ORIGIN=https://ramaiah.app.healix360.net npx tsx scripts/seed-ramaiah.ts
|
||||
*/
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
const GQL = process.env.SEED_GQL ?? 'http://localhost:4000/graphql';
|
||||
const SUB = process.env.SEED_SUB ?? 'ramaiah';
|
||||
const ORIGIN = process.env.SEED_ORIGIN ?? 'http://ramaiah.localhost:5080';
|
||||
const DATA_FILE = process.env.SEED_DATA ?? '/tmp/ramaiah-seed-data.json';
|
||||
|
||||
let token = '';
|
||||
|
||||
async function gql(query: string, variables?: any) {
|
||||
const h: Record<string, string> = { 'Content-Type': 'application/json', 'X-Workspace-Subdomain': SUB };
|
||||
if (token) h['Authorization'] = `Bearer ${token}`;
|
||||
const r = await fetch(GQL, { method: 'POST', headers: h, body: JSON.stringify({ query, variables }) });
|
||||
const d: any = await r.json();
|
||||
if (d.errors) { console.error('❌', d.errors[0].message); throw new Error(d.errors[0].message); }
|
||||
return d.data;
|
||||
}
|
||||
|
||||
async function auth() {
|
||||
const d1 = await gql(`mutation { getLoginTokenFromCredentials(email: "dev@fortytwo.dev", password: "tim@apple.dev", origin: "${ORIGIN}") { loginToken { token } } }`);
|
||||
const lt = d1.getLoginTokenFromCredentials.loginToken.token;
|
||||
const d2 = await gql(`mutation { getAuthTokensFromLoginToken(loginToken: "${lt}", origin: "${ORIGIN}") { tokens { accessOrWorkspaceAgnosticToken { token } } } }`);
|
||||
token = d2.getAuthTokensFromLoginToken.tokens.accessOrWorkspaceAgnosticToken.token;
|
||||
}
|
||||
|
||||
async function mk(entity: string, data: any): Promise<string> {
|
||||
const cap = entity[0].toUpperCase() + entity.slice(1);
|
||||
const d = await gql(`mutation($data: ${cap}CreateInput!) { create${cap}(data: $data) { id } }`, { data });
|
||||
return d[`create${cap}`].id;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🌱 Seeding Ramaiah Hospital data...\n');
|
||||
|
||||
const raw = JSON.parse(readFileSync(DATA_FILE, 'utf-8'));
|
||||
console.log(`📁 Loaded ${raw.doctors.length} doctors, ${raw.departments.length} departments\n`);
|
||||
|
||||
await auth();
|
||||
console.log('✅ Auth OK\n');
|
||||
|
||||
// Clinic
|
||||
console.log('🏥 Clinic');
|
||||
const clinicId = await mk('clinic', {
|
||||
name: raw.clinic.name,
|
||||
clinicName: raw.clinic.name,
|
||||
status: 'ACTIVE',
|
||||
opensAt: '08:00',
|
||||
closesAt: '20:00',
|
||||
openMonday: true, openTuesday: true, openWednesday: true,
|
||||
openThursday: true, openFriday: true, openSaturday: true, openSunday: false,
|
||||
phone: {
|
||||
primaryPhoneNumber: raw.clinic.phone?.replace(/[^0-9]/g, '').slice(-10) ?? '',
|
||||
primaryPhoneCallingCode: '+91',
|
||||
primaryPhoneCountryCode: 'IN',
|
||||
},
|
||||
addressCustom: {
|
||||
addressStreet1: raw.clinic.address?.split(',')[0] ?? 'New BEL Road',
|
||||
addressCity: raw.clinic.city ?? 'Bangalore',
|
||||
addressState: raw.clinic.state ?? 'Karnataka',
|
||||
addressCountry: 'India',
|
||||
addressPostcode: raw.clinic.pincode ?? '560054',
|
||||
},
|
||||
onlineBooking: true,
|
||||
walkInAllowed: true,
|
||||
});
|
||||
console.log(` ${raw.clinic.name}: ${clinicId}\n`);
|
||||
|
||||
// Re-auth (long operation ahead)
|
||||
await auth();
|
||||
|
||||
// Doctors — batch in groups of 20 with re-auth
|
||||
console.log(`👨⚕️ Doctors (${raw.doctors.length})`);
|
||||
let created = 0;
|
||||
let failed = 0;
|
||||
|
||||
for (let i = 0; i < raw.doctors.length; i++) {
|
||||
// Re-auth every 40 doctors (token may expire on long runs)
|
||||
if (i > 0 && i % 40 === 0) {
|
||||
await auth();
|
||||
console.log(` (re-authed at ${i})`);
|
||||
}
|
||||
|
||||
const doc = raw.doctors[i];
|
||||
const firstName = doc.name.replace(/^Dr\.?\s*/i, '').split(' ')[0] ?? '';
|
||||
const lastNameParts = doc.name.replace(/^Dr\.?\s*/i, '').split(' ').slice(1);
|
||||
const lastName = lastNameParts.join(' ');
|
||||
|
||||
try {
|
||||
await mk('doctor', {
|
||||
name: doc.name,
|
||||
fullName: { firstName, lastName },
|
||||
department: doc.department ?? 'Other',
|
||||
specialty: doc.designation ?? 'Consultant',
|
||||
qualifications: doc.qualifications ?? '',
|
||||
registrationNumber: '',
|
||||
active: true,
|
||||
});
|
||||
created++;
|
||||
if (created % 20 === 0) console.log(` ${created}/${raw.doctors.length} created...`);
|
||||
} catch (err: any) {
|
||||
failed++;
|
||||
console.error(` ✗ ${doc.name}: ${err.message?.slice(0, 80)}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n ✅ ${created} doctors created, ${failed} failed\n`);
|
||||
console.log('🎉 Ramaiah seed complete!');
|
||||
console.log(` 1 clinic · ${created} doctors · ${raw.departments.length} departments`);
|
||||
}
|
||||
|
||||
main().catch(e => { console.error('💥', e.message); process.exit(1); });
|
||||
Reference in New Issue
Block a user