fix: rétablir la création des portées

This commit is contained in:
Alexandre NOEL 2026-09-15 18:27:40 +02:00
commit 2029849f18
14 changed files with 35 additions and 21 deletions

View file

@ -2,6 +2,14 @@
Toutes les modifications importantes du projet sont consignées ici. Le format s’inspire de [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/) et le projet suit le [versionnage sémantique](https://semver.org/lang/fr/). Toutes les modifications importantes du projet sont consignées ici. Le format s’inspire de [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/) et le projet suit le [versionnage sémantique](https://semver.org/lang/fr/).
## [1.0.0-rc.23] — 2026-09-15
### Création des portées
- retrait d’un bloc de téléversement résiduel qui interrompait systématiquement l’enregistrement d’une portée ;
- correction du message trompeur « Le téléversement a échoué » rencontré sans aucun fichier envoyé ;
- compatibilité des événements de portée, de soins, de décès, de chirurgie et de placement avec l’historique des bases existantes.
## [1.0.0-rc.22] — 2026-09-15 ## [1.0.0-rc.22] — 2026-09-15
### Disponibilité après adoption ### Disponibilité après adoption

View file

@ -97,3 +97,7 @@ Ajout d’une température préremplie à 38,5 °C lors du contrôle de chaque a
## `1.0.0-rc.22` — Disponibilité après adoption ## `1.0.0-rc.22` — Disponibilité après adoption
Une adoption finalisée rend désormais automatiquement l’animal indisponible à l’adoption afin que son état administratif et sa visibilité restent cohérents. Une adoption finalisée rend désormais automatiquement l’animal indisponible à l’adoption afin que son état administratif et sa visibilité restent cohérents.
## `1.0.0-rc.23` — Fiabilité des portées
Suppression d’un ancien bloc de téléversement qui bloquait la création des fratries et harmonisation de leur écriture dans l’historique des animaux.

View file

@ -200,7 +200,7 @@ L’option `--apply` ne doit être utilisée qu’après lecture des rapports. L
## État du projet ## État du projet
La candidate actuelle est `1.0.0-rc.22`. La branche 1.0 est gelée fonctionnellement : seuls les défauts bloquants découverts pendant les validations terrain sont corrigés avant `1.0.0`. La candidate actuelle est `1.0.0-rc.23`. La branche 1.0 est gelée fonctionnellement : seuls les défauts bloquants découverts pendant les validations terrain sont corrigés avant `1.0.0`.
Le contrôle de stabilisation est disponible dans [docs/AUDIT-1.0.md](docs/AUDIT-1.0.md). Le contrôle de stabilisation est disponible dans [docs/AUDIT-1.0.md](docs/AUDIT-1.0.md).

View file

@ -1 +1 @@
1.0.0-rc.22 1.0.0-rc.23

View file

@ -139,13 +139,6 @@ trait AnimalRelationshipActions
$baseName = trim((string) ($parents[$motherId]['name'] ?? ($parents[$fatherId]['name'] ?? 'Portée'))); $baseName = trim((string) ($parents[$motherId]['name'] ?? ($parents[$fatherId]['name'] ?? 'Portée')));
$allowedSexes = ['F', 'M', 'U']; $allowedSexes = ['F', 'M', 'U'];
try {
PrivateMediaService::moveVisibility($animalId, (string) $photo['filename'], $isPublic === 1);
} catch (Throwable $e) {
http_response_code(500);
echo h(t('error.upload_failed'));
return;
}
$db->beginTransaction(); $db->beginTransaction();
try { try {
$stmt = $db->prepare( $stmt = $db->prepare(

View file

@ -116,8 +116,8 @@ final class AnimalsController
$db = DB::pdo(); $db = DB::pdo();
$db->prepare( $db->prepare(
' '
INSERT INTO animal_history (animal_id, type, label, details, user_id) INSERT INTO animal_history (animal_id, action, type, label, details, user_id)
VALUES (:aid, :type, :label, :details, :user) VALUES (:aid, :type, :type, :label, :details, :user)
', ',
)->execute([ )->execute([
':aid' => $animalId, ':aid' => $animalId,

View file

@ -295,7 +295,7 @@ final class CareRoundsController
$roundDate = $roundInfo ? date('d/m/Y', strtotime((string) $roundInfo['round_date'])) : date('d/m/Y'); $roundDate = $roundInfo ? date('d/m/Y', strtotime((string) $roundInfo['round_date'])) : date('d/m/Y');
$roundPeriod = t('care.' . self::period($roundInfo['period'] ?? 'morning')); $roundPeriod = t('care.' . self::period($roundInfo['period'] ?? 'morning'));
$history = $db->prepare( $history = $db->prepare(
"INSERT INTO animal_history(animal_id,type,label,details,user_id) VALUES(:animal,'care_round',:label,:details,:user)", "INSERT INTO animal_history(animal_id,action,type,label,details,user_id) VALUES(:animal,'care_round','care_round',:label,:details,:user)",
); );
$history->execute([ $history->execute([
':animal' => $animalId, ':animal' => $animalId,

View file

@ -175,7 +175,7 @@ final class DeathController
$details .= '\nEuthanasie : oui'; $details .= '\nEuthanasie : oui';
} }
$db->prepare( $db->prepare(
"INSERT INTO animal_history(animal_id,type,label,details,user_id) VALUES(:id,'death',:label,:details,:user)", "INSERT INTO animal_history(animal_id,action,type,label,details,user_id) VALUES(:id,'death','death',:label,:details,:user)",
)->execute([ )->execute([
':id' => $id, ':id' => $id,
':label' => $isUpdate ? 'Informations de décès modifiées' : 'Décès enregistré', ':label' => $isUpdate ? 'Informations de décès modifiées' : 'Décès enregistré',

View file

@ -85,7 +85,7 @@ final class DewormingController
'INSERT INTO dewormings(animal_id,dewormer_id,administered_on,dose_text,weight_kg,next_due_date,notes,source_litter_id,created_by) VALUES(?,?,?,?,?,?,?,?,?)', 'INSERT INTO dewormings(animal_id,dewormer_id,administered_on,dose_text,weight_kg,next_due_date,notes,source_litter_id,created_by) VALUES(?,?,?,?,?,?,?,?,?)',
); );
$history = $db->prepare( $history = $db->prepare(
"INSERT INTO animal_history(animal_id,type,label,details,user_id) VALUES(?,'deworming','Vermifuge administré',?,?)", "INSERT INTO animal_history(animal_id,action,type,label,details,user_id) VALUES(?,'deworming','deworming','Vermifuge administré',?,?)",
); );
foreach ($ids as $id) { foreach ($ids as $id) {
$s = $db->prepare('SELECT name,birth_date FROM animals WHERE id=? AND deleted_at IS NULL'); $s = $db->prepare('SELECT name,birth_date FROM animals WHERE id=? AND deleted_at IS NULL');

View file

@ -314,7 +314,7 @@ final class MedicalDocumentsController
private static function history(PDO $db, int $animalId, string $label, string $details): void private static function history(PDO $db, int $animalId, string $label, string $details): void
{ {
$db->prepare( $db->prepare(
"INSERT INTO animal_history(animal_id,type,label,details,user_id) VALUES(?,'medical',?,?,?)", "INSERT INTO animal_history(animal_id,action,type,label,details,user_id) VALUES(?,'medical','medical',?,?,?)",
)->execute([$animalId, $label, $details, Auth::id()]); )->execute([$animalId, $label, $details, Auth::id()]);
} }
private static function fr(string $date): string private static function fr(string $date): string

View file

@ -126,7 +126,7 @@ final class PlacementsController
$details[] = 'Notes : ' . $notes; $details[] = 'Notes : ' . $notes;
} }
$db->prepare( $db->prepare(
'INSERT INTO animal_history(animal_id,type,label,details,user_id,created_at) VALUES(:animal,\'placement\',:label,:details,:user,:date)', 'INSERT INTO animal_history(animal_id,action,type,label,details,user_id,created_at) VALUES(:animal,\'placement\',\'placement\',:label,:details,:user,:date)',
)->execute([ )->execute([
':animal' => $animalId, ':animal' => $animalId,
':label' => self::TYPES[$type], ':label' => self::TYPES[$type],

View file

@ -104,7 +104,7 @@ final class SurgeriesController
]); ]);
} }
$db->prepare( $db->prepare(
"INSERT INTO animal_history(animal_id,type,label,details,user_id) VALUES(?,'medical','Chirurgie enregistrée',?,?)", "INSERT INTO animal_history(animal_id,action,type,label,details,user_id) VALUES(?,'medical','medical','Chirurgie enregistrée',?,?)",
)->execute([$animal, $name . ' — ' . $date, Auth::id()]); )->execute([$animal, $name . ' — ' . $date, Auth::id()]);
$db->commit(); $db->commit();
header('Location: /animal?id=' . $animal . '#tab-med'); header('Location: /animal?id=' . $animal . '#tab-med');

View file

@ -31,10 +31,10 @@
<div class="col-lg-6"> <div class="col-lg-6">
<section class="card h-100"> <section class="card h-100">
<div class="card-body"> <div class="card-body">
<span class="badge bg-blue-lt mb-2">1.0.0-rc.22</span> <span class="badge bg-blue-lt mb-2">1.0.0-rc.23</span>
<h3>Disponibilité après adoption</h3> <h3>Fiabilité des portées</h3>
<p class="text-muted">Une adoption finalisée rend automatiquement l’animal indisponible afin de <p class="text-muted">La création d’une fratrie ne dépend plus d’un ancien traitement de photo et
conserver un état administratif cohérent.</p> son historique reste compatible avec les bases existantes.</p>
</div> </div>
</section> </section>
</div> </div>

View file

@ -78,6 +78,15 @@ try {
); );
$assert(in_array('temperature_c', $columns, true), 'Colonne temperature_c absente'); $assert(in_array('temperature_c', $columns, true), 'Colonne temperature_c absente');
}); });
$test('La création d’une portée ne dépend pas d’un téléversement', function () use ($assert): void {
$relationships = file_get_contents(__DIR__ . '/../app/Controllers/AnimalRelationshipActions.php');
$animals = file_get_contents(__DIR__ . '/../app/Controllers/AnimalsController.php');
$assert(!str_contains($relationships, 'PrivateMediaService::moveVisibility'), 'Bloc de photo résiduel dans les portées');
$assert(
str_contains($animals, 'animal_id, action, type, label, details, user_id'),
'L’historique des portées ne renseigne pas son action',
);
});
$test("Les voies d’administration des médicaments sont initialisées", function () use ($db, $assert): void { $test("Les voies d’administration des médicaments sont initialisées", function () use ($db, $assert): void {
$routes = $db $routes = $db
->query('SELECT accro FROM ref_med_administration ORDER BY id') ->query('SELECT accro FROM ref_med_administration ORDER BY id')