Globinours/scripts/reconcile-animal-current-state.php

106 lines
5.1 KiB
PHP
Raw 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.

#!/usr/bin/env php
<?php
declare(strict_types=1);
$root = dirname(__DIR__);
require $root . '/app/Services/DB.php';
require $root . '/app/Services/BackupService.php';
$apply = in_array('--apply', $argv, true);
$db = DB::pdo();
$backup = null;
$user =
(int) ($db->query("SELECT id FROM users WHERE role='admin' AND active=1 ORDER BY id LIMIT 1")->fetchColumn() ?:
0) ?:
null;
$latest = $db
->query(
"WITH ranked AS (SELECT ap.*,ROW_NUMBER() OVER(PARTITION BY animal_id ORDER BY date(event_date) DESC,id DESC) rn FROM animal_placements ap) SELECT r.*,a.status current_status,a.archived_at current_archived,dc.name contact_name,dc.address contact_address,dc.postal_code contact_postal,dc.city contact_city,ad.adopter_address,ad.adopter_postal_code,ad.adopter_city FROM ranked r JOIN animals a ON a.id=r.animal_id LEFT JOIN animal_deaths d ON d.animal_id=a.id LEFT JOIN directory_contacts dc ON dc.id=r.contact_id LEFT JOIN adoptions ad ON ad.id=r.adoption_id WHERE r.rn=1 AND r.event_type='adoption' AND d.animal_id IS NULL AND a.deleted_at IS NULL ORDER BY r.event_date,r.animal_id",
)
->fetchAll(PDO::FETCH_ASSOC);
$summary = [
'adopted_states_checked' => count($latest),
'statuses_fixed' => 0,
'locations_fixed' => 0,
'movements_created' => 0,
'movements_updated' => 0,
'history_created' => 0,
];
if ($apply) {
$backup = BackupService::create('avant-reconciliation-etat-animaux');
}
$db->beginTransaction();
try {
foreach ($latest as $row) {
$animal = (int) $row['animal_id'];
$date = (string) $row['event_date'];
$contact = trim((string) ($row['contact_name'] ?? '')) ?: 'Adoptant non renseigné';
$address = implode(
' ',
array_filter([
trim((string) ($row['contact_address'] ?? '' ?: $row['adopter_address'] ?? '')),
trim((string) ($row['contact_postal'] ?? '' ?: $row['adopter_postal_code'] ?? '')),
trim((string) ($row['contact_city'] ?? '' ?: $row['adopter_city'] ?? '')),
]),
);
if ($address === '') {
$address = 'Adopté par ' . $contact;
}
if ($row['current_status'] !== 'adopte' || empty($row['current_archived'])) {
$summary['statuses_fixed']++;
}
$current = $db->prepare('SELECT current_address FROM animals WHERE id=?');
$current->execute([$animal]);
if (trim((string) $current->fetchColumn()) !== $address) {
$summary['locations_fixed']++;
}
$db->prepare(
"UPDATE animals SET status='adopte',is_archived=1,archived_at=?,refuge_room=NULL,care_box_key=NULL,quarantine_until=NULL,current_address=?,current_lat=NULL,current_lng=NULL,updated_at=datetime('now') WHERE id=?",
)->execute([$date . ' 12:00:00', $address, $animal]);
$movement = $db->prepare(
"SELECT id FROM animal_movements WHERE animal_id=? AND kind='exit' AND lower(COALESCE(lieu,'')) LIKE 'adopt%' ORDER BY created_at DESC,id DESC LIMIT 1",
);
$movement->execute([$animal]);
$movementId = (int) $movement->fetchColumn();
if ($movementId) {
$db->prepare(
"UPDATE animal_movements SET place=?,lieu='Adoption',contact_name=?,note=CASE WHEN note IS NULL OR note='' THEN 'Sortie synchronisée avec le parcours dadoption.' ELSE note END,created_at=? WHERE id=?",
)->execute([$address, $contact, $date . ' 12:00:00', $movementId]);
$summary['movements_updated']++;
} else {
$db->prepare(
"INSERT INTO animal_movements(animal_id,kind,place,lieu,contact_name,note,created_at) VALUES(?,'exit',?,'Adoption',?,'Sortie synchronisée avec le parcours dadoption.',?)",
)->execute([$animal, $address, $contact, $date . ' 12:00:00']);
$summary['movements_created']++;
}
$history = $db->prepare(
"SELECT 1 FROM animal_history WHERE animal_id=? AND date(created_at)=date(?) AND (lower(label) LIKE '%adopt%' OR lower(type)='adoption') LIMIT 1",
);
$history->execute([$animal, $date]);
if (!$history->fetchColumn()) {
$db->prepare(
"INSERT INTO animal_history(animal_id,type,label,details,user_id,created_at) VALUES(?,'status','Adoption de lanimal',?,?,?)",
)->execute([$animal, 'Adopté par ' . $contact . '.', $user, $date . ' 12:00:00']);
$summary['history_created']++;
}
}
$fk = $db->query('PRAGMA foreign_key_check')->fetchAll();
if ($fk) {
throw new RuntimeException('Violation de clé étrangère après synchronisation.');
}
if ($apply) {
$db->commit();
} else {
$db->rollBack();
}
echo json_encode(
['mode' => $apply ? 'APPLIQUE' : 'SIMULATION', 'backup' => $backup['name'] ?? null, 'summary' => $summary],
JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
),
"\n";
} catch (Throwable $error) {
if ($db->inTransaction()) {
$db->rollBack();
}
fwrite(STDERR, 'Synchronisation interrompue : ' . $error->getMessage() . "\n");
exit(1);
}