Globinours/app/Services/DemoDataService.php

536 lines
21 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
final class DemoDataService
{
private const TABLES = [
'agenda_volunteers',
'agenda_items',
'prescription_treatments',
'lab_results',
'medical_prescriptions',
'lab_reports',
'treatment_administrations',
'care_round_observations',
'care_rounds',
'medical_photos',
'animal_photos',
'animal_expenses',
'animal_surgeries',
'animal_health_conditions',
'dewormings',
'vaccinations',
'treatments',
'medical_notes',
'measurements',
'animal_placements',
'adoptions',
'animal_movements',
'animal_deaths',
'animal_location_history',
'animal_history',
'litter_kittens',
'litters',
'bonded_group_members',
'bonded_groups',
'icad_cache',
'asm3_import_links',
'asm3_import_runs',
'asm3_import_jobs',
'directory_contact_roles',
'animals',
'directory_contacts',
'grant_documents',
'grant_applications',
'grant_years',
'care_room_layouts',
'clinics',
'geocode_cache',
'audit_log',
];
public static function reset(PDO $db): array
{
$before = [
'animals' => (int) $db->query('SELECT COUNT(*) FROM animals')->fetchColumn(),
'contacts' => (int) $db->query('SELECT COUNT(*) FROM directory_contacts')->fetchColumn(),
];
$sequence = $db->prepare('DELETE FROM sqlite_sequence WHERE name=?');
$exists = $db->prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?");
foreach (self::TABLES as $table) {
$exists->execute([$table]);
if (!$exists->fetchColumn()) {
continue;
}
$db->exec('DELETE FROM ' . $table);
$sequence->execute([$table]);
}
return $before;
}
public static function seed(PDO $db, ?int $userId): array
{
$contacts = [
'fa' => [
'person',
'Alice Martin',
'06 00 00 00 01',
'alice.demo@example.org',
'12 rue des Lilas',
'29260',
'Lesneven',
],
'adopter' => [
'person',
'Marc Durand',
'06 00 00 00 02',
'marc.demo@example.org',
'8 rue du Port',
'29200',
'Brest',
],
'depositor' => [
'person',
'Sophie Le Gall',
'06 00 00 00 03',
'sophie.demo@example.org',
'4 place du Marché',
'29000',
'Ville fictive',
],
'vet' => [
'person',
'Dr Camille Morel',
'02 00 00 00 04',
'veterinaire.demo@example.org',
'2 avenue des Chats',
'29260',
'Lesneven',
],
'clinic' => [
'organization',
'Clinique vétérinaire Démo',
'02 00 00 00 05',
'clinique.demo@example.org',
'2 avenue des Chats',
'29260',
'Lesneven',
],
'crematorium' => [
'organization',
'Crématorium animalier Démo',
'02 00 00 00 06',
'crematorium.demo@example.org',
'1 route du Souvenir',
'29400',
'Landivisiau',
],
];
$contactIds = [];
$insert = $db->prepare(
'INSERT INTO directory_contacts(kind,name,phone,email,address,postal_code,city,notes) VALUES(?,?,?,?,?,?,?,?)',
);
$role = $db->prepare('INSERT INTO directory_contact_roles(contact_id,role) VALUES(?,?)');
foreach ($contacts as $key => $c) {
$insert->execute([...$c, 'Donnée fictive de démonstration']);
$contactIds[$key] = (int) $db->lastInsertId();
$roleName = match ($key) {
'adopter' => 'adoptant',
'vet' => 'veterinaire',
'clinic' => 'cabinet',
'crematorium' => 'crematorium',
'depositor' => 'deposant',
default => 'fa',
};
$role->execute([$contactIds[$key], $roleName]);
}
$animals = [
[
'DEMO-001',
'Moka',
'F',
'2019-05-14',
'refuge',
'silver',
'Bicolore Noir / Blanc',
'yes',
'yes',
'yes',
'yes',
'yes',
'available',
],
[
'DEMO-002',
'Pixel',
'M',
'2021-09-03',
'refuge',
'twix',
'Roux',
'yes',
'yes',
'yes',
'yes',
'no',
'available',
],
[
'DEMO-003',
'Twix',
'M',
'2019-04-15',
'quarantaine',
null,
'Roux',
'yes',
'yes',
'yes',
'yes',
'yes',
'not_available',
],
[
'DEMO-004',
'Nox',
'M',
'2023-02-18',
'soin',
null,
'Noir',
'no',
'yes',
'unknown',
'yes',
'no',
'not_available',
],
[
'DEMO-005',
'Caramel',
'F',
'2020-07-21',
'fa',
null,
'Écaille de tortue',
'yes',
'yes',
'yes',
'yes',
'yes',
'available',
],
[
'DEMO-006',
'Plume',
'F',
'2022-04-08',
'refuge',
'silver',
'Tricolore / Calico',
'yes',
'yes',
'yes',
'yes',
'yes',
'available',
],
[
'DEMO-007',
'Plume-Bébé-1',
'F',
date('Y-m-d', strtotime('-4 months')),
'refuge',
'silver',
'Bicolore Gris / Blanc',
'unknown',
'yes',
'unknown',
'unknown',
'unknown',
'not_available',
],
[
'DEMO-008',
'Plume-Bébé-2',
'M',
date('Y-m-d', strtotime('-4 months')),
'refuge',
'silver',
'Gris',
'unknown',
'yes',
'unknown',
'unknown',
'unknown',
'not_available',
],
[
'DEMO-009',
'Plume-Bébé-3',
'U',
date('Y-m-d', strtotime('-4 months')),
'refuge',
'silver',
'Tigré / Tabby',
'unknown',
'yes',
'unknown',
'unknown',
'unknown',
'not_available',
],
[
'DEMO-010',
'Lune',
'F',
'2021-01-12',
'refuge',
'twix',
'Blanc',
'yes',
'no',
'yes',
'yes',
'yes',
'available',
],
[
'DEMO-011',
'Soleil',
'M',
'2021-01-12',
'refuge',
'twix',
'Roux',
'yes',
'no',
'yes',
'yes',
'yes',
'available',
],
[
'DEMO-012',
'Étoile',
'F',
'2012-06-01',
'decede',
null,
'Noir',
'yes',
'unknown',
'unknown',
'unknown',
'unknown',
'not_available',
],
];
$animalIds = [];
$animal = $db->prepare(
"INSERT INTO animals(internal_code,name,species,sex,birth_date,status,refuge_room,care_box_key,color,sterilized,sterilization_status,compatibility_cats,compatibility_dogs,compatibility_children,house_trained,adoption_availability,intake_date,intake_type,intake_reason,rescue_location_name,current_address,chip_id,identification_type,identification_registration_status,archived_at,notes) VALUES(:code,:name,'chat',:sex,:birth,:status,:room,:box,:color,:sterilized,:sterilization,:cats,:dogs,:children,:clean,:availability,date('now','-'||:days||' days'),'found','stray_found','Commune fictive','5 rue de la Démonstration, 29260 Lesneven',:chip,:identification,:registration,:archived,'Donnée fictive de démonstration')",
);
foreach ($animals as $i => $a) {
[
$code,
$name,
$sex,
$birth,
$status,
$room,
$color,
$sterilization,
$cats,
$dogs,
$children,
$clean,
$availability,
] = $a;
$sterilized = $sterilization === 'yes' ? 1 : 0;
$chip = $i < 6 ? '250269900' . str_pad((string) ($i + 1), 6, '0', STR_PAD_LEFT) : null;
$animal->execute([
':code' => $code,
':name' => $name,
':sex' => $sex,
':birth' => $birth,
':status' => $status,
':room' => $room,
':box' => $status === 'soin' ? 'care-top-1' : null,
':color' => $color,
':sterilized' => $sterilized,
':sterilization' => $sterilization,
':cats' => $cats,
':dogs' => $dogs,
':children' => $children,
':clean' => $clean,
':availability' => $availability,
':days' => 90 + $i * 12,
':chip' => $chip,
':identification' => $chip ? 'microchip' : 'unknown',
':registration' => $chip ? 'registered' : 'unknown',
':archived' => $status === 'decede' ? date('Y-m-d H:i:s') : null,
]);
$animalIds[$name] = (int) $db->lastInsertId();
}
$db->prepare('INSERT INTO litters(mother_id,birth_date,notes) VALUES(?,?,?)')->execute([
$animalIds['Plume'],
$animals[6][3],
'Portée fictive de démonstration',
]);
$litter = (int) $db->lastInsertId();
$link = $db->prepare('INSERT INTO litter_kittens(litter_id,animal_id,position) VALUES(?,?,?)');
foreach (['Plume-Bébé-1', 'Plume-Bébé-2', 'Plume-Bébé-3'] as $i => $name) {
$link->execute([$litter, $animalIds[$name], $i + 1]);
}
$db->prepare('INSERT INTO bonded_groups(name,notes) VALUES(?,?)')->execute([
'Duo Lune & Soleil',
'Chats fictifs à adopter ensemble',
]);
$group = (int) $db->lastInsertId();
$member = $db->prepare('INSERT INTO bonded_group_members(group_id,animal_id,position) VALUES(?,?,?)');
$member->execute([$group, $animalIds['Lune'], 1]);
$member->execute([$group, $animalIds['Soleil'], 2]);
$twix = $animalIds['Twix'];
$db->prepare(
"UPDATE animals SET breed='Européen',birth_is_estimated=0,fiv=0,felv=0,quarantine_until=date('now','+10 days'),intake_circumstances='Trouvé seul, bilan sanitaire programmé à larrivée.',depositor_contact_id=?,rescue_location_name='Commune fictive',current_address='Quarantaine — box supérieur gauche',identification_date=date('now','-2 years'),notes='Fiche vitrine entièrement fictive : elle illustre un dossier animal complet.' WHERE id=?",
)->execute([$contactIds['depositor'], $twix]);
$db->prepare(
"INSERT OR IGNORE INTO ref_medications(name,molecule,form,notes) VALUES('Doxybactin','doxycycline','comprimé','Référence de démonstration')",
)->execute();
$med = (int) $db->query("SELECT id FROM ref_medications WHERE name='Doxybactin'")->fetchColumn();
$db->prepare(
"INSERT INTO treatments(animal_id,medication_id,route,dose_text,start_date,end_date,ongoing,notes,created_by,give_morning,give_evening) VALUES(?,?,'PO','1/2 comprimé matin et soir',date('now','-2 days'),date('now','+5 days'),1,'Traitement fictif de démonstration',?,1,1)",
)->execute([$twix, $med, $userId]);
$db->prepare(
"INSERT INTO medical_notes(animal_id,noted_at,kind,reason,symptoms,exam,diagnosis,plan,weight_kg,temperature_c,created_by,vet_contact_id,clinic_contact_id) VALUES(?,datetime('now','-1 day'),'consult','Visite sanitaire dentrée','Éternuements occasionnels','État général satisfaisant, auscultation sans anomalie','Coryza léger','Surveillance, traitement court et contrôle avant sortie de quarantaine',4.8,38.4,?,?,?)",
)->execute([$twix, $userId, $contactIds['vet'], $contactIds['clinic']]);
$weight = $db->prepare(
"INSERT INTO measurements(animal_id,type,value,unit,measured_at,notes,created_by) VALUES(?,'weight',?,'kg',datetime('now',?),'Mesure fictive',?)",
);
foreach ([[4.6, '-30 days'], [4.7, '-14 days'], [4.8, '-1 day']] as $w) {
$weight->execute([$twix, $w[0], $w[1], $userId]);
}
$db->prepare(
"INSERT OR IGNORE INTO ref_vaccines(name,notes) VALUES('TCL','Vaccin de démonstration')",
)->execute();
$vaccine = (int) $db->query("SELECT id FROM ref_vaccines WHERE name='TCL'")->fetchColumn();
$db->prepare(
"INSERT INTO vaccinations(animal_id,vaccine_id,done_date,due_date,lot,manufacturer,notes,created_by,vet_contact_id,clinic_contact_id) VALUES(?,?,date('now','-11 months'),date('now','+1 month'),'LOT-DEMO-1','Laboratoire Démo','Vaccination fictive à jour',?,?,?)",
)->execute([$twix, $vaccine, $userId, $contactIds['vet'], $contactIds['clinic']]);
$dewormer = (int) $db->query('SELECT id FROM ref_dewormers ORDER BY id LIMIT 1')->fetchColumn();
$db->prepare(
"INSERT INTO dewormings(animal_id,dewormer_id,administered_on,dose_text,weight_kg,next_due_date,notes,created_by) VALUES(?,?,date('now','-10 days'),'1 pipette',4.7,date('now','+80 days'),'Administration fictive',?)",
)->execute([$twix, $dewormer, $userId]);
$db->prepare(
"INSERT INTO animal_health_conditions(animal_id,name,status,diagnosed_at,resolved_at,notes) VALUES(?,'Gingivite légère','resolved',date('now','-6 months'),date('now','-5 months'),'Antécédent fictif résolu')",
)->execute([$twix]);
$db->prepare(
"INSERT INTO lab_reports(animal_id,sampled_on,report_type,laboratory_name,veterinarian_contact_id,clinic_contact_id,notes,created_by) VALUES(?,date('now','-1 day'),'Bilan complet','Laboratoire Démo',?,?,'Prise de sang fictive — valeurs dans les intervalles usuels',?)",
)->execute([$twix, $contactIds['vet'], $contactIds['clinic'], $userId]);
$report = (int) $db->lastInsertId();
$result = $db->prepare(
'INSERT INTO lab_results(report_id,parameter_name,value,unit,reference_min,reference_max,notes,position) VALUES(?,?,?,?,?,?,?,?)',
);
foreach (
[
['Leucocytes', 8.4, '10⁹/L', 3.5, 20.7, 10],
['Érythrocytes', 9.6, '10¹²/L', 7.7, 12.8, 20],
['Hémoglobine', 13.8, 'g/dL', 10, 17, 30],
['Hématocrite', 42.1, '%', 33.7, 55.4, 40],
['Plaquettes', 312, '10⁹/L', 125, 618, 50],
['Créatinine', 12, 'mg/L', 3, 21, 60],
['Urée', 0.42, 'g/L', 0.214, 0.642, 70],
]
as $r
) {
$result->execute([$report, $r[0], $r[1], $r[2], $r[3], $r[4], 'Résultat fictif', $r[5]]);
}
$db->prepare(
"INSERT INTO animal_photos(animal_id,filename,original_name,mime,size_bytes,is_primary,is_public,caption) VALUES(?,'twix.webp','twix.jpg','image/webp',0,1,1,'Twix — photographie de démonstration')",
)->execute([$twix]);
$db->prepare(
"INSERT INTO agenda_items(item_type,title,description,starts_at,ends_at,location,status,priority,animal_id,contact_id,reminder_minutes,created_by) VALUES('veterinary','Contrôle de sortie de quarantaine','Rendez-vous fictif : contrôle clinique et validation de la sortie.',datetime('now','+7 days','09:00'),datetime('now','+7 days','09:30'),'Clinique vétérinaire Démo','planned','high',?,?,60,?)",
)->execute([$twix, $contactIds['clinic'], $userId]);
$db->prepare(
"INSERT INTO animal_placements(animal_id,event_type,event_date,contact_id,reason,notes,created_by) VALUES(?,'foster',date('now','-30 days'),?,'Placement de démonstration','Donnée fictive',?)",
)->execute([$animalIds['Caramel'], $contactIds['fa'], $userId]);
$db->prepare(
"INSERT INTO animal_deaths(animal_id,deceased_date,cause_code,cause_details,occurred_in_care,place_type,euthanized,veterinarian_contact_id,crematorium_contact_id,body_disposition,created_by) VALUES(?,date('now','-60 days'),'old_age','Décès fictif',1,'veterinaire',1,?,?,'collective_cremation',?)",
)->execute([$animalIds['Étoile'], $contactIds['vet'], $contactIds['crematorium'], $userId]);
$history = $db->prepare(
"INSERT INTO animal_history(animal_id,action,field,new_value,user_id,created_at) VALUES(?,'created','demo','Donnée entièrement fictive',?,datetime('now'))",
);
foreach ($animalIds as $id) {
$history->execute([$id, $userId]);
}
return [
'animals' => count($animalIds),
'contacts' => count($contactIds),
'litters' => 1,
'bonded_groups' => 1,
'treatments' => 1,
'vaccinations' => 1,
'lab_reports' => 1,
'agenda_items' => 1,
'photos' => 1,
];
}
public static function clearFiles(): void
{
foreach (
[
dirname(__DIR__, 2) . '/public/media/animals',
dirname(__DIR__, 2) . '/data/grants',
dirname(__DIR__, 2) . '/data/medical-documents',
]
as $root
) {
if (!is_dir($root)) {
continue;
}
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST,
);
foreach ($it as $file) {
$path = $file->getPathname();
if ($file->isLink() || $file->isFile()) {
@unlink($path);
} elseif ($file->isDir()) {
@rmdir($path);
}
}
}
}
public static function installFiles(PDO $db): void
{
$animalId = (int) $db->query("SELECT id FROM animals WHERE internal_code='DEMO-003' LIMIT 1")->fetchColumn();
if ($animalId <= 0) {
return;
}
$source = dirname(__DIR__, 2) . '/resources/demo/twix.webp';
$directory = dirname(__DIR__, 2) . '/public/media/animals/' . $animalId;
$target = $directory . '/twix.webp';
if (!is_file($source)) {
throw new RuntimeException(t('service.image.invalid_upload'));
}
if (!is_dir($directory) && !mkdir($directory, 0755, true) && !is_dir($directory)) {
throw new RuntimeException(t('service.image.directory_failed'));
}
if (!copy($source, $target)) {
throw new RuntimeException(t('service.image.save_failed'));
}
@chmod($target, 0644);
$db->prepare("UPDATE animal_photos SET size_bytes=? WHERE animal_id=? AND filename='twix.webp'")->execute([
filesize($target),
$animalId,
]);
}
}