Files
hrm-medpark/apps/api/scripts/seed-test-data.ts
T
Danil Suhomlinov 33800292aa chore: add Coolify deployment scaffolding (Dockerfiles, prod compose, git hygiene)
- apps/api/Dockerfile: build NestJS, run prisma migrate deploy on start
- apps/web/Dockerfile + nginx.conf: build Vite, serve static, proxy /api -> api
- docker-compose.coolify.yml: full prod stack (postgres, redis, minio, keycloak, api, web)
- .dockerignore / .gitignore / .gitattributes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 17:42:45 +03:00

663 lines
29 KiB
TypeScript

import {
AnexaType,
CampaignStatus,
ContractCategory,
ContractPeriod,
ContractType,
DisciplinarySanctionType,
DiplomaStatus,
DocumentType,
EmployeeStatus,
EvaluationScore,
FamilyMemberType,
InventoryItemType,
MedicalCheckupType,
MedicalVerdict,
OverexposureKind,
PrismaClient,
ProposedCategory,
QualificationCategory,
RiskExposureType,
SalaryType,
ScientificTitle,
Sex,
StudyLevel,
PostUniversityType,
StudyType,
TrainingType,
} from '@prisma/client';
const prisma = new PrismaClient();
function dbNameFromUrl(url: string): string {
return decodeURIComponent(new URL(url).pathname.replace(/^\//, ''));
}
function requireTemporaryDatabase() {
const url = process.env.DATABASE_URL;
if (!url) throw new Error('DATABASE_URL is required for test seed');
const dbName = dbNameFromUrl(url);
if (!dbName.startsWith('hrm_medpark_test_') && process.env.ALLOW_NON_TEST_DB !== 'true') {
throw new Error(`Refusing to seed non-test database "${dbName}". Expected hrm_medpark_test_*.`);
}
return dbName;
}
const d = (value: string) => new Date(`${value}T00:00:00.000Z`);
async function resetData() {
await prisma.auditLog.deleteMany();
await prisma.anexaTemplateVersion.deleteMany();
await prisma.anexaTemplate.deleteMany();
await prisma.radiationOverexposure.deleteMany();
await prisma.medicalCheckup.deleteMany();
await prisma.employeeMedicalProfile.deleteMany();
await prisma.workplaceRiskExposure.deleteMany();
await prisma.workplaceRiskCard.deleteMany();
await prisma.evaluationForm.deleteMany();
await prisma.evaluationCampaign.deleteMany();
await prisma.cimServiceCategory.deleteMany();
await prisma.employmentContract.deleteMany();
await prisma.benefit.deleteMany();
await prisma.disciplinarySanction.deleteMany();
await prisma.training.deleteMany();
await prisma.qualification.deleteMany();
await prisma.education.deleteMany();
await prisma.familyMember.deleteMany();
await prisma.identityDocument.deleteMany();
await prisma.employee.deleteMany();
await prisma.inventoryItem.deleteMany();
await prisma.department.deleteMany();
await prisma.workSchedule.deleteMany();
await prisma.taxExemption.deleteMany();
await prisma.disabilityGrade.deleteMany();
}
async function main() {
const dbName = requireTemporaryDatabase();
console.log(`Seeding Medpark test data into ${dbName}...`);
await resetData();
const disability = await prisma.disabilityGrade.create({
data: { code: 'TEST-GR-I', name: 'Grad dizabilitate I - test' },
});
const childTax = await prisma.taxExemption.create({
data: { code: 'TEST-SCUTIRE-COPIL', description: 'Scutire copil - test' },
});
const schedule = await prisma.workSchedule.create({
data: { name: 'Test 5/2 8h', daysWork: 5, daysRest: 2, hoursPerDay: 8 },
});
const shiftSchedule = await prisma.workSchedule.create({
data: { name: 'Test 12/24', daysWork: 1, daysRest: 1, hoursPerDay: 12 },
});
const root = await prisma.department.create({ data: { name: 'Medpark Test', code: 'TEST_ROOT' } });
const surgeryDept = await prisma.department.create({
data: { name: 'Chirurgie Test', code: 'TEST_CHIR', parentId: root.id },
});
const radiologyDept = await prisma.department.create({
data: { name: 'Radiologie Test', code: 'TEST_RAD', parentId: root.id },
});
const remoteDept = await prisma.department.create({
data: { name: 'Administrativ Digital Test', code: 'TEST_REMOTE', parentId: root.id },
});
const labDept = await prisma.department.create({
data: { name: 'Laborator Test', code: 'TEST_LAB', parentId: root.id },
});
const uniform = await prisma.inventoryItem.create({
data: { sku: 'TEST-UNIFORM-M', name: 'Uniformă test M', type: InventoryItemType.uniforma, size: 'M', color: 'teal', stockQty: 20 },
});
const coat = await prisma.inventoryItem.create({
data: { sku: 'TEST-HALAT-L', name: 'Halat test L', type: InventoryItemType.halat, size: 'L', color: 'alb', stockQty: 20 },
});
const shoes = await prisma.inventoryItem.create({
data: { sku: 'TEST-CIUPICI-40', name: 'Ciupici test 40', type: InventoryItemType.ciupici, size: '40', color: 'alb', stockQty: 20 },
});
const phone = await prisma.inventoryItem.create({
data: { sku: 'TEST-PHONE-A15', name: 'Telefon test Samsung A15', type: InventoryItemType.aparat_telefon, stockQty: 5 },
});
const commonEval = {
echipa: true,
oreZi: '8',
schimburi: '2',
schimbNoapte: true,
pauzeOrganizate: true,
riscInfectare: true,
riscElectrocutare: true,
riscTensiuneInalta: false,
riscInecare: false,
riscAsfixiere: false,
riscStrivire: true,
riscTaiere: true,
riscIntepare: true,
riscLovire: true,
riscMuscatura: false,
riscMicrotraumatisme: true,
conduceMasina: true,
conduceMasinaCategorie: 'B',
conduceUtilajeIntrauzinal: false,
spatiuL: '4',
spatiul: '5',
spatiuH: '3',
suprafataVerticala: false,
suprafataOrizontala: true,
suprafataOblica: false,
muncaIzolare: false,
muncaInaltime: true,
muncaInMiscare: true,
pozitieOrtostatica: true,
pozitieAsezat: false,
pozitieAplecata: true,
pozitieMixta: true,
pozitieFortata: false,
coloanaCervicala: true,
coloanaToracala: true,
coloanaLombara: true,
manipulareRidicare: true,
manipulareCoborare: true,
manipulareImpingere: true,
manipulareTragere: false,
manipularePurtare: true,
manipulareDeplasare: true,
greutateMaxima: '15 kg',
suprasolicitariVizuale: true,
suprasolicitariAuditive: true,
suprasolicitariNeuropsihice: true,
microclimatInterior: true,
microclimatExterior: false,
radiatiiCaloriceRece: false,
radiatiiCaloriceCalda: false,
iluminatSuficient: true,
iluminatInsuficient: false,
iluminatNatural: true,
iluminatArtificial: true,
iluminatMixt: true,
};
const surgeryCard = await prisma.workplaceRiskCard.create({
data: {
name: 'Test - Medic profil chirurgical cu gărzi de noapte',
riskFactors: { source: 'Control medical (5).docx', categories: ['chimici', 'biologici', 'fizici', 'ergonomici'] },
filiala: 'Sediul central',
adresaFiliala: 'str. Nicolae Testemițanu 29, Chișinău',
telefonFiliala: '+373 22 000 101',
caemPrimeleDouaCifre: '86',
cormSubgrupaMajora: 'Personal medical profil chirurgical',
directiaSectiaSectorul: 'Bloc operator / Chirurgie',
numarulLoculuiDeMunca: 'TEST-CHIR-01',
caemDiviziune: '86.10',
clasaConditiilorDeMunca: '3.2',
numarLucratoriPosibili: 12,
tipFisa: 'STANDARD',
evaluareDetalii: commonEval,
radiatiiIonizante: false,
mijloaceProtectieColectiva: 'Ventilație locală, containere pentru obiecte ascuțite',
mijloaceProtectieIndividuala: 'Mănuși, mască, halat steril, vizieră',
echipamentLucru: 'Uniformă chirurgicală',
anexeIgienicoSanitare: { vestiar: true, chiuveta: true, wc: true, dus: true, salaMese: true, recreere: true },
observatii: 'Set complet pentru testarea Anexa 4.',
exposures: {
create: [
{ tip: RiskExposureType.AGENT_CHIMIC, denumire: 'Glutaraldehidă', cas: '111-30-8', einecs: '203-856-5', timpExpunere: '2 h/zi', vep: '0,03 ppm', vlep: '0,1 ppm', caracteristici: 'iritant respirator' },
{ tip: RiskExposureType.PULBERI, denumire: 'Pulberi textile sterile', cas: '—', einecs: '—', timpExpunere: '1 h/zi', vep: '2 mg/m3', vlep: '5 mg/m3', caracteristici: 'pulberi inhalabile' },
{ tip: RiskExposureType.AGENT_BIOLOGIC, denumire: 'HBV/HCV/HIV', clasificare: 'grupa 3', caracteristici: 'risc prin înțepare/tăiere' },
{ tip: RiskExposureType.ZGOMOT, denumire: 'Echipamente bloc operator', timpExpunere: '4 h/zi', vep: '80 dB', vlep: '87 dB', caracteristici: 'zgomot intermitent' },
{ tip: RiskExposureType.VIBRATII, denumire: 'Instrumentar oscilant', zonaAfectata: 'mână-braț', timpExpunere: '30 min/zi', vep: '2,5 m/s2', vlep: '5 m/s2', caracteristici: 'vibrații locale' },
{ tip: RiskExposureType.CAMP_ELECTROMAGNETIC, denumire: 'Electrocauter', zonaAfectata: 'corp întreg', timpExpunere: '1 h/zi', vep: 'conform NU-10', vlep: 'conform NU-10', caracteristici: 'câmp EM local' },
{ tip: RiskExposureType.RADIATII_OPTICE, denumire: 'Lămpi chirurgicale', zonaAfectata: 'ochi', timpExpunere: '6 h/zi', vep: 'conform NU-10', vlep: 'conform NU-10', caracteristici: 'lumină intensă' },
],
},
},
});
const radiologyCard = await prisma.workplaceRiskCard.create({
data: {
name: 'Test - Radiologie cu radiații ionizante',
riskFactors: { source: 'Control medical (5).docx', categories: ['radiații ionizante', 'câmp electromagnetic'] },
filiala: 'Sediul central',
adresaFiliala: 'str. Nicolae Testemițanu 29, Chișinău',
telefonFiliala: '+373 22 000 102',
caemPrimeleDouaCifre: '86',
cormSubgrupaMajora: 'Personal imagistică medicală',
directiaSectiaSectorul: 'Diagnostic / Radiologie',
numarulLoculuiDeMunca: 'TEST-RAD-01',
caemDiviziune: '86.90',
clasaConditiilorDeMunca: '3.3',
numarLucratoriPosibili: 8,
tipFisa: 'STANDARD',
evaluareDetalii: { ...commonEval, riscInfectare: false, pozitieAsezat: true, pozitieOrtostatica: false },
radiatiiIonizante: true,
radiatiiGrupa: 'A',
radiatiiAparatura: 'CT, Rx digital',
radiatiiSurse: 'închise',
radiatiiTipExpunere: 'X externă',
radiatiiMasuriProtectie: 'Ecran de protecție, șorț plumb, dozimetru individual',
mijloaceProtectieColectiva: 'Ecrane plumbate și semnalizare zonă controlată',
mijloaceProtectieIndividuala: 'Șorț plumb, ochelari, dozimetru',
echipamentLucru: 'Uniformă radiologie',
anexeIgienicoSanitare: { vestiar: true, chiuveta: true, wc: true, dus: true, salaMese: true, recreere: false },
exposures: {
create: [
{ tip: RiskExposureType.CAMP_ELECTROMAGNETIC, denumire: 'Câmp electromagnetic RMN', zonaAfectata: 'corp întreg', timpExpunere: '4 h/zi', vep: 'conform NU-10', vlep: 'conform NU-10', caracteristici: 'câmp magnetic static intens' },
{ tip: RiskExposureType.ZGOMOT, denumire: 'Aparatură imagistică', timpExpunere: '3 h/zi', vep: '75 dB', vlep: '87 dB', caracteristici: 'zgomot tehnic' },
],
},
},
});
const remoteCard = await prisma.workplaceRiskCard.create({
data: {
name: 'Test - Activități administrative la distanță',
riskFactors: { source: 'Control medical (5).docx', categories: ['vizual', 'neuropsihic', 'platforme digitale'] },
filiala: 'Sediul central',
adresaFiliala: 'str. Nicolae Testemițanu 29, Chișinău',
telefonFiliala: '+373 22 000 103',
caemPrimeleDouaCifre: '86',
cormSubgrupaMajora: 'Personal administrativ',
directiaSectiaSectorul: 'Administrativ / Digital',
numarulLoculuiDeMunca: 'TEST-REMOTE-01',
caemDiviziune: '86.90',
clasaConditiilorDeMunca: '2',
numarLucratoriPosibili: 4,
tipFisa: 'DISTANTA_DIGITAL',
evaluareDetalii: {
echipa: false,
oreZi: '8',
schimburi: '1',
schimbNoapte: false,
pauzeOrganizate: true,
lucruMonitor: true,
platformeDigitale: true,
conduceMasina: false,
operatiuni: 'Operare HIS, e-mail, raportare digitală',
deplasari: true,
deplasariDescriere: 'Deplasări ocazionale la sediu',
manipulareRidicare: false,
manipulareCoborare: false,
manipulareImpingere: false,
manipulareTragere: false,
manipularePurtare: false,
manipulareDeplasare: false,
greutateMaxima: 'sub 3 kg',
suprasolicitariVizuale: true,
suprasolicitariAuditive: false,
suprasolicitariNeuropsihice: true,
alteRiscuri: 'Lucru prelungit la monitor',
},
radiatiiIonizante: false,
mijloaceProtectieIndividuala: 'Scaun ergonomic, monitor extern',
echipamentLucru: 'Laptop corporativ',
anexeIgienicoSanitare: { vestiar: false, chiuveta: true, wc: true, dus: false, salaMese: false, recreere: true },
observatii: 'Set pentru testarea Anexa 4A.',
},
});
const employees = await Promise.all([
prisma.employee.create({
data: {
idnp: '1985061500016',
nume: 'Popescu',
prenume: 'Alexandru',
patronimic: 'Ion',
dataNasterii: d('1985-06-15'),
domiciliu: 'mun. Chișinău, str. Ștefan cel Mare 1',
adresaReala: 'mun. Chișinău, str. Test 1',
telefonPersonal: '+37369100001',
telefonServiciu: '+37322100001',
emailPersonal: 'alexandru.popescu.test@example.com',
emailCorporativ: 'alexandru.popescu@medpark.test',
sex: Sex.M,
codCpas: 'CPAS-001',
stareCivila: 'casatorit',
titluStiintific: ScientificTitle.doctor,
status: EmployeeStatus.activ,
},
}),
prisma.employee.create({
data: {
idnp: '1990032200017',
nume: 'Ionescu',
prenume: 'Maria',
patronimic: 'Vasile',
dataNasterii: d('1990-03-22'),
domiciliu: 'mun. Chișinău, str. Mihai Viteazul 5',
telefonPersonal: '+37369100002',
telefonServiciu: '+37322100002',
emailCorporativ: 'maria.ionescu@medpark.test',
sex: Sex.F,
status: EmployeeStatus.activ,
gradDizabilitateId: disability.id,
},
}),
prisma.employee.create({
data: {
idnp: '1978110800016',
nume: 'Rusu',
prenume: 'Viorel',
dataNasterii: d('1978-11-08'),
domiciliu: 'mun. Chișinău, str. Alba Iulia 12',
telefonPersonal: '+37369100003',
emailCorporativ: 'viorel.rusu@medpark.test',
sex: Sex.M,
status: EmployeeStatus.activ,
},
}),
prisma.employee.create({
data: {
idnp: '2001091400010',
nume: 'Cojocaru',
prenume: 'Elena',
dataNasterii: d('2001-09-14'),
domiciliu: 'mun. Chișinău, str. Trandafirilor 3',
telefonPersonal: '+37369100004',
emailCorporativ: 'elena.cojocaru@medpark.test',
sex: Sex.F,
status: EmployeeStatus.activ,
},
}),
prisma.employee.create({
data: {
idnp: '1995120100019',
nume: 'Munteanu',
prenume: 'Ana',
dataNasterii: d('1995-12-01'),
domiciliu: 'mun. Chișinău, bd. Dacia 20',
telefonPersonal: '+37369100005',
emailCorporativ: 'ana.munteanu@medpark.test',
sex: Sex.F,
status: EmployeeStatus.activ,
},
}),
prisma.employee.create({
data: {
idnp: '1989020300012',
nume: 'Lungu',
prenume: 'Sergiu',
dataNasterii: d('1989-02-03'),
domiciliu: 'mun. Chișinău, str. Laboratorului 7',
telefonPersonal: '+37369100006',
emailCorporativ: 'sergiu.lungu@medpark.test',
sex: Sex.M,
status: EmployeeStatus.activ,
},
}),
]);
const [surgeon, nurse, radiologist, radiologyNurse, remoteAdmin, labDoctor] = employees;
await prisma.identityDocument.createMany({
data: employees.map((employee, index) => ({
employeeId: employee.id,
tipAct: DocumentType.buletin_de_identitate,
seria: `T${index + 1}`,
nr: `TESTDOC${index + 1}`,
dataEmiterii: d('2021-01-10'),
autoritateEmitenta: 'ASP Test',
dataExpirarii: d(`2031-01-${10 + index}`),
})),
});
await prisma.familyMember.createMany({
data: [
{ employeeId: surgeon.id, tip: FamilyMemberType.contact_principal, numePrenume: 'Popescu Elena', telefon: '+37368111111' },
{ employeeId: surgeon.id, tip: FamilyMemberType.copil, numePrenume: 'Popescu Andrei', dataNasterii: d('2015-05-20'), idnp: '2015052000015', tipScutireId: childTax.id },
{ employeeId: nurse.id, tip: FamilyMemberType.mama, numePrenume: 'Ionescu Tatiana', telefon: '+37368222222' },
],
});
await prisma.education.createMany({
data: [
{ employeeId: surgeon.id, tipStudii: StudyType.superioare, institutia: 'USMF Nicolae Testemițanu', specialitatea: 'Chirurgie', dataAbsolvirii: d('2008-06-30'), nrSeriaDiploma: 'DIP-TEST-001', dataEmiterii: d('2008-07-10'), nrInregistrare: 'REG-001', confirmare: DiplomaStatus.confirmata, nivel: StudyLevel.postuniversitar, tipPostuniversitar: PostUniversityType.rezidentiat },
{ employeeId: nurse.id, tipStudii: StudyType.medii_de_specialitate, institutia: 'Colegiul Național de Medicină', specialitatea: 'Nursing', dataAbsolvirii: d('2012-06-30'), nrSeriaDiploma: 'DIP-TEST-002', confirmare: DiplomaStatus.confirmata, nivel: StudyLevel.de_baza },
{ employeeId: radiologist.id, tipStudii: StudyType.superioare, institutia: 'USMF Nicolae Testemițanu', specialitatea: 'Radiologie', dataAbsolvirii: d('2002-06-30'), nrSeriaDiploma: 'DIP-TEST-003', confirmare: DiplomaStatus.confirmata, nivel: StudyLevel.postuniversitar, tipPostuniversitar: PostUniversityType.rezidentiat },
{ employeeId: radiologyNurse.id, tipStudii: StudyType.medii_de_specialitate, institutia: 'Colegiul Național de Medicină', specialitatea: 'Radiologie', dataAbsolvirii: d('2022-06-30'), nrSeriaDiploma: 'DIP-TEST-004', confirmare: DiplomaStatus.confirmata, nivel: StudyLevel.de_baza },
{ employeeId: remoteAdmin.id, tipStudii: StudyType.superioare, institutia: 'ASEM', specialitatea: 'Management', dataAbsolvirii: d('2017-06-30'), nrSeriaDiploma: 'DIP-TEST-005', confirmare: DiplomaStatus.confirmata, nivel: StudyLevel.de_baza },
{ employeeId: labDoctor.id, tipStudii: StudyType.superioare, institutia: 'USMF Nicolae Testemițanu', specialitatea: 'Medicină de laborator', dataAbsolvirii: d('2013-06-30'), nrSeriaDiploma: 'DIP-TEST-006', confirmare: DiplomaStatus.confirmata, nivel: StudyLevel.postuniversitar, tipPostuniversitar: PostUniversityType.rezidentiat },
],
});
await prisma.qualification.createMany({
data: [
{ employeeId: surgeon.id, categorie: QualificationCategory.superioara, dataObtinerii: d('2020-02-01'), dataUltimeiConfirmari: d('2024-02-01'), dataExpirarii: d('2029-02-01'), specialitate: 'Chirurgie' },
{ employeeId: nurse.id, categorie: QualificationCategory.cat_I, dataObtinerii: d('2021-03-01'), dataUltimeiConfirmari: d('2024-03-01'), dataExpirarii: d('2029-03-01'), specialitate: 'Nursing' },
{ employeeId: radiologist.id, categorie: QualificationCategory.superioara, dataObtinerii: d('2019-04-01'), dataUltimeiConfirmari: d('2024-04-01'), dataExpirarii: d('2029-04-01'), specialitate: 'Radiologie' },
{ employeeId: radiologyNurse.id, categorie: QualificationCategory.cat_II, dataObtinerii: d('2024-05-01'), dataUltimeiConfirmari: d('2024-05-01'), dataExpirarii: d('2029-05-01'), specialitate: 'Radiologie' },
],
});
await prisma.training.createMany({
data: employees.map((employee, index) => ({
employeeId: employee.id,
denumire: `Instruire Control medical test ${index + 1}`,
inceput: d('2026-01-10'),
sfirsit: d('2026-01-12'),
tip: index % 2 === 0 ? TrainingType.intern : TrainingType.extern_RM,
tara: 'Republica Moldova',
nrOre: 16,
organizatia: 'Medpark Academy Test',
certificat: true,
cost: '1000.00',
})),
});
await prisma.disciplinarySanction.createMany({
data: [
{ employeeId: nurse.id, tip: DisciplinarySanctionType.avertisment, dataAplicarii: d('2026-02-01'), dataExpirarii: d('2026-08-01') },
{ employeeId: remoteAdmin.id, tip: DisciplinarySanctionType.mustrare, dataAplicarii: d('2025-09-01'), dataExpirarii: d('2026-03-01'), isStinsa: true },
],
});
const contractRows = [
{ employee: surgeon, dept: surgeryDept, nr: 'TEST-CIM-001', role: 'Chirurg', corm: '221201', card: surgeryCard, schedule: shiftSchedule },
{ employee: nurse, dept: surgeryDept, nr: 'TEST-CIM-002', role: 'Asistentă medicală chirurgie', corm: '222101', card: surgeryCard, schedule: shiftSchedule },
{ employee: radiologist, dept: radiologyDept, nr: 'TEST-CIM-003', role: 'Medic radiolog', corm: '221203', card: radiologyCard, schedule },
{ employee: radiologyNurse, dept: radiologyDept, nr: 'TEST-CIM-004', role: 'Asistentă radiologie', corm: '222102', card: radiologyCard, schedule },
{ employee: remoteAdmin, dept: remoteDept, nr: 'TEST-CIM-005', role: 'Specialist documente digitale', corm: '242101', card: remoteCard, schedule },
{ employee: labDoctor, dept: labDept, nr: 'TEST-CIM-006', role: 'Medic laborator', corm: '221207', card: surgeryCard, schedule },
];
for (const row of contractRows) {
const contract = await prisma.employmentContract.create({
data: {
nrCim: row.nr,
employeeId: row.employee.id,
categorie: ContractCategory.principal,
dataSemnarii: d('2024-01-05'),
dataAngajarii: d('2024-01-15'),
perioada: ContractPeriod.nedeterminata,
functiaClasificator: row.corm,
codFunctie: row.corm,
functiaOrganigrama: row.role,
tipCim: ContractType.de_baza,
departmentId: row.dept.id,
regimMunca: 'normă întreagă',
tipSalarizare: SalaryType.fix,
salarizareDetails: { tip: 'fix', salariu: 15000 + contractRows.indexOf(row) * 500, zileConcediu: 28 },
clausaAditionala: { test: true, source: 'Rubrici necesare (6).xlsx / CIM' },
workScheduleId: row.schedule.id,
categoriiServicii: {
create: [
{ categorieId: `TEST-SERV-${contractRows.indexOf(row) + 1}`, tipRemunerare: 'tarif', sumaNeta: '250.00' },
],
},
},
});
await prisma.auditLog.create({
data: { userId: 'seed-test', userRole: 'hr_admin', action: 'CREATE', entity: 'EmploymentContract', entityId: contract.id },
});
}
await prisma.benefit.createMany({
data: [
{
employeeId: nurse.id,
uniformaId: uniform.id,
halatId: coat.id,
ciupiciId: shoes.id,
ticheteMasa: true,
valoareTichet: '70.00',
alimentatiePersonal: true,
abonamentTel: '150.00',
aparatTelefonId: phone.id,
cardCompanie: 'TEST-CARD-001',
},
{
employeeId: radiologyNurse.id,
uniformaId: uniform.id,
halatId: coat.id,
ticheteMasa: true,
valoareTichet: '70.00',
},
],
});
const profileByEmployeeId = new Map<string, string>();
for (const row of contractRows) {
const radiology = row.card.id === radiologyCard.id;
const profile = await prisma.employeeMedicalProfile.create({
data: {
employeeId: row.employee.id,
ocupatieCorm: `${row.role} (${row.corm})`,
workplaceRiskCardId: row.card.id,
dataUltimControlMedical: row.employee.id === surgeon.id ? null : d(row.employee.id === nurse.id ? '2025-02-01' : '2025-06-01'),
expusRadiatiiIonizante: radiology,
dataIntrarii: radiology ? d('2020-01-15') : null,
expunereAnterioaraPerioda: radiology ? '2017-2019' : null,
expunereAnterioaraAni: radiology ? 3 : null,
dozaCumulataExternaMsv: radiology ? '4.2500' : null,
dozaCumulataInternaMsv: radiology ? '0.8000' : null,
overexposures: radiology && row.employee.id === radiologist.id
? {
create: [
{ fel: OverexposureKind.EXCEPTIONALA, tipExpunere: 'X externă', data: d('2023-05-12'), dozaMsv: '2.5000' },
{ fel: OverexposureKind.ACCIDENTALA, tipExpunere: 'gamma externă', data: d('2024-09-03'), dozaMsv: '1.2000' },
],
}
: undefined,
},
});
profileByEmployeeId.set(row.employee.id, profile.id);
}
await prisma.medicalCheckup.createMany({
data: [
{ employeeId: surgeon.id, tip: MedicalCheckupType.la_angajare, dataPlanificata: d('2026-05-20') },
{ employeeId: nurse.id, tip: MedicalCheckupType.periodic, dataPlanificata: d('2026-05-28') },
{ employeeId: radiologist.id, tip: MedicalCheckupType.la_reluarea_activitatii, dataPlanificata: d('2026-05-29') },
{ employeeId: surgeon.id, tip: MedicalCheckupType.periodic, dataPlanificata: d('2025-05-20'), dataEfectuata: d('2025-05-20'), verdict: MedicalVerdict.apt, recomandari: 'Control anual', valabilPanaLa: d('2026-05-20'), semnatDe: 'Dr. Test Apt', documenteGenerate: [{ name: 'Anexa_6_Final_Apt', url: 's3://test/anexa6_apt.docx', type: 'ANEXA_6' }] },
{ employeeId: nurse.id, tip: MedicalCheckupType.periodic, dataPlanificata: d('2025-04-20'), dataEfectuata: d('2025-04-20'), verdict: MedicalVerdict.apt_perioada_adaptare, recomandari: 'Adaptare 30 zile', valabilPanaLa: d('2026-04-20'), semnatDe: 'Dr. Test Adaptare', documenteGenerate: [{ name: 'Anexa_6_Final_Adaptare', url: 's3://test/anexa6_adaptare.docx', type: 'ANEXA_6' }] },
{ employeeId: radiologist.id, tip: MedicalCheckupType.periodic, dataPlanificata: d('2025-03-20'), dataEfectuata: d('2025-03-20'), verdict: MedicalVerdict.apt_conditionat, recomandari: 'Dozimetru obligatoriu', valabilPanaLa: d('2026-03-20'), semnatDe: 'Dr. Test Conditionat', documenteGenerate: [{ name: 'Anexa_6_Final_Conditionat', url: 's3://test/anexa6_conditionat.docx', type: 'ANEXA_6' }] },
{ employeeId: radiologyNurse.id, tip: MedicalCheckupType.suplimentar, dataPlanificata: d('2025-02-20'), dataEfectuata: d('2025-02-20'), verdict: MedicalVerdict.inapt_temporar, recomandari: 'Reevaluare peste 30 zile', valabilPanaLa: d('2025-03-20'), semnatDe: 'Dr. Test Temporar', documenteGenerate: [{ name: 'Anexa_6_Final_Temporar', url: 's3://test/anexa6_temporar.docx', type: 'ANEXA_6' }] },
{ employeeId: remoteAdmin.id, tip: MedicalCheckupType.periodic, dataPlanificata: d('2025-01-20'), dataEfectuata: d('2025-01-20'), verdict: MedicalVerdict.inapt, recomandari: 'Inapt pentru postul curent', valabilPanaLa: d('2025-02-20'), semnatDe: 'Dr. Test Inapt', documenteGenerate: [{ name: 'Anexa_6_Final_Inapt', url: 's3://test/anexa6_inapt.docx', type: 'ANEXA_6' }] },
],
});
const campaign = await prisma.evaluationCampaign.create({
data: {
name: 'Test evaluare anuală nursing - Chirurgie 2026',
departmentId: surgeryDept.id,
month: d('2026-05-01'),
status: CampaignStatus.in_progress,
},
});
await prisma.evaluationForm.createMany({
data: [
{
campaignId: campaign.id,
employeeId: nurse.id,
abilitatiClinice: EvaluationScore.bine,
judecataClinica: EvaluationScore.bine,
manopere: EvaluationScore.bine,
gestionareaSarcinilor: EvaluationScore.mediu,
constiintaProfesionala: EvaluationScore.bine,
atitudineaPacienti: EvaluationScore.bine,
atitudineaColegi: EvaluationScore.bine,
atitudineaPersonalNonMed: EvaluationScore.mediu,
utilizareSmartphone: EvaluationScore.bine,
respectareaProgramului: EvaluationScore.bine,
respectareaDressCode: EvaluationScore.bine,
testJci: { score: 18, max_score: 20, percent: 90, source: 'academy_ocean_test' },
completareaDocMed: true,
perfectioneazaCunostinte: true,
membruComitetCalitate: true,
functieDeMonitor: false,
inlocuiesteSuperiorul: false,
categorieCalculata: ProposedCategory.superioara,
},
{
campaignId: campaign.id,
employeeId: surgeon.id,
abilitatiClinice: EvaluationScore.mediu,
judecataClinica: EvaluationScore.mediu,
manopere: EvaluationScore.bine,
categorieCalculata: ProposedCategory.fara,
},
],
});
const closedCampaign = await prisma.evaluationCampaign.create({
data: {
name: 'Test evaluare nursing - Radiologie 2025',
departmentId: radiologyDept.id,
month: d('2025-11-01'),
status: CampaignStatus.closed,
},
});
await prisma.evaluationForm.create({
data: {
campaignId: closedCampaign.id,
employeeId: radiologyNurse.id,
abilitatiClinice: EvaluationScore.bine,
judecataClinica: EvaluationScore.bine,
manopere: EvaluationScore.bine,
gestionareaSarcinilor: EvaluationScore.bine,
constiintaProfesionala: EvaluationScore.bine,
atitudineaPacienti: EvaluationScore.mediu,
atitudineaColegi: EvaluationScore.bine,
atitudineaPersonalNonMed: EvaluationScore.bine,
utilizareSmartphone: EvaluationScore.bine,
respectareaProgramului: EvaluationScore.bine,
respectareaDressCode: EvaluationScore.mediu,
completareaDocMed: true,
perfectioneazaCunostinte: true,
membruComitetCalitate: false,
functieDeMonitor: false,
inlocuiesteSuperiorul: false,
categorieCalculata: ProposedCategory.cat_I,
categorieAprobata: ProposedCategory.cat_I,
observatii: 'Formular închis pentru test read-only.',
completedAt: d('2025-11-20'),
},
});
for (const type of [AnexaType.ANEXA_3, AnexaType.ANEXA_4, AnexaType.ANEXA_4A, AnexaType.ANEXA_4B, AnexaType.ANEXA_6]) {
await prisma.anexaTemplate.create({
data: {
type,
name: `Test ${type}`,
contentJson: { source: 'templates/docx', note: 'DOCX template is stored on disk' },
updatedById: 'seed-test',
},
});
}
console.log('Seed summary:');
console.log(` employees=${await prisma.employee.count()}`);
console.log(` workplaceRiskCards=${await prisma.workplaceRiskCard.count()}`);
console.log(` riskExposures=${await prisma.workplaceRiskExposure.count()}`);
console.log(` medicalCheckups=${await prisma.medicalCheckup.count()}`);
console.log(` evaluationForms=${await prisma.evaluationForm.count()}`);
console.log(` profiles=${profileByEmployeeId.size}`);
}
main()
.catch((error: unknown) => {
console.error(error);
process.exitCode = 1;
})
.finally(async () => {
await prisma.$disconnect();
});