Corrige la localisation actuelle des animaux

This commit is contained in:
Alexandre NOEL 2026-09-13 15:57:57 +02:00
commit 68590eddbb
9 changed files with 80 additions and 36 deletions

View file

@ -2,6 +2,15 @@
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.20] — 2026-09-13
### Localisation des animaux
- regroupement des informations de récupération et de lieu actuel dans une seule section sans anciens champs en double ;
- conservation de l’adresse actuelle lors de la modification d’une fiche ;
- géocodage du nouveau lieu lors d’un placement ou d’un retour au refuge ;
- réparation ponctuelle des coordonnées manquantes des animaux déjà importés afin d’afficher leur lieu actuel sur la carte.
## [1.0.0-rc.19] — 2026-09-13 ## [1.0.0-rc.19] — 2026-09-13
### Horodatage des contrôles de soins ### Horodatage des contrôles de soins

View file

@ -85,3 +85,7 @@ Déplacement des informations légales dans le pied de page, insertion guidée d
## `1.0.0-rc.19` — Contrôles de soins horodatés ## `1.0.0-rc.19` — Contrôles de soins horodatés
Ajout d’une date et d’une heure modifiables aux contrôles médicaux, avec reprise cohérente de l’instant choisi dans les mesures de poids et les données associées. Ajout d’une date et d’une heure modifiables aux contrôles médicaux, avec reprise cohérente de l’instant choisi dans les mesures de poids et les données associées.
## `1.0.0-rc.20` — Localisations cohérentes
Simplification des lieux affichés dans la fiche, conservation de l’adresse actuelle et réparation des coordonnées manquantes après un import ou un placement.

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.19`. 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.20`. 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.19 1.0.0-rc.20

View file

@ -453,6 +453,35 @@ trait AnimalBrowseActions
echo h(t('error.animal_not_found')); echo h(t('error.animal_not_found'));
return; return;
} }
// Les imports historiques peuvent contenir une adresse sans ses coordonnées.
// On complète alors la fiche une seule fois, au premier affichage de la carte.
$coordinateUpdates = [];
foreach ([
'rescue' => trim((string) ($animal['rescue_address'] ?: $animal['rescue_location_name'] ?? '')),
'current' => trim((string) ($animal['current_address'] ?? '')),
] as $kind => $address) {
if (
$address !== '' &&
($animal[$kind . '_lat'] === null || $animal[$kind . '_lng'] === null)
) {
$coordinates = GeoService::geocode($db, $address);
if ($coordinates) {
$coordinateUpdates[$kind . '_lat'] = $coordinates['lat'];
$coordinateUpdates[$kind . '_lng'] = $coordinates['lng'];
}
}
}
if ($coordinateUpdates) {
$assignments = [];
$parameters = [':id' => $id];
foreach ($coordinateUpdates as $column => $value) {
$assignments[] = $column . '=:' . $column;
$parameters[':' . $column] = $value;
$animal[$column] = $value;
}
$db->prepare('UPDATE animals SET ' . implode(',', $assignments) . ' WHERE id=:id')->execute($parameters);
}
if (!empty($animal['intake_owner_care_home'])) { if (!empty($animal['intake_owner_care_home'])) {
$animal['intake_reason'] = 'owner_care_home'; $animal['intake_reason'] = 'owner_care_home';
} }

View file

@ -72,6 +72,15 @@ final class PlacementsController
]), ]),
); );
} }
$currentLat = null;
$currentLng = null;
if ($currentAddress !== '') {
$coordinates = GeoService::geocode($db, $currentAddress);
if ($coordinates) {
$currentLat = $coordinates['lat'];
$currentLng = $coordinates['lng'];
}
}
$notes = trim((string) ($_POST['notes'] ?? '')); $notes = trim((string) ($_POST['notes'] ?? ''));
$db->beginTransaction(); $db->beginTransaction();
try { try {
@ -87,8 +96,14 @@ final class PlacementsController
':user' => Auth::id(), ':user' => Auth::id(),
]); ]);
$db->prepare( $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', 'UPDATE animals SET status=:status,refuge_room=NULL,care_box_key=NULL,current_address=:address,current_lat=:lat,current_lng=:lng,updated_at=datetime(\'now\') WHERE id=:id',
)->execute([':status' => $status, ':address' => $currentAddress ?: null, ':id' => $animalId]); )->execute([
':status' => $status,
':address' => $currentAddress ?: null,
':lat' => $currentLat,
':lng' => $currentLng,
':id' => $animalId,
]);
$after = $animal; $after = $animal;
$after['status'] = $status; $after['status'] = $status;
$after['refuge_room'] = null; $after['refuge_room'] = null;

View file

