(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é à l’arrivé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 d’entré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, ]); } }