Globinours/app/Controllers/PlacementsController.php

172 lines
6.7 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 PlacementsController
{
private const TYPES = [
'reservation' => 'Réservation',
'foster' => 'Placement en famille daccueil',
'return' => 'Retour au refuge',
'cancellation' => 'Annulation',
];
public static function save(): void
{
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
http_response_code(405);
return;
}
$db = DB::pdo();
$animalId = (int) ($_POST['animal_id'] ?? 0);
$type = (string) ($_POST['event_type'] ?? '');
$date = (string) ($_POST['event_date'] ?? '');
if (!$animalId || !isset(self::TYPES[$type]) || !self::validDate($date)) {
http_response_code(400);
echo h(t('error.invalid_placement'));
return;
}
$reason = trim((string) ($_POST['reason'] ?? ''));
if (in_array($type, ['return', 'cancellation'], true) && $reason === '') {
http_response_code(400);
echo h(t('error.placement_reason_required'));
return;
}
$s = $db->prepare('SELECT * FROM animals WHERE id=:id AND deleted_at IS NULL AND archived_at IS NULL');
$s->execute([':id' => $animalId]);
$animal = $s->fetch(PDO::FETCH_ASSOC);
if (!$animal) {
http_response_code(404);
return;
}
$contactId = (int) ($_POST['contact_id'] ?? 0) ?: null;
$contact = null;
if ($contactId) {
$s = $db->prepare('SELECT * FROM directory_contacts WHERE id=:id AND deleted_at IS NULL');
$s->execute([':id' => $contactId]);
$contact = $s->fetch(PDO::FETCH_ASSOC) ?: null;
if (!$contact) {
$contactId = null;
}
}
$status = match ($type) {
'reservation' => 'reserve',
'foster' => 'fa',
'return' => 'refuge',
'cancellation' => in_array($animal['status'], ['reserve', 'réservé'], true) ? 'refuge' : $animal['status'],
};
$currentAddress = (string) ($animal['current_address'] ?? '');
if ($type === 'foster' && $contact) {
$currentAddress = implode(
' ',
array_filter([$contact['address'] ?? '', $contact['postal_code'] ?? '', $contact['city'] ?? '']),
);
}
if ($type === 'return') {
$currentAddress = implode(
' ',
array_filter([
AppSettings::get('association_address'),
AppSettings::get('association_postal_code'),
AppSettings::get('association_city'),
]),
);
}
$notes = trim((string) ($_POST['notes'] ?? ''));
$db->beginTransaction();
try {
$db->prepare(
'INSERT INTO animal_placements(animal_id,event_type,event_date,contact_id,reason,notes,created_by) VALUES(:animal,:type,:date,:contact,:reason,:notes,:user)',
)->execute([
':animal' => $animalId,
':type' => $type,
':date' => $date,
':contact' => $contactId,
':reason' => $reason ?: null,
':notes' => $notes ?: null,
':user' => Auth::id(),
]);
$db->prepare(
'UPDATE animals SET status=:status,refuge_room=NULL,care_box_key=NULL,current_address=:address,current_lat=NULL,current_lng=NULL,updated_at=datetime(\'now\') WHERE id=:id',
)->execute([':status' => $status, ':address' => $currentAddress ?: null, ':id' => $animalId]);
$after = $animal;
$after['status'] = $status;
$after['refuge_room'] = null;
$after['care_box_key'] = null;
$after['current_address'] = $currentAddress;
LocationHistoryService::record(
$db,
$animalId,
$animal,
$after,
'placement',
self::TYPES[$type] . ($reason !== '' ? ' — ' . $reason : ''),
$date . ' 12:00:00',
);
$details = [];
if ($reason !== '') {
$details[] = 'Motif : ' . $reason;
}
if ($notes !== '') {
$details[] = 'Notes : ' . $notes;
}
$db->prepare(
'INSERT INTO animal_history(animal_id,type,label,details,user_id,created_at) VALUES(:animal,\'placement\',:label,:details,:user,:date)',
)->execute([
':animal' => $animalId,
':label' => self::TYPES[$type],
':details' => $details ? implode("\n", $details) : null,
':user' => Auth::id(),
':date' => $date . ' 12:00:00',
]);
if ($type === 'foster' || $type === 'return') {
self::movement($db, $animalId, $type, $contactId, $reason, $notes, $date);
}
$db->commit();
header('Location: /animal?id=' . $animalId . '#tab-placements');
exit();
} catch (Throwable $e) {
if ($db->inTransaction()) {
$db->rollBack();
}
throw $e;
}
}
private static function movement(
PDO $db,
int $animalId,
string $type,
?int $contactId,
string $reason,
string $notes,
string $date,
): void {
$contact = null;
if ($contactId) {
$s = $db->prepare('SELECT name,phone,email,city FROM directory_contacts WHERE id=:id');
$s->execute([':id' => $contactId]);
$contact = $s->fetch(PDO::FETCH_ASSOC) ?: null;
}
$db->prepare(
'INSERT INTO animal_movements(animal_id,kind,place,lieu,contact_name,contact_phone,contact_email,note,created_at) VALUES(:animal,:kind,:place,:lieu,:name,:phone,:email,:note,:date)',
)->execute([
':animal' => $animalId,
':kind' => $type === 'return' ? 'entry' : 'exit',
':place' => $contact['city'] ?? null,
':lieu' => $type === 'return' ? 'Retour de placement' : 'Placement en FA',
':name' => $contact['name'] ?? null,
':phone' => $contact['phone'] ?? null,
':email' => $contact['email'] ?? null,
':note' =>
trim(($reason !== '' ? 'Motif : ' . $reason : '') . ($notes !== '' ? "\nNotes : " . $notes : '')) ?:
null,
':date' => $date . ' 12:00:00',
]);
}
private static function validDate(string $date): bool
{
$d = DateTimeImmutable::createFromFormat('!Y-m-d', $date);
return $d !== false && $d->format('Y-m-d') === $date;
}
}