@ -178,11 +178,11 @@
<?php <?php
$rescueAddr = trim((string)($animal['rescue_address'] ?? '')); $rescueAddr = trim((string)($animal['rescue_address'] ?: $animal['rescue_location_name'] ?? ''));
$rescueLat = isset($animal['rescue_lat']) && $animal['rescue_lat'] !== '' ? (float)$animal['rescue_lat'] : null; $rescueLat = isset($animal['rescue_lat']) && $animal['rescue_lat'] !== '' ? (float)$animal['rescue_lat'] : null;
$rescueLng = isset($animal['rescue_lng']) && $animal['rescue_lng'] !== '' ? (float)$animal['rescue_lng'] : null; $rescueLng = isset($animal['rescue_lng']) && $animal['rescue_lng'] !== '' ? (float)$animal['rescue_lng'] : null;
$currentAddr = trim((string)($animal['current_address'] ?? '5 RUE NOTRE DAME 29260 LESNEVEN')); $currentAddr = trim((string)($animal['current_address'] ?? ''));
$currentLat = isset($animal['current_lat']) && $animal['current_lat'] !== '' ? (float)$animal['current_lat'] : null; $currentLat = isset($animal['current_lat']) && $animal['current_lat'] !== '' ? (float)$animal['current_lat'] : null;
$currentLng = isset($animal['current_lng']) && $animal['current_lng'] !== '' ? (float)$animal['current_lng'] : null; $currentLng = isset($animal['current_lng']) && $animal['current_lng'] !== '' ? (float)$animal['current_lng'] : null;
@ -212,7 +212,7 @@ $hasCurrent = ($currentLat !== null && $currentLng !== null);
<div class="col-md-6"> <div class="col-md-6">
<div class="text-muted mb-1"><?= h(t('animal.form.current_location')) ?></div> <div class="text-muted mb-1"><?= h(t('animal.form.current_location')) ?></div>
<div class="fw-bold"><?= h($currentAddr) ?></div> <div class="fw-bold"><?= $currentAddr !== '' ? h($currentAddr) : '—' ?></div>
<?php if (!$hasCurrent): ?> <?php if (!$hasCurrent): ?>
<div class="text-muted small mt-1"><?= h(t('animal.coordinates_missing')) ?></div> <div class="text-muted small mt-1"><?= h(t('animal.coordinates_missing')) ?></div>

View file

@ -422,22 +422,6 @@ $estMonths = $birth_estimated_months > 0 ? ($birth_estimated_months % 12) : '';
</div> </div>
</div> </div>
<div class="row">
<div class="col-md-8">
<div class="text-muted"><?= h(t('animal.rescue_location')) ?></div>
<input class="form-control" type="text" name="rescue_address"
value="<?= h($animal['rescue_address'] ?? '') ?>"
placeholder="<?= h(t('animal.rescue_location_placeholder')) ?>">
<div class="text-muted small mt-1"><?= h(t('animal.geocode_help')) ?></div>
</div>
<div class="col-md-4">
<div class="text-muted"><?= h(t('animal.form.current_location')) ?></div>
<input class="form-control" type="text" name="current_address"
value="<?= h($animal['current_address'] ?? '5 RUE NOTRE DAME 29260 LESNEVEN') ?>"
<?= $isArchivedEdit ? 'readonly' : '' ?> disabled>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -534,7 +518,7 @@ $estMonths = $birth_estimated_months > 0 ? ($birth_estimated_months % 12) : '';
</div> </div>
<div class="row g-3"> <div class="row g-3">
<div class="col-md-6"> <div class="col-md-4">
<label class="form-label"><?= h(t('animal.form.origin_city')) ?></label> <label class="form-label"><?= h(t('animal.form.origin_city')) ?></label>
<input type="text" name="rescue_location_name" class="form-control" <input type="text" name="rescue_location_name" class="form-control"
value="<?= h($animal['rescue_location_name'] ?? '') ?>" value="<?= h($animal['rescue_location_name'] ?? '') ?>"
@ -547,17 +531,20 @@ $estMonths = $birth_estimated_months > 0 ? ($birth_estimated_months % 12) : '';
value="<?= h($animal['rescue_lng'] ?? '') ?>"> value="<?= h($animal['rescue_lng'] ?? '') ?>">
</div> </div>
<div class="col-md-6"> <div class="col-md-4">
<label class="form-label"><?= h(t('animal.rescue_location')) ?></label>
<input class="form-control" type="text" name="rescue_address"
value="<?= h($animal['rescue_address'] ?? '') ?>"
placeholder="<?= h(t('animal.rescue_location_placeholder')) ?>">
<div class="form-hint"><?= h(t('animal.geocode_help')) ?></div>
</div>
<div class="col-md-4">
<label class="form-label"><?= h(t('animal.form.current_location')) ?></label> <label class="form-label"><?= h(t('animal.form.current_location')) ?></label>
<input type="text" name="location_name" class="form-control" <input type="text" name="current_address" class="form-control"
value="<?= h($animal['location_name'] ?? '5 Rue Notre Dame 29260 LESNEVEN') ?>" value="<?= h($animal['current_address'] ?? '') ?>"
readonly> readonly>
<div class="form-hint"><?= h(t('animal.form.current_location_hint')) ?></div> <div class="form-hint"><?= h(t('animal.form.current_location_hint')) ?></div>
<input type="hidden" name="location_lat"
value="<?= h($animal['location_lat'] ?? '') ?>">
<input type="hidden" name="location_lng"
value="<?= h($animal['location_lng'] ?? '') ?>">
</div> </div>
</div> </div>
</div> </div>

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.19</span> <span class="badge bg-blue-lt mb-2">1.0.0-rc.20</span>
<h3>Suivi des soins</h3> <h3>Localisations cohérentes</h3>
<p class="text-muted">Date et heure modifiables pour distinguer précisément plusieurs contrôles et <p class="text-muted">Lieu de récupération et lieu actuel clairement distingués, avec réparation
mesures réalisés au cours d’une même journée.</p> des coordonnées manquantes après un import ou un placement.</p>
</div> </div>
</section> </section>
</div> </div>