You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
3.3 KiB
TypeScript
71 lines
3.3 KiB
TypeScript
// apps/hq/scripts/import-employees.ts — one-off: seed the employee master (D34).
|
|
// Adds each employee with username = first-name slug, a default password `<username>@123`,
|
|
// and must_change_password=1 (they change it on first login). Active per ACTIVE_STAT.
|
|
// Idempotent: skips a username/email that already exists.
|
|
// DATABASE_URL=postgres://… npx tsx apps/hq/scripts/import-employees.ts
|
|
import { openDb, sqliteFilePath } from '../src/db'
|
|
import { openPgDb, pgTargetDescription, requireDbUrlForEnv } from '../src/db-pg'
|
|
import { createEmployee } from '../src/repos-employees'
|
|
import type { DB } from '../src/db'
|
|
|
|
// From empmaster.xlsx (EMPNAME + ACTIVE_STAT + DESIGNATION code). Emails/phones were blank.
|
|
const EMPLOYEES: { name: string; active: boolean; title?: string }[] = [
|
|
{ name: 'ADITHYA', active: true, title: '702' },
|
|
{ name: 'RAVEENA', active: false, title: '702' },
|
|
{ name: 'ADITHYAN', active: true },
|
|
{ name: 'CYRIAC', active: true, title: '702' },
|
|
{ name: 'ANJU', active: true, title: '702' },
|
|
{ name: 'RENJITH', active: true },
|
|
{ name: 'AJMAL', active: true },
|
|
{ name: 'ELIAS MATHEW', active: false, title: '703' },
|
|
{ name: 'THOMAS', active: true, title: '700' },
|
|
{ name: 'DEVIKA', active: true, title: '702' },
|
|
{ name: 'TIBIN', active: true, title: '703' },
|
|
]
|
|
|
|
/** First name, lowercased, non-alphanumerics stripped — the login username + password base. */
|
|
function slug(name: string): string {
|
|
return name.trim().toLowerCase().split(/\s+/)[0]!.replace(/[^a-z0-9]/g, '')
|
|
}
|
|
|
|
async function main() {
|
|
// Pre-ship audit FIX A: the SAME resolver server.ts uses (never re-derived locally) — and,
|
|
// unlike the server, this one-off script hard-fails rather than silently falling back to a
|
|
// throwaway SQLite file when NODE_ENV=production resolves no Postgres target.
|
|
const pgUrl = requireDbUrlForEnv()
|
|
if (pgUrl !== '') {
|
|
console.log(`[db] engine: postgres ${pgTargetDescription(pgUrl)}`)
|
|
} else {
|
|
console.log(`[db] engine: sqlite at ${sqliteFilePath(process.env['HQ_DATA_DIR'])}`)
|
|
}
|
|
const db: DB = pgUrl !== '' ? await openPgDb(pgUrl) : openDb(process.env['HQ_DATA_DIR'])
|
|
try {
|
|
let added = 0, skipped = 0
|
|
const summary: string[] = []
|
|
for (const e of EMPLOYEES) {
|
|
const username = slug(e.name)
|
|
const password = `${username}@123`
|
|
const email = `${username}@sims.local` // placeholder (no real emails in the master)
|
|
try {
|
|
const emp = await createEmployee(db, 'system', {
|
|
email, username, displayName: e.name, role: 'staff', password,
|
|
mustChangePassword: true, ...(e.title !== undefined ? { title: e.title } : {}),
|
|
})
|
|
// Set inactive employees inactive (createEmployee makes them active by default).
|
|
if (!e.active) await db.run(`UPDATE staff_user SET active=0 WHERE id=?`, emp.id)
|
|
added++
|
|
summary.push(` + ${e.name} → username: ${username} password: ${password} ${e.active ? '' : '(inactive)'}`)
|
|
} catch (err) {
|
|
skipped++
|
|
summary.push(` - ${e.name} skipped: ${err instanceof Error ? err.message : String(err)}`)
|
|
}
|
|
}
|
|
// eslint-disable-next-line no-console
|
|
console.log(`Employee import: ${added} added, ${skipped} skipped.\n${summary.join('\n')}`)
|
|
} finally {
|
|
await db.close()
|
|
}
|
|
}
|
|
|
|
main().catch((e) => { console.error(e); process.exit(1) })
|