feat: permettre la modification des portées

This commit is contained in:
Alexandre NOEL 2026-09-15 18:48:25 +02:00
commit f45cfc40f2
15 changed files with 218 additions and 14 deletions

View file

@ -8,8 +8,10 @@ trait AnimalRelationshipActions
{
$db = DB::pdo();
$sourceAnimalId = (int) ($_GET['animal_id'] ?? 0);
$existingLitterId = (int) ($_GET['litter_id'] ?? 0);
$motherId = 0;
$fatherId = 0;
$birthDate = '';
if ($sourceAnimalId > 0) {
$stmt = $db->prepare(
@ -30,6 +32,20 @@ trait AnimalRelationshipActions
}
}
if ($existingLitterId > 0) {
$stmt = $db->prepare('SELECT mother_id,father_id,birth_date FROM litters WHERE id=:id');
$stmt->execute([':id' => $existingLitterId]);
$existingLitter = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$existingLitter) {
http_response_code(404);
echo h(t('litter.not_found'));
return;
}
$motherId = (int) ($existingLitter['mother_id'] ?? 0);
$fatherId = (int) ($existingLitter['father_id'] ?? 0);
$birthDate = (string) ($existingLitter['birth_date'] ?? '');
}
$eligibleSql = "
SELECT id, name FROM animals
WHERE deleted_at IS NULL AND archived_at IS NULL AND lower(species) IN ('chat', 'cat') AND sex = :sex
@ -53,6 +69,8 @@ trait AnimalRelationshipActions
'sourceAnimalId' => $sourceAnimalId,
'motherId' => $motherId,
'fatherId' => $fatherId,
'birthDate' => $birthDate,
'existingLitterId' => $existingLitterId,
'mothers' => $mothers,
'fathers' => $fathers,
'existingKittens' => $existingKittens,
@ -66,6 +84,7 @@ trait AnimalRelationshipActions
return;
}
$db = DB::pdo();
$existingLitterId = (int) ($_POST['existing_litter_id'] ?? 0);
$motherId = (int) ($_POST['mother_id'] ?? 0) ?: null;
$fatherId = (int) ($_POST['father_id'] ?? 0) ?: null;
$birthDate = trim((string) ($_POST['birth_date'] ?? '')) ?: null;
@ -141,11 +160,22 @@ trait AnimalRelationshipActions
$allowedSexes = ['F', 'M', 'U'];
$db->beginTransaction();
try {
$stmt = $db->prepare(
'INSERT INTO litters(mother_id, father_id, birth_date) VALUES(:mother, :father, :birth)',
);
$stmt->execute([':mother' => $motherId, ':father' => $fatherId, ':birth' => $birthDate]);
$litterId = (int) $db->lastInsertId();
if ($existingLitterId > 0) {
$stmt = $db->prepare('SELECT id,mother_id,father_id,birth_date FROM litters WHERE id=:id');
$stmt->execute([':id' => $existingLitterId]);
$existingLitter = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$existingLitter) {
throw new RuntimeException(t('litter.not_found'));
}
$litterId = (int) $existingLitter['id'];
$motherId = (int) ($existingLitter['mother_id'] ?? 0) ?: null;
$fatherId = (int) ($existingLitter['father_id'] ?? 0) ?: null;
$birthDate = (string) ($existingLitter['birth_date'] ?? '') ?: null;
} else {
$stmt = $db->prepare('INSERT INTO litters(mother_id, father_id, birth_date) VALUES(:mother, :father, :birth)');
$stmt->execute([':mother' => $motherId, ':father' => $fatherId, ':birth' => $birthDate]);
$litterId = (int) $db->lastInsertId();
}
$insertAnimal = $db->prepare("
INSERT INTO animals(name, internal_code, status, species, sex, breed, color, birth_date, birth_is_estimated,intake_date,intake_type,intake_reason, created_at, updated_at)
VALUES(:name, :code, 'refuge', 'chat', :sex, 'Chat Européen', :color, :birth, 0,:birth,'born_in_care','birth', datetime('now'), datetime('now'))
@ -153,11 +183,14 @@ trait AnimalRelationshipActions
$link = $db->prepare(
'INSERT INTO litter_kittens(litter_id, animal_id, position) VALUES(:litter, :animal, :position)',
);
$positionBase = $existingLitterId > 0
? (int) $db->query('SELECT COALESCE(MAX(position),0) FROM litter_kittens WHERE litter_id=' . $litterId)->fetchColumn()
: 0;
foreach ($kittens as $index => $kitten) {
if (!is_array($kitten)) {
continue;
}
$position = $index + 1;
$position = $positionBase + $index + 1;
$name = trim((string) ($kitten['name'] ?? ''));
if ($name === '') {
$name = $baseName . '-Bébé-' . $position;
@ -198,7 +231,7 @@ trait AnimalRelationshipActions
);
self::logHistory($animalId, 'create', 'Chaton ajouté avec sa portée', 'Portée n°' . $litterId);
}
$position = count($kittens);
$position = $positionBase + count($kittens);
foreach ($existingKittenIds as $animalId) {
$link->execute([':litter' => $litterId, ':animal' => $animalId, ':position' => ++$position]);
self::logHistory($animalId, 'update', 'Rattaché à une nouvelle portée', 'Portée n°' . $litterId);
@ -214,6 +247,113 @@ trait AnimalRelationshipActions
}
}
public static function litterEditForm(): void
{
$db = DB::pdo();
$litterId = (int) ($_GET['id'] ?? 0);
$sourceAnimalId = (int) ($_GET['animal_id'] ?? 0);
$stmt = $db->prepare('SELECT l.*,m.name mother_name,f.name father_name FROM litters l LEFT JOIN animals m ON m.id=l.mother_id LEFT JOIN animals f ON f.id=l.father_id WHERE l.id=:id');
$stmt->execute([':id' => $litterId]);
$litter = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$litter) {
http_response_code(404);
echo h(t('litter.not_found'));
return;
}
$parents = $db->query("SELECT id,name,sex FROM animals WHERE deleted_at IS NULL AND lower(species) IN ('chat','cat') ORDER BY name COLLATE NOCASE")->fetchAll(PDO::FETCH_ASSOC);
$stmt = $db->prepare('SELECT a.id,a.name,a.internal_code,a.sex,a.color,a.status,a.archived_at FROM litter_kittens lk JOIN animals a ON a.id=lk.animal_id WHERE lk.litter_id=:id ORDER BY lk.position,a.name COLLATE NOCASE');
$stmt->execute([':id' => $litterId]);
render('litter_edit.php', [
'title' => t('litter.edit'),
'pageDescription' => t('litter.edit_help'),
'litter' => $litter,
'mothers' => array_values(array_filter($parents, static fn(array $animal): bool => $animal['sex'] === 'F')),
'fathers' => array_values(array_filter($parents, static fn(array $animal): bool => $animal['sex'] === 'M')),
'kittens' => $stmt->fetchAll(PDO::FETCH_ASSOC),
'sourceAnimalId' => $sourceAnimalId,
]);
}
public static function updateLitter(): void
{
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
http_response_code(405);
return;
}
$db = DB::pdo();
$litterId = (int) ($_POST['litter_id'] ?? 0);
$sourceAnimalId = (int) ($_POST['source_animal_id'] ?? 0);
$motherId = (int) ($_POST['mother_id'] ?? 0) ?: null;
$fatherId = (int) ($_POST['father_id'] ?? 0) ?: null;
$birthDate = trim((string) ($_POST['birth_date'] ?? '')) ?: null;
if ($litterId <= 0 || ($motherId !== null && $motherId === $fatherId)) {
http_response_code(400);
echo h(t('litter.invalid_parent'));
return;
}
if ($birthDate !== null && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $birthDate)) {
http_response_code(400);
echo h(t('error.invalid_birth_date'));
return;
}
$ids = array_values(array_filter([$motherId, $fatherId]));
if ($ids) {
$placeholders = implode(',', array_fill(0, count($ids), '?'));
$stmt = $db->prepare("SELECT id,sex FROM animals WHERE id IN ($placeholders) AND deleted_at IS NULL AND lower(species) IN ('chat','cat')");
$stmt->execute($ids);
$valid = [];
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $animal) {
$valid[(int) $animal['id']] = $animal['sex'];
}
if (($motherId && ($valid[$motherId] ?? '') !== 'F') || ($fatherId && ($valid[$fatherId] ?? '') !== 'M')) {
http_response_code(400);
echo h(t('litter.invalid_parent'));
return;
}
$stmt = $db->prepare('SELECT COUNT(*) FROM litter_kittens WHERE litter_id=? AND animal_id IN (' . $placeholders . ')');
$stmt->execute([$litterId, ...$ids]);
if ((int) $stmt->fetchColumn() > 0) {
http_response_code(400);
echo h(t('litter.parent_is_kitten'));
return;
}
}
$exists = $db->prepare('SELECT 1 FROM litters WHERE id=:id');
$exists->execute([':id' => $litterId]);
if (!$exists->fetchColumn()) {
http_response_code(404);
return;
}
$db->prepare('UPDATE litters SET mother_id=:mother,father_id=:father,birth_date=:birth WHERE id=:id')->execute([':mother' => $motherId, ':father' => $fatherId, ':birth' => $birthDate, ':id' => $litterId]);
header('Location: /animal?id=' . ($sourceAnimalId ?: ($motherId ?: ($fatherId ?: 0))) . '#tab-litters');
exit();
}
public static function detachLitterKitten(): void
{
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
http_response_code(405);
return;
}
$litterId = (int) ($_POST['litter_id'] ?? 0);
$animalId = (int) ($_POST['animal_id'] ?? 0);
$sourceAnimalId = (int) ($_POST['source_animal_id'] ?? 0);
$stmt = DB::pdo()->prepare('DELETE FROM litter_kittens WHERE litter_id=:litter AND animal_id=:animal');
$stmt->execute([':litter' => $litterId, ':animal' => $animalId]);
if ($stmt->rowCount() > 0) {
self::logHistory($animalId, 'update', 'Retiré d’une portée', 'Ancienne portée n°' . $litterId);
}
$remaining = DB::pdo()->prepare('SELECT COUNT(*) FROM litter_kittens WHERE litter_id=:id');
$remaining->execute([':id' => $litterId]);
if ((int) $remaining->fetchColumn() === 0) {
DB::pdo()->prepare('DELETE FROM litters WHERE id=:id')->execute([':id' => $litterId]);
header('Location: /animal?id=' . ($sourceAnimalId ?: $animalId) . '#tab-litters');
exit();
}
header('Location: /litter/edit?id=' . $litterId . '&animal_id=' . $sourceAnimalId);
exit();
}
public static function litterAddExistingForm(): void
{
$db = DB::pdo();