164 lines
6.5 KiB
PHP
164 lines
6.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
final class Asm3ContactPlanner
|
|
{
|
|
public static function plan(string $path, PDO $db): array
|
|
{
|
|
$source = Asm3Analyzer::rows($path, ['owner', 'animal', 'adoption', 'animalvaccination']);
|
|
$adopters = [];
|
|
$depositors = [];
|
|
$vets = [];
|
|
foreach ($source['adoption'] ?? [] as $r) {
|
|
if ((int) ($r['OWNERID'] ?? 0) > 0) {
|
|
$adopters[(int) $r['OWNERID']] = true;
|
|
}
|
|
}
|
|
foreach ($source['animal'] ?? [] as $r) {
|
|
foreach (['BROUGHTINBYOWNERID', 'ORIGINALOWNERID'] as $field) {
|
|
if ((int) ($r[$field] ?? 0) > 0) {
|
|
$depositors[(int) $r[$field]] = true;
|
|
}
|
|
}
|
|
foreach (['CURRENTVETID', 'OWNERSVETID'] as $field) {
|
|
if ((int) ($r[$field] ?? 0) > 0) {
|
|
$vets[(int) $r[$field]] = true;
|
|
}
|
|
}
|
|
}
|
|
foreach ($source['animalvaccination'] ?? [] as $r) {
|
|
if ((int) ($r['ADMINISTERINGVETID'] ?? 0) > 0) {
|
|
$vets[(int) $r['ADMINISTERINGVETID']] = true;
|
|
}
|
|
}
|
|
$existing = $db
|
|
->query('SELECT id,kind,name,phone,email,city FROM directory_contacts WHERE deleted_at IS NULL')
|
|
->fetchAll(PDO::FETCH_ASSOC);
|
|
$items = [];
|
|
$summary = ['create' => 0, 'match' => 0, 'review' => 0];
|
|
foreach ($source['owner'] ?? [] as $row) {
|
|
$mapped = self::map(
|
|
$row,
|
|
isset($adopters[(int) $row['ID']]),
|
|
isset($depositors[(int) $row['ID']]),
|
|
isset($vets[(int) $row['ID']]),
|
|
);
|
|
$strong = [];
|
|
$weak = [];
|
|
$reasons = [];
|
|
foreach ($existing as $contact) {
|
|
$email = self::text($mapped['email']);
|
|
$phone = self::phone($mapped['phone']);
|
|
$sameEmail = $email !== '' && $email === self::text($contact['email']);
|
|
$samePhone = $phone !== '' && $phone === self::phone($contact['phone']);
|
|
$sameIdentity =
|
|
self::text($mapped['name']) === self::text($contact['name']) &&
|
|
self::text($mapped['city']) === self::text($contact['city']);
|
|
if ($sameEmail || $samePhone || $sameIdentity) {
|
|
$strong[(int) $contact['id']] = $contact;
|
|
if ($sameEmail) {
|
|
$reasons[] = 'même adresse e-mail';
|
|
}
|
|
if ($samePhone) {
|
|
$reasons[] = 'même téléphone';
|
|
}
|
|
if ($sameIdentity) {
|
|
$reasons[] = 'même nom et ville';
|
|
}
|
|
} elseif (
|
|
self::text($mapped['name']) !== '' &&
|
|
self::text($mapped['name']) === self::text($contact['name'])
|
|
) {
|
|
$weak[(int) $contact['id']] = $contact;
|
|
}
|
|
}
|
|
if (count($strong) === 1) {
|
|
$action = 'match';
|
|
$candidates = $strong;
|
|
} elseif (count($strong) > 1) {
|
|
$action = 'review';
|
|
$candidates = $strong;
|
|
} elseif ($weak) {
|
|
$action = 'review';
|
|
$candidates = $weak;
|
|
$reasons[] = 'même nom uniquement';
|
|
} else {
|
|
$action = 'create';
|
|
$candidates = [];
|
|
}
|
|
$summary[$action]++;
|
|
$items[] = [
|
|
'asm3_id' => (int) $row['ID'],
|
|
'action' => $action,
|
|
'match_reasons' => array_values(array_unique($reasons)),
|
|
'globinours_candidates' => array_values(
|
|
array_map(
|
|
static fn($c) => ['id' => (int) $c['id'], 'name' => $c['name'], 'city' => $c['city']],
|
|
$candidates,
|
|
),
|
|
),
|
|
'mapped' => $mapped,
|
|
];
|
|
}
|
|
return ['source' => basename($path), 'read_only' => true, 'summary' => $summary, 'items' => $items];
|
|
}
|
|
private static function map(array $r, bool $adopter, bool $depositor, bool $vetReferenced): array
|
|
{
|
|
$yes = static fn($v) => (string) $v === '1';
|
|
$name = trim(
|
|
(string) ($r['OWNERNAME'] ?? '' ?:
|
|
trim((string) ($r['OWNERFORENAMES'] ?? '') . ' ' . (string) ($r['OWNERSURNAME'] ?? ''))),
|
|
);
|
|
$organization =
|
|
(bool) preg_match('/\b(cabinet|clinique|cr[eé]matorium|association|refuge|fourri[eè]re)\b/iu', $name) ||
|
|
$yes($r['ISSHELTER'] ?? 0) ||
|
|
$yes($r['ISSUPPLIER'] ?? 0);
|
|
$roles = [];
|
|
if ($adopter || $yes($r['ISADOPTER'] ?? 0)) {
|
|
$roles[] = 'adoptant';
|
|
}
|
|
if ($yes($r['ISFOSTERER'] ?? 0)) {
|
|
$roles[] = 'fa';
|
|
}
|
|
if ($yes($r['ISVOLUNTEER'] ?? 0)) {
|
|
$roles[] = 'benevole';
|
|
}
|
|
if ($depositor) {
|
|
$roles[] = 'deposant';
|
|
}
|
|
if ($vetReferenced || $yes($r['ISVET'] ?? 0)) {
|
|
$roles[] = $organization ? 'cabinet' : 'veterinaire';
|
|
}
|
|
if (preg_match('/cr[eé]matorium/iu', $name)) {
|
|
$roles[] = 'crematorium';
|
|
}
|
|
$phones = array_values(
|
|
array_filter([
|
|
trim((string) ($r['MOBILETELEPHONE'] ?? '')),
|
|
trim((string) ($r['HOMETELEPHONE'] ?? '')),
|
|
trim((string) ($r['WORKTELEPHONE'] ?? '')),
|
|
]),
|
|
);
|
|
return [
|
|
'kind' => $organization ? 'organization' : 'person',
|
|
'name' => $name ?: 'Contact ASM3 ' . (int) $r['ID'],
|
|
'phone' => $phones[0] ?? null,
|
|
'email' => trim((string) ($r['EMAILADDRESS'] ?? '')) ?: null,
|
|
'address' => trim((string) ($r['OWNERADDRESS'] ?? '')) ?: null,
|
|
'postal_code' => trim((string) ($r['OWNERPOSTCODE'] ?? '')) ?: null,
|
|
'city' => trim((string) ($r['OWNERTOWN'] ?? '')) ?: null,
|
|
'country' => trim((string) ($r['OWNERCOUNTRY'] ?? '')) ?: 'France',
|
|
'notes' => trim((string) ($r['COMMENTS'] ?? '')) ?: null,
|
|
'roles' => array_values(array_unique($roles)),
|
|
];
|
|
}
|
|
private static function text(mixed $v): string
|
|
{
|
|
return mb_strtolower(trim((string) $v));
|
|
}
|
|
private static function phone(mixed $v): string
|
|
{
|
|
return (string) preg_replace('/\D+/', '', (string) $v);
|
|
}
|
|
}
|