feat(transport) : synchronisation du référentiel transporteurs QUALIMAT (ERP-39)

Commande console app:qualimat:sync : récupère les opérateurs de transport agréés depuis l'API publique qualimat.org, normalise et synchronise une table référentielle (upsert sur le SIRET + soft-delete des absents + journal). Prévue pour un cron quotidien.

- migration : tables qualimat_carrier + qualimat_sync_log (COMMENT ON COLUMN sur chaque colonne)
- QualimatRowMapper : normalisation pure (SIRET sans espaces, date dd/mm/yyyy -> ISO, skip sans SIRET) + tests unitaires
- SyncQualimatCommand : options --file / --ppp / --dry-run, upsert DBAL transactionnel
- activation de framework.http_client
- tests fonctionnels de la commande (upsert/normalisation/journal/soft-delete)
This commit is contained in:
2026-06-12 15:03:28 +02:00
parent 5f3da7022b
commit b444061237
6 changed files with 722 additions and 0 deletions
@@ -0,0 +1,90 @@
<?php
declare(strict_types=1);
namespace App\Tests\Module\Transport\Application\Qualimat;
use App\Module\Transport\Application\Qualimat\QualimatRowMapper;
use PHPUnit\Framework\TestCase;
/**
* @internal
*/
final class QualimatRowMapperTest extends TestCase
{
public function testNormalizeSiretStripsNonDigits(): void
{
self::assertSame('44415628500025', QualimatRowMapper::normalizeSiret('444 156 285 000 25'));
self::assertNull(QualimatRowMapper::normalizeSiret(null));
self::assertNull(QualimatRowMapper::normalizeSiret(' '));
self::assertNull(QualimatRowMapper::normalizeSiret(''));
}
public function testParseDate(): void
{
self::assertSame('2027-05-14', QualimatRowMapper::parseDate('14/05/2027'));
self::assertNull(QualimatRowMapper::parseDate(null));
self::assertNull(QualimatRowMapper::parseDate('2027-05-14'));
self::assertNull(QualimatRowMapper::parseDate('14-05-2027'));
// Date calendaire impossible : evite un INSERT en erreur.
self::assertNull(QualimatRowMapper::parseDate('31/02/2027'));
}
public function testMapOneNormalizesAndTrims(): void
{
$row = QualimatRowMapper::mapOne([
'Nom' => ' 2C TRANS ',
'Societe' => '2C TRANS',
'Adresse' => '66 Impasse Mendi',
'CodePostal' => '65500',
'Ville' => 'VIC EN BIGORRE',
'Telephone_1' => '+33|0608890316',
'Siret' => '444 156 285 000 25',
'Validite' => '14/05/2027',
'Statut' => 'Audité',
'Departement' => '65 - Hautes-Pyrénées',
]);
self::assertNotNull($row);
self::assertSame('44415628500025', $row['siret']);
self::assertSame('2C TRANS', $row['name']);
self::assertSame('2027-05-14', $row['validity_date']);
self::assertSame('+33|0608890316', $row['phone']);
self::assertSame('Audité', $row['status']);
self::assertSame('65 - Hautes-Pyrénées', $row['department']);
}
public function testMapOneReturnsNullWithoutSiret(): void
{
self::assertNull(QualimatRowMapper::mapOne(['Nom' => 'X', 'Siret' => null]));
self::assertNull(QualimatRowMapper::mapOne(['Nom' => 'X']));
self::assertNull(QualimatRowMapper::mapOne(['Nom' => 'X', 'Siret' => ' ']));
}
public function testMapManyCountsSkipped(): void
{
$result = QualimatRowMapper::mapMany([
['Nom' => 'A', 'Siret' => '111 111 111 00011', 'Statut' => 'Audité', 'Validite' => '01/01/2030'],
['Nom' => 'B', 'Siret' => null],
['Nom' => 'C', 'Siret' => ' '],
]);
self::assertCount(1, $result['rows']);
self::assertSame(2, $result['skipped']);
}
public function testEmptyOptionalFieldsBecomeNull(): void
{
$row = QualimatRowMapper::mapOne([
'Siret' => '111 111 111 00011',
'Nom' => 'A',
'Adresse' => '',
'Ville' => ' ',
]);
self::assertNotNull($row);
self::assertNull($row['address']);
self::assertNull($row['city']);
self::assertNull($row['validity_date']);
}
}