Refine public documentation and code comments
This commit is contained in:
parent
d7fb2b4413
commit
0a482afe9d
16 changed files with 195 additions and 628 deletions
|
|
@ -679,7 +679,7 @@ trait AnimalBrowseActions
|
|||
$stmt->execute([':id' => $id]);
|
||||
$prevWeight = $stmt->fetchColumn();
|
||||
|
||||
// PHOTOS : on récupère TOUT (public + privé)
|
||||
// Charge les photos publiques et privées pour la fiche interne.
|
||||
$stmt = $db->prepare('
|
||||
SELECT id, filename, is_primary, is_public, caption, care_round_id, created_at
|
||||
FROM animal_photos
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ trait AnimalMedicalActions
|
|||
}
|
||||
$vetName = $vetContact['name'] ?? null;
|
||||
|
||||
// 1️⃣ Insertion note médicale
|
||||
// Enregistre la note médicale avant ses éventuelles pièces jointes.
|
||||
$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)
|
||||
|
|
@ -274,7 +274,7 @@ trait AnimalMedicalActions
|
|||
':created' => self::now(),
|
||||
]);
|
||||
|
||||
// 👉 RÉCUPÉRATION ID NOTE
|
||||
// Identifiant utilisé pour rattacher les photos à la note.
|
||||
$medicalNoteId = $db->lastInsertId();
|
||||
if ((int) ($_POST['tariff_id'] ?? 0) > 0) {
|
||||
PricingService::record(
|
||||
|
|
@ -287,9 +287,7 @@ trait AnimalMedicalActions
|
|||
);
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// 2️⃣ Upload photos médicales
|
||||
// ==========================
|
||||
// Enregistre les photos médicales associées.
|
||||
|
||||
if (!empty($_FILES['medical_photos']['name'][0])) {
|
||||
$uploadDir = PrivateMediaService::medicalDir($animalId);
|
||||
|
|
@ -337,7 +335,7 @@ trait AnimalMedicalActions
|
|||
}
|
||||
}
|
||||
|
||||
// 3️⃣ Poids → measurements (graph)
|
||||
// Ajoute le poids aux mesures utilisées par le graphique.
|
||||
if ($weight !== '' && is_numeric($weight)) {
|
||||
$db->prepare(
|
||||
"
|
||||
|
|
@ -352,10 +350,10 @@ trait AnimalMedicalActions
|
|||
]);
|
||||
}
|
||||
|
||||
// 4️⃣ Historique
|
||||
// Ajoute l'intervention à l'historique de l'animal.
|
||||
self::logHistory($animalId, 'medical', 'Note médicale ajoutée', $reason ?: null);
|
||||
|
||||
// 5️⃣ Touch animal
|
||||
// Actualise la date de modification de la fiche.
|
||||
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",
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ trait AnimalPhotoActions
|
|||
continue;
|
||||
}
|
||||
|
||||
// RÈGLE : jamais une privée en principale
|
||||
// Une photo privée ne peut pas devenir la photo principale.
|
||||
$isPrimary = !$hasPrimary && $isPublic === 1 ? 1 : 0;
|
||||
if ($isPrimary === 1) {
|
||||
$hasPrimary = true;
|
||||
|
|
@ -221,7 +221,7 @@ trait AnimalPhotoActions
|
|||
throw $e;
|
||||
}
|
||||
|
||||
// Historique si tu veux
|
||||
// Conserve la suppression dans l'historique de la fiche.
|
||||
if (method_exists(__CLASS__, 'logHistory')) {
|
||||
self::logHistory($animalId, 'photo', 'Photo principale modifiée');
|
||||
}
|
||||
|
|
@ -274,7 +274,7 @@ trait AnimalPhotoActions
|
|||
@unlink($path);
|
||||
}
|
||||
|
||||
// Si on a supprimé la principale, on met la plus récente restante en principale
|
||||
// Remplace une photo principale supprimée par la plus récente encore disponible.
|
||||
if ($wasPrimary) {
|
||||
$pid = $db
|
||||
->query('SELECT id FROM animal_photos WHERE animal_id=' . (int) $animalId . ' ORDER BY id DESC LIMIT 1')
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ trait AnimalRecordActions
|
|||
'free_cat_captured_at' => '',
|
||||
'free_cat_released_at' => '',
|
||||
'free_cat_tracking_status' => 'present',
|
||||
// adapte si tu as fiv/felv en colonnes
|
||||
// Normalise les statuts FIV et FeLV enregistrés sur la fiche.
|
||||
'fiv' => '',
|
||||
'felv' => '',
|
||||
];
|
||||
|
|
@ -486,7 +486,7 @@ trait AnimalRecordActions
|
|||
$birth_estimated_months = null;
|
||||
}
|
||||
|
||||
// FIV/FELV (selon ton stockage actuel)
|
||||
// Statuts FIV et FeLV enregistrés sur la fiche.
|
||||
$fiv = array_key_exists('fiv', $_POST) ? (isset($_POST['fiv']) ? 1 : 0) : null;
|
||||
$felv = array_key_exists('felv', $_POST) ? (isset($_POST['felv']) ? 1 : 0) : null;
|
||||
|
||||
|
|
@ -514,7 +514,7 @@ trait AnimalRecordActions
|
|||
$birth_date = $birth_date === '' ? null : $birth_date;
|
||||
$intake_date = $intake_date === '' ? null : $intake_date;
|
||||
|
||||
// Code interne : auto si vide (et idéalement readonly en edit)
|
||||
// Génère le code interne lorsqu'il est absent.
|
||||
$internal_code = trim((string) ($_POST['internal_code'] ?? ''));
|
||||
if ($internal_code === '') {
|
||||
$internal_code = self::nextInternalCode($name);
|
||||
|
|
@ -528,7 +528,7 @@ trait AnimalRecordActions
|
|||
$quarantine_until = date('Y-m-d', $ts + AppSettings::int('quarantine_days', 1, 90) * 86400);
|
||||
}
|
||||
} else {
|
||||
// si pas en quarantaine, on vide la sortie (optionnel, mais logique)
|
||||
// La date de sortie n'a de sens que pour un animal en quarantaine.
|
||||
$quarantine_until = null;
|
||||
}
|
||||
|
||||
|
|
@ -575,7 +575,7 @@ trait AnimalRecordActions
|
|||
);
|
||||
$depositorId = $depositor ? (int) $depositor['id'] : null;
|
||||
|
||||
// Pour l’instant, tu bloques le lieu actuel
|
||||
// Le lieu actuel est conservé lorsque la fiche archivée est corrigée.
|
||||
if ($isArchivedCorrection) {
|
||||
$currentAddress = (string) ($old['current_address'] ?? '');
|
||||
}
|
||||
|
|
@ -758,9 +758,7 @@ trait AnimalRecordActions
|
|||
}
|
||||
|
||||
if ($old) {
|
||||
// Les nouvelles valeurs “connues” (ce que tu viens de sauver)
|
||||
// Astuce: tu mets TOUT ce que tu passes à l’UPDATE ici, mais sans maintenance lourde :
|
||||
// si tu ajoutes un champ au formulaire + UPDATE, tu l’ajoutes déjà ici de toute façon.
|
||||
// Valeurs persistées à comparer avec l'état précédent de la fiche.
|
||||
$new = [
|
||||
'name' => $name,
|
||||
'internal_code' => $internal_code,
|
||||
|
|
@ -801,8 +799,7 @@ trait AnimalRecordActions
|
|||
'quarantine_until' => $quarantine_until,
|
||||
'fiv' => $fiv,
|
||||
'felv' => $felv,
|
||||
// ajoute ici uniquement les champs que tu SAUVEGARDES dans UPDATE
|
||||
// (si demain tu ajoutes 3 champs au form, tu les ajouteras déjà à l’UPDATE -> copie/colle aussi ici)
|
||||
// Cette liste doit rester alignée sur les champs écrits par la requête UPDATE.
|
||||
];
|
||||
|
||||
// Champs à ignorer (bruit)
|
||||
|
|
|
|||
|
|
@ -426,7 +426,7 @@ final class AnimalsController
|
|||
throw $e;
|
||||
}
|
||||
|
||||
// Historique (optionnel)
|
||||
// Historique associé à la modification.
|
||||
if (method_exists(__CLASS__, 'logHistory')) {
|
||||
self::logHistory(
|
||||
$animalId,
|
||||
|
|
@ -486,7 +486,7 @@ final class AnimalsController
|
|||
try {
|
||||
$svc->refreshByChip($id, $chipId);
|
||||
} catch (Throwable $e) {
|
||||
// on laisse le cache en "error"
|
||||
// Le cache conserve l'état d'erreur fourni par le service.
|
||||
}
|
||||
$cached = $svc->getCachedByAnimal($id);
|
||||
$stale = $svc->isStale($cached, 86400);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ final class GeocodeService
|
|||
* Retour: ['lat'=>float, 'lng'=>float, 'display_name'=>string] ou null
|
||||
*
|
||||
* IMPORTANT:
|
||||
* - Respecte le fair use : pas de spam (cache côté DB chez toi, et TTL)
|
||||
* - Limite les appels au service grâce au cache local et à son TTL
|
||||
* - User-Agent explicite
|
||||
*/
|
||||
public static function geocode(string $query): ?array
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ final class IcadService
|
|||
return true;
|
||||
}
|
||||
|
||||
// si en erreur → on retente
|
||||
// Une entrée en erreur peut être actualisée lors d'une nouvelle tentative.
|
||||
if (($cache['status'] ?? '') !== 'ok') {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -227,13 +227,13 @@ final class IcadService
|
|||
return html_entity_decode($m[3], ENT_QUOTES);
|
||||
}
|
||||
|
||||
// 2) fallback: value avant name
|
||||
// 2) Accepte aussi les attributs placés dans l'ordre inverse.
|
||||
$re2 = '/<input\b[^>]*\bvalue=(["\'])(.*?)\1[^>]*\bname=(["\'])' . $field . '\3[^>]*>/is';
|
||||
if (preg_match($re2, $html, $m)) {
|
||||
return html_entity_decode($m[2], ENT_QUOTES);
|
||||
}
|
||||
|
||||
// 3) si fieldName == _token : on prend le 1er _token trouvé
|
||||
// 3) Utilise le premier jeton générique lorsque le champ demandé est _token.
|
||||
if ($fieldName === '_token') {
|
||||
if (preg_match('/<input\b[^>]*\bname=(["\'])_token\1[^>]*\bvalue=(["\'])(.*?)\2[^>]*>/is', $html, $m)) {
|
||||
return html_entity_decode($m[3], ENT_QUOTES);
|
||||
|
|
@ -264,7 +264,7 @@ final class IcadService
|
|||
return $p;
|
||||
}
|
||||
|
||||
// fallback HTML
|
||||
// Recherche de l'identifiant dans le HTML lorsque l'URL ne le contient pas.
|
||||
if (preg_match('~href=["\'](/animal/\d+)["\']~', $resp['body'], $m)) {
|
||||
return $m[1];
|
||||
}
|
||||
|
|
@ -336,9 +336,9 @@ final class IcadService
|
|||
// Adresse postale: i-CAD ne la met pas toujours dans un bloc unique, mais on tente
|
||||
$ownerPostal = $txt('//*[@id="down_right_block"]//*[contains(@class,"coords")]//*[contains(@class,"postal")]');
|
||||
if ($ownerPostal === '') {
|
||||
// fallback: parfois l’adresse est dans le même bloc coords mais pas taggée
|
||||
// L'adresse peut être présente dans le bloc de coordonnées sans libellé dédié.
|
||||
$coordsText = $txt('//*[@id="down_right_block"]//*[contains(@class,"coords")]');
|
||||
// on évite de tout recracher, juste si on détecte des numéros/rue
|
||||
// Ne conserve le bloc que s'il ressemble à une adresse postale.
|
||||
$ownerPostal = $coordsText;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ $data['owner'] ??
|
|||
$data['detenteur'] ??
|
||||
null;
|
||||
|
||||
// Si ton parse aplatit au lieu d'imbriquer :
|
||||
// Prend également en charge une réponse aplatie.
|
||||
if (!$holder && (
|
||||
isset($data['holder_name']) || isset($data['holder_phone']) || isset($data['holder_email'])
|
||||
)) {
|
||||
|
|
|
|||
|
|
@ -769,7 +769,7 @@ $today = date('Y-m-d');
|
|||
return true;
|
||||
}
|
||||
|
||||
// 2) Fallback “manuel” (au cas où)
|
||||
// 2) Activation manuelle si l'API Bootstrap n'est pas disponible.
|
||||
tabLinks.forEach(a => a.classList.remove('active'));
|
||||
document.querySelectorAll('.tab-pane').forEach(p => p.classList.remove('active', 'show'));
|
||||
|
||||
|
|
@ -794,7 +794,7 @@ $today = date('Y-m-d');
|
|||
history.replaceState(null, '', href);
|
||||
});
|
||||
|
||||
// Si jamais "shown.bs.tab" ne déclenche pas (rare), on sauvegarde au click aussi
|
||||
// Le clic maintient le fragment même si l'événement Bootstrap n'est pas émis.
|
||||
a.addEventListener('click', () => {
|
||||
const href = a.getAttribute('href');
|
||||
if (!href) return;
|
||||
|
|
@ -805,7 +805,7 @@ $today = date('Y-m-d');
|
|||
// Un hash explicite est respecté ; sinon Identité est systématique.
|
||||
const target = window.location.hash || '#tab-ident';
|
||||
|
||||
// Si bootstrap n'est pas prêt à l'instant T, on retente un peu (Tabler peut charger en bas)
|
||||
// Tabler peut initialiser Bootstrap après ce script : une courte nouvelle tentative suffit.
|
||||
let tries = 0;
|
||||
(function retry() {
|
||||
tries++;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
/** @var array $statuses */
|
||||
/** @var array $speciesOptions */
|
||||
|
||||
// Liste races (tu pourras l’externaliser plus tard en table ref)
|
||||
// Races proposées par défaut dans le formulaire.
|
||||
$breeds = [
|
||||
'Chat Européen',
|
||||
'Abyssin','Bengal','British Shorthair','Chartreux','Maine Coon','Norvégien',
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ function labelStatus(string $s): string
|
|||
|
||||
function fivFelvText(array $a): string
|
||||
{
|
||||
// adapte selon tes colonnes réelles (chez toi ça marche déjà côté liste)
|
||||
// Les photos publiques sont privilégiées pour le document imprimable.
|
||||
$fiv = (string)($a['fiv'] ?? '');
|
||||
$felv = (string)($a['felv'] ?? '');
|
||||
if ($fiv === '' && $felv === '') {
|
||||
|
|
@ -67,7 +67,7 @@ function fivFelvText(array $a): string
|
|||
if ($felv === '1') {
|
||||
return 'FELV+';
|
||||
}
|
||||
// fallback : si tu stockes déjà du texte
|
||||
// Accepte également une valeur déjà enregistrée sous forme de texte.
|
||||
return trim($fiv . ' ' . $felv);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,7 @@
|
|||
<span class="badge bg-blue-lt mb-2">1.0.0-rc.3</span>
|
||||
<h3>Stabilisation avant la 1.0</h3>
|
||||
<p class="text-muted">Découpage des fichiers volumineux, recherche universelle, correction de
|
||||
l’installation vierge, anonymisation du dépôt, fiche Twix fictive complète et harmonisation des
|
||||
sources PHP.</p>
|
||||
l’installation vierge, jeu de démonstration enrichi et harmonisation de la présentation.</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue