Globinours/app/Controllers/AnimalMedicalActions.php

706 lines
28 KiB
PHP
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. 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);
trait AnimalMedicalActions
{
public static function updateMedicalStatus(): void
{
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
http_response_code(405);
return;
}
$animalId = (int) ($_POST['animal_id'] ?? 0);
if ($animalId <= 0) {
http_response_code(400);
return;
}
$allowedTestStatuses = ['unknown', 'neg', 'pos', 'doubtful'];
$fivStatus = (string) ($_POST['fiv_status'] ?? 'unknown');
$felvStatus = (string) ($_POST['felv_status'] ?? 'unknown');
if (!in_array($fivStatus, $allowedTestStatuses, true)) {
$fivStatus = 'unknown';
}
if (!in_array($felvStatus, $allowedTestStatuses, true)) {
$felvStatus = 'unknown';
}
$testDate = trim((string) ($_POST['test_date'] ?? date('Y-m-d')));
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $testDate)) {
$testDate = date('Y-m-d');
}
$testNotes = trim((string) ($_POST['test_notes'] ?? ''));
$conditions = is_array($_POST['conditions'] ?? null) ? $_POST['conditions'] : [];
$db = DB::pdo();
$animalStmt = $db->prepare('SELECT fiv, felv, fiv_status, felv_status FROM animals WHERE id = :id');
$animalStmt->execute([':id' => $animalId]);
$old = $animalStmt->fetch(PDO::FETCH_ASSOC);
if (!$old) {
http_response_code(404);
return;
}
$oldFivStatus = (string) ($old['fiv_status'] ?: ((int) $old['fiv'] === 1 ? 'pos' : 'neg'));
$oldFelvStatus = (string) ($old['felv_status'] ?: ((int) $old['felv'] === 1 ? 'pos' : 'neg'));
$db->beginTransaction();
try {
$db->prepare(
"
UPDATE animals
SET fiv_status = :fiv_status,
felv_status = :felv_status,
fiv = :fiv,
felv = :felv,
updated_at = datetime('now')
WHERE id = :id
",
)->execute([
':fiv_status' => $fivStatus,
':felv_status' => $felvStatus,
':fiv' => $fivStatus === 'pos' ? 1 : 0,
':felv' => $felvStatus === 'pos' ? 1 : 0,
':id' => $animalId,
]);
$noteStmt = $db->prepare("
INSERT INTO medical_notes
(animal_id, noted_at, kind, reason, diagnosis, plan, created_at)
VALUES
(:animal_id, :noted_at, 'diagnostic', :reason, :diagnosis, :plan, datetime('now'))
");
foreach (
[
['label' => 'FIV', 'old' => $oldFivStatus, 'new' => $fivStatus],
['label' => 'FeLV', 'old' => $oldFelvStatus, 'new' => $felvStatus],
]
as $test
) {
if ($test['new'] === 'pos' && $test['old'] !== 'pos') {
$diagnosis = $test['label'] . ' positif';
$noteStmt->execute([
':animal_id' => $animalId,
':noted_at' => $testDate . ' 12:00:00',
':reason' => 'Résultat de test ' . $test['label'],
':diagnosis' => $diagnosis,
':plan' => $testNotes !== '' ? $testNotes : null,
]);
self::logHistory(
$animalId,
'medical',
$diagnosis,
'Test positif le ' . $testDate . ($testNotes !== '' ? "\n" . $testNotes : ''),
);
}
}
$conditionSelect = $db->prepare(
'SELECT status FROM animal_health_conditions WHERE id = :id AND animal_id = :animal_id',
);
$conditionUpdate = $db->prepare("
UPDATE animal_health_conditions
SET name = :name, status = :status, diagnosed_at = :diagnosed_at,
resolved_at = :resolved_at, notes = :notes, updated_at = datetime('now')
WHERE id = :id AND animal_id = :animal_id
");
$conditionInsert = $db->prepare('
INSERT INTO animal_health_conditions
(animal_id, name, status, diagnosed_at, resolved_at, notes)
VALUES
(:animal_id, :name, :status, :diagnosed_at, :resolved_at, :notes)
');
foreach ($conditions as $key => $condition) {
if (!is_array($condition)) {
continue;
}
$name = trim((string) ($condition['name'] ?? ''));
if ($name === '') {
continue;
}
$status = ($condition['status'] ?? 'active') === 'resolved' ? 'resolved' : 'active';
$diagnosedAt = trim((string) ($condition['diagnosed_at'] ?? '')) ?: null;
$notes = trim((string) ($condition['notes'] ?? '')) ?: null;
$conditionId = ctype_digit((string) $key) ? (int) $key : 0;
$previousStatus = null;
if ($conditionId > 0) {
$conditionSelect->execute([':id' => $conditionId, ':animal_id' => $animalId]);
$previousStatus = $conditionSelect->fetchColumn();
if ($previousStatus === false) {
continue;
}
$conditionUpdate->execute([
':name' => $name,
':status' => $status,
':diagnosed_at' => $diagnosedAt,
':resolved_at' => $status === 'resolved' ? date('Y-m-d') : null,
':notes' => $notes,
':id' => $conditionId,
':animal_id' => $animalId,
]);
} else {
$conditionInsert->execute([
':animal_id' => $animalId,
':name' => $name,
':status' => $status,
':diagnosed_at' => $diagnosedAt,
':resolved_at' => $status === 'resolved' ? date('Y-m-d') : null,
':notes' => $notes,
]);
}
if ($status === 'active' && $previousStatus !== 'active') {
$noteStmt->execute([
':animal_id' => $animalId,
':noted_at' => ($diagnosedAt ?: date('Y-m-d')) . ' 12:00:00',
':reason' => 'Statut médical global',
':diagnosis' => $name,
':plan' => $notes,
]);
self::logHistory(
$animalId,
'medical',
'Pathologie / vigilance ajoutée',
$name . ($notes ? "\n" . $notes : ''),
);
}
}
$changes = [];
if ($oldFivStatus !== $fivStatus) {
$changes[] = 'FIV : ' . $oldFivStatus . ' → ' . $fivStatus;
}
if ($oldFelvStatus !== $felvStatus) {
$changes[] = 'FeLV : ' . $oldFelvStatus . ' → ' . $felvStatus;
}
if ($changes) {
self::logHistory($animalId, 'medical', 'Statut médical mis à jour', implode("\n", $changes));
}
$db->commit();
} catch (Throwable $e) {
$db->rollBack();
throw $e;
}
header('Location: /animal?id=' . $animalId . '#tab-med');
exit();
}
public static function addMedical(): void
{
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
return;
}
$animalId = (int) ($_POST['animal_id'] ?? 0);
if ($animalId <= 0) {
http_response_code(400);
return;
}
$kind = trim($_POST['kind'] ?? 'consult');
$reason = trim($_POST['reason'] ?? '');
$symptoms = trim($_POST['symptoms'] ?? '');
$exam = trim($_POST['exam'] ?? '');
$diagnosis = trim($_POST['diagnosis'] ?? '');
$plan = trim($_POST['plan'] ?? '');
$markSterilized = !empty($_POST['mark_sterilized']);
if ($markSterilized) {
$kind = 'acte';
if ($reason === '') {
$reason = 'Stérilisation';
}
}
$temperature = $_POST['temperature_c'] ?? null;
$weight = $_POST['weight_kg'] ?? null;
$clinicId = (int) ($_POST['clinic_id'] ?? 0);
$clinicId = $clinicId > 0 ? $clinicId : null;
$db = DB::pdo();
$clinicContact = self::resolveDirectoryContact(
$db,
(int) ($_POST['clinic_contact_id'] ?? 0),
(string) ($_POST['new_clinic_name'] ?? ''),
'organization',
'cabinet',
);
$vetContact = self::resolveDirectoryContact(
$db,
(int) ($_POST['vet_contact_id'] ?? 0),
(string) ($_POST['new_vet_name'] ?? ''),
'person',
'veterinaire',
);
self::normalizeVeterinaryClinic($db, $vetContact, $clinicContact);
if (!$vetContact || !$clinicContact) {
http_response_code(400);
echo h(t('error.vet_clinic_required'));
return;
}
$vetName = $vetContact['name'] ?? null;
// 1⃣ Insertion note médicale
$stmt = $db->prepare('
INSERT INTO medical_notes
(animal_id, kind, reason, symptoms, exam, diagnosis, plan, temperature_c, weight_kg, clinic_id, vet_name, clinic_contact_id, vet_contact_id, created_by, created_at)
VALUES
(:aid, :kind, :reason, :symptoms, :exam, :diagnosis, :plan, :temp, :weight, :clinic, :vet, :clinic_contact, :vet_contact, :created_by, :created)
');
$stmt->execute([
':aid' => $animalId,
':kind' => $kind,
':reason' => $reason,
':symptoms' => $symptoms,
':exam' => $exam,
':diagnosis' => $diagnosis,
':plan' => $plan,
':temp' => $temperature !== '' ? (float) $temperature : null,
':weight' => $weight !== '' ? (float) $weight : null,
':clinic' => $clinicId,
':vet' => $vetName,
':clinic_contact' => $clinicContact['id'] ?? null,
':vet_contact' => $vetContact['id'] ?? null,
':created_by' => Auth::id(),
':created' => self::now(),
]);
// 👉 RÉCUPÉRATION ID NOTE
$medicalNoteId = $db->lastInsertId();
if ((int) ($_POST['tariff_id'] ?? 0) > 0) {
PricingService::record(
$db,
$animalId,
(int) $_POST['tariff_id'],
1,
substr(self::now(), 0, 10),
'Ajoutée avec la note médicale',
);
}
// ==========================
// 2⃣ Upload photos médicales
// ==========================
if (!empty($_FILES['medical_photos']['name'][0])) {
$uploadDir = PrivateMediaService::medicalDir($animalId);
if (!is_dir($uploadDir)) {
PrivateMediaService::ensure($uploadDir);
}
foreach ($_FILES['medical_photos']['tmp_name'] as $key => $tmpName) {
if ($_FILES['medical_photos']['error'][$key] !== UPLOAD_ERR_OK) {
continue;
}
if ($_FILES['medical_photos']['size'][$key] > 20 * 1024 * 1024) {
continue;
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $tmpName);
$allowedTypes = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/webp' => 'webp',
];
if (!isset($allowedTypes[$mime])) {
continue;
}
try {
$stored = ImageService::storeUploaded($tmpName, $uploadDir, 'med', 'medical');
$safeName = $stored['filename'];
@chmod($stored['path'], 0600);
$stmtPhoto = $db->prepare('
INSERT INTO medical_photos (animal_id, medical_note_id, filename)
VALUES (?, ?, ?)
');
$stmtPhoto->execute([$animalId, $medicalNoteId, $safeName]);
} catch (Throwable) {
continue;
}
}
}
// 3⃣ Poids → measurements (graph)
if ($weight !== '' && is_numeric($weight)) {
$db->prepare(
"
INSERT INTO measurements (animal_id, measured_at, type, value, unit, notes, created_by)
VALUES (:aid, :at, 'weight', :v, 'kg', 'from medical note', :created_by)
",
)->execute([
':aid' => $animalId,
':at' => self::now(),
':v' => (float) $weight,
':created_by' => Auth::id(),
]);
}
// 4⃣ Historique
self::logHistory($animalId, 'medical', 'Note médicale ajoutée', $reason ?: null);
// 5⃣ Touch animal
if ($markSterilized) {
$db->prepare(
"UPDATE animals SET sterilized=1,sterilization_status='yes',sterilization_date=COALESCE(sterilization_date,date(:date)),sterilization_vet_contact_id=COALESCE(:vet,sterilization_vet_contact_id),sterilization_clinic_contact_id=COALESCE(:clinic,sterilization_clinic_contact_id) WHERE id=:id",
)->execute([
':date' => self::now(),
':vet' => $vetContact['id'] ?? null,
':clinic' => $clinicContact['id'] ?? null,
':id' => $animalId,
]);
}
$db->prepare(
'
UPDATE animals SET updated_at = :u WHERE id = :id
',
)->execute([
':u' => self::now(),
':id' => $animalId,
]);
self::redirectToAnimal($animalId);
}
public static function addTreatment(): void
{
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
http_response_code(405);
echo h(t('error.method_not_allowed'));
return;
}
$id = (int) ($_POST['animal_id'] ?? 0);
$medId = (int) ($_POST['medication_id'] ?? 0);
$createMedication = !empty($_POST['create_medication']);
if ($id <= 0 || (!$createMedication && $medId <= 0)) {
http_response_code(400);
echo h(t('error.bad_request'));
return;
}
$route = trim((string) ($_POST['route'] ?? ''));
$dose = trim((string) ($_POST['dose_text'] ?? ''));
$start = trim((string) ($_POST['start_date'] ?? date('Y-m-d')));
$end = trim((string) ($_POST['end_date'] ?? ''));
$notes = trim((string) ($_POST['notes'] ?? ''));
$giveMorning = !empty($_POST['give_morning']) ? 1 : 0;
$giveEvening = !empty($_POST['give_evening']) ? 1 : 0;
$giveAsNeeded = !empty($_POST['give_as_needed']) ? 1 : 0;
$clinic_id = (int) ($_POST['clinic_id'] ?? 0);
$clinic_id = $clinic_id > 0 ? $clinic_id : null;
$vet_name = trim((string) ($_POST['vet_name'] ?? ''));
$vet_name = $vet_name !== '' ? mb_strtoupper($vet_name, 'UTF-8') : null;
if ($dose === '') {
http_response_code(400);
echo h(t('error.dose_required'));
return;
}
$db = DB::pdo();
if ($createMedication) {
$medicationName = trim((string) ($_POST['new_medication_name'] ?? ''));
$medicationMolecule = trim((string) ($_POST['new_medication_molecule'] ?? ''));
$medicationForm = trim((string) ($_POST['new_medication_form'] ?? ''));
if ($medicationName === '') {
http_response_code(400);
echo h(t('error.medication_name_required'));
return;
}
$existing = $db->prepare('SELECT id FROM ref_medications WHERE name = :name COLLATE NOCASE LIMIT 1');
$existing->execute([':name' => $medicationName]);
$medId = (int) ($existing->fetchColumn() ?: 0);
if ($medId <= 0) {
$insertMedication = $db->prepare(
'INSERT INTO ref_medications(name, molecule, form) VALUES(:name,:molecule,:form)',
);
$insertMedication->execute([
':name' => mb_substr($medicationName, 0, 150),
':molecule' => $medicationMolecule !== '' ? mb_substr($medicationMolecule, 0, 150) : null,
':form' => $medicationForm !== '' ? mb_substr($medicationForm, 0, 100) : null,
]);
$medId = (int) $db->lastInsertId();
}
}
$clinicContact = self::resolveDirectoryContact(
$db,
(int) ($_POST['clinic_contact_id'] ?? 0),
(string) ($_POST['new_clinic_name'] ?? ''),
'organization',
'cabinet',
);
$vetContact = self::resolveDirectoryContact(
$db,
(int) ($_POST['vet_contact_id'] ?? 0),
(string) ($_POST['new_vet_name'] ?? ''),
'person',
'veterinaire',
);
self::normalizeVeterinaryClinic($db, $vetContact, $clinicContact);
if (!$vetContact || !$clinicContact) {
http_response_code(400);
echo h(t('error.vet_clinic_required'));
return;
}
$vet_name = $vetContact['name'] ?? $vet_name;
$stmt = $db->prepare('
INSERT INTO treatments(animal_id, medication_id, route, dose_text, start_date, end_date, ongoing, notes, clinic_id, vet_name, clinic_contact_id, vet_contact_id, give_morning, give_evening, give_as_needed, created_by)
VALUES(:aid,:mid,:route,:dose,:start,:end,1,:notes,:clinic_id,:vet_name,:clinic_contact_id,:vet_contact_id,:give_morning,:give_evening,:give_as_needed,:created_by)
');
$stmt->execute([
':aid' => $id,
':mid' => $medId,
':route' => $route !== '' ? $route : null,
':dose' => $dose,
':start' => $start,
':end' => $end !== '' ? $end : null,
':notes' => $notes !== '' ? $notes : null,
':clinic_id' => $clinic_id,
':vet_name' => $vet_name,
':clinic_contact_id' => $clinicContact['id'] ?? null,
':vet_contact_id' => $vetContact['id'] ?? null,
':give_morning' => $giveMorning,
':give_evening' => $giveEvening,
':give_as_needed' => $giveAsNeeded,
':created_by' => Auth::id(),
]);
if ((int) ($_POST['tariff_id'] ?? 0) > 0) {
PricingService::record($db, $id, (int) $_POST['tariff_id'], 1, $start, 'Ajoutée avec le traitement');
}
self::logHistory(
$id,
'treatment',
'Traitement ajouté',
"Médicament #$medId\nDose : $dose\nDébut : $start" .
($end !== '' ? "\nFin : $end" : '') .
($notes !== '' ? "\nNotes : $notes" : ''),
);
$db->prepare("UPDATE animals SET updated_at = datetime('now') WHERE id = :id")->execute([':id' => $id]);
self::redirectToAnimal($id);
}
public static function addExpense(): void
{
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
http_response_code(405);
return;
}
$animal = (int) ($_POST['animal_id'] ?? 0);
$tariff = (int) ($_POST['tariff_id'] ?? 0);
$qty = (float) str_replace(',', '.', (string) ($_POST['quantity'] ?? 1));
$date = (string) ($_POST['occurred_on'] ?? date('Y-m-d'));
if (!$animal || !$tariff || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
http_response_code(400);
echo h(t('error.invalid_expense'));
return;
}
$db = DB::pdo();
try {
$total = PricingService::record($db, $animal, $tariff, $qty, $date, trim((string) ($_POST['notes'] ?? '')));
self::logHistory(
$animal,
'medical',
'Dépense vétérinaire ajoutée',
number_format($total / 100, 2, ',', ' ') . ' €',
);
AuditService::log(
'animal_expense_added',
'/animal/add-expense',
'Dépense vétérinaire enregistrée',
'animal',
$animal,
['total_cents' => $total],
);
self::redirectToAnimal($animal);
} catch (Throwable $e) {
http_response_code(400);
echo h($e->getMessage());
}
}
public static function addVaccine(): void
{
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
http_response_code(405);
echo h(t('error.method_not_allowed'));
return;
}
$db = DB::pdo();
$id = (int) ($_POST['animal_id'] ?? 0);
$vacId = (int) ($_POST['vaccine_id'] ?? 0);
if ($id <= 0 || $vacId <= 0) {
http_response_code(400);
echo h(t('error.bad_request'));
return;
}
$done = trim((string) ($_POST['done_date'] ?? date('Y-m-d')));
$due = trim((string) ($_POST['due_date'] ?? ''));
// Si due_date est fourni, on respecte.
// Sinon auto selon protocole.
if ($due === '') {
// Birthdate (pour l'âge)
$stmt = $db->prepare('SELECT birth_date FROM animals WHERE id = :id');
$stmt->execute([':id' => $id]);
$birth = (string) ($stmt->fetchColumn() ?: '');
$isUnderOne = false;
if ($birth !== '') {
$birthDt = new DateTime($birth);
$doneDt = new DateTime($done);
$ageDays = (int) $birthDt->diff($doneDt)->format('%r%a');
if ($ageDays >= 0) {
$isUnderOne = $ageDays < 365;
}
}
// Protocole vaccin (family TC / L)
$stmt = $db->prepare('SELECT family, name FROM ref_vaccines WHERE id = :vid');
$stmt->execute([':vid' => $vacId]);
$vac = $stmt->fetch() ?: [];
$family = strtoupper((string) ($vac['family'] ?? ''));
// Détermine si c'est une primo pour la famille L (Leucose)
$isPrimoL = false;
if ($family === 'L') {
$stmt = $db->prepare("
SELECT COUNT(*)
FROM vaccinations v
JOIN ref_vaccines rv ON rv.id = v.vaccine_id
WHERE v.animal_id = :aid AND upper(coalesce(rv.family,'')) = 'L'
");
$stmt->execute([':aid' => $id]);
$countL = (int) $stmt->fetchColumn();
$isPrimoL = $countL === 0;
}
// Règles
if ($family === 'L') {
$due = $isPrimoL
? date('Y-m-d', strtotime($done . ' +1 month'))
: date('Y-m-d', strtotime($done . ' +1 year'));
} else {
// TC (ou inconnu => TC)
$due = $isUnderOne
? date('Y-m-d', strtotime($done . ' +1 month'))
: date('Y-m-d', strtotime($done . ' +1 year'));
}
}
$lot = trim((string) ($_POST['lot'] ?? ''));
$manufacturer = trim((string) ($_POST['manufacturer'] ?? ''));
$batchExpiresOn = trim((string) ($_POST['batch_expires_on'] ?? ''));
if ($batchExpiresOn !== '' && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $batchExpiresOn)) {
http_response_code(400);
echo h(t('error.invalid_batch_expiry'));
return;
}
$administratorUserId = (int) ($_POST['administered_by_user_id'] ?? 0) ?: null;
$administratorName = trim((string) ($_POST['administered_by_name'] ?? ''));
if ($administratorUserId) {
$check = $db->prepare('SELECT 1 FROM users WHERE id=:id AND active=1');
$check->execute([':id' => $administratorUserId]);
if (!$check->fetchColumn()) {
$administratorUserId = null;
}
}
$notes = trim((string) ($_POST['notes'] ?? ''));
$clinic_id = (int) ($_POST['clinic_id'] ?? 0);
$clinic_id = $clinic_id > 0 ? $clinic_id : null;
$vet_name = trim((string) ($_POST['vet_name'] ?? ''));
$vet_name = $vet_name !== '' ? mb_strtoupper($vet_name, 'UTF-8') : null;
$clinicContact = self::resolveDirectoryContact(
$db,
(int) ($_POST['clinic_contact_id'] ?? 0),
(string) ($_POST['new_clinic_name'] ?? ''),
'organization',
'cabinet',
);
$vetContact = self::resolveDirectoryContact(
$db,
(int) ($_POST['vet_contact_id'] ?? 0),
(string) ($_POST['new_vet_name'] ?? ''),
'person',
'veterinaire',
);
self::normalizeVeterinaryClinic($db, $vetContact, $clinicContact);
if (!$vetContact || !$clinicContact) {
http_response_code(400);
echo h(t('error.vet_clinic_required'));
return;
}
$vet_name = $vetContact['name'] ?? $vet_name;
$stmt = $db->prepare('
INSERT INTO vaccinations(animal_id, vaccine_id, done_date, due_date, lot,manufacturer,batch_expires_on,administered_by_user_id,administered_by_name, notes, clinic_id, vet_name, clinic_contact_id, vet_contact_id, created_by)
VALUES(:aid,:vid,:done,:due,:lot,:manufacturer,:batch_expiry,:administrator_user,:administrator_name,:notes,:clinic_id,:vet_name,:clinic_contact_id,:vet_contact_id,:created_by)
');
$stmt->execute([
':aid' => $id,
':vid' => $vacId,
':done' => $done,
':due' => $due !== '' ? $due : null,
':lot' => $lot !== '' ? $lot : null,
':manufacturer' => $manufacturer ?: null,
':batch_expiry' => $batchExpiresOn ?: null,
':administrator_user' => $administratorUserId,
':administrator_name' => $administratorName ?: null,
':notes' => $notes !== '' ? $notes : null,
':clinic_id' => $clinic_id,
':vet_name' => $vet_name,
':clinic_contact_id' => $clinicContact['id'] ?? null,
':vet_contact_id' => $vetContact['id'] ?? null,
':created_by' => Auth::id(),
]);
InventoryService::consumeBatch(
(int) ($_POST['inventory_batch_id'] ?? 0),
(float) str_replace(',', '.', (string) ($_POST['inventory_quantity'] ?? 0)),
$id,
'Vaccination du ' . $done,
);
if ((int) ($_POST['tariff_id'] ?? 0) > 0) {
PricingService::record($db, $id, (int) $_POST['tariff_id'], 1, $done, 'Ajoutée avec la vaccination');
}
self::logHistory(
$id,
'vaccine',
'Vaccin ajouté',
"Vaccin #$vacId\nFait le : $done" .
($due !== '' ? "\nRappel : $due" : '') .
($manufacturer !== '' ? "\nFabricant : $manufacturer" : '') .
($lot !== '' ? "\nLot : $lot" : '') .
($batchExpiresOn !== '' ? "\nExpiration du lot : $batchExpiresOn" : '') .
($administratorName !== '' || $administratorUserId
? "\nAdministré par : " .
($administratorName !== '' ? $administratorName : 'utilisateur #' . $administratorUserId)
: ''),
);
$db->prepare("UPDATE animals SET updated_at = datetime('now') WHERE id = :id")->execute([':id' => $id]);
self::redirectToAnimal($id);
}
}