b444061237
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)
112 lines
5.8 KiB
PHP
112 lines
5.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace DoctrineMigrations;
|
|
|
|
use Doctrine\DBAL\Schema\Schema;
|
|
use Doctrine\Migrations\AbstractMigration;
|
|
|
|
/**
|
|
* ERP-39 (Module Transport) : referentiel des transporteurs agrees QUALIMAT.
|
|
*
|
|
* Tables alimentees par la commande de synchronisation `app:qualimat:sync`
|
|
* (upsert sur le SIRET + soft-delete des absents + journal). Aucune FK
|
|
* cross-module (referentiel autonome) : migration posee au namespace racine
|
|
* `DoctrineMigrations`, comme les autres migrations de creation de tables.
|
|
*/
|
|
final class Version20260612150000 extends AbstractMigration
|
|
{
|
|
public function getDescription(): string
|
|
{
|
|
return 'ERP-39 : tables qualimat_carrier + qualimat_sync_log (referentiel transporteurs QUALIMAT, synchro console).';
|
|
}
|
|
|
|
public function up(Schema $schema): void
|
|
{
|
|
$this->addSql(<<<'SQL'
|
|
CREATE TABLE qualimat_carrier (
|
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
|
|
siret VARCHAR(20) NOT NULL,
|
|
name VARCHAR(255) NOT NULL,
|
|
address VARCHAR(255) DEFAULT NULL,
|
|
postal_code VARCHAR(10) DEFAULT NULL,
|
|
city VARCHAR(255) DEFAULT NULL,
|
|
phone VARCHAR(32) DEFAULT NULL,
|
|
department VARCHAR(64) DEFAULT NULL,
|
|
status VARCHAR(32) NOT NULL,
|
|
validity_date DATE DEFAULT NULL,
|
|
is_active BOOLEAN DEFAULT TRUE NOT NULL,
|
|
last_synced_at TIMESTAMP(6) WITHOUT TIME ZONE NOT NULL,
|
|
PRIMARY KEY (id),
|
|
CONSTRAINT uq_qualimat_carrier_siret UNIQUE (siret)
|
|
)
|
|
SQL);
|
|
$this->addSql('CREATE INDEX idx_qualimat_carrier_active ON qualimat_carrier (is_active)');
|
|
|
|
$this->comment('qualimat_carrier', '_table', "Referentiel des transporteurs agrees QUALIMAT, synchronise quotidiennement depuis l'API qualimat.org (type=operateur_transport).");
|
|
$this->comment('qualimat_carrier', 'id', 'Cle technique auto-incrementee.');
|
|
$this->comment('qualimat_carrier', 'siret', 'SIRET normalise (chiffres sans espaces). Cle naturelle de synchro (unique). Source parfois incomplete (longueur variable), non contrainte a 14.');
|
|
$this->comment('qualimat_carrier', 'name', 'Raison sociale du transporteur (champs Nom = Societe de la source, identiques).');
|
|
$this->comment('qualimat_carrier', 'address', 'Adresse postale (voie). Nullable.');
|
|
$this->comment('qualimat_carrier', 'postal_code', 'Code postal. Nullable.');
|
|
$this->comment('qualimat_carrier', 'city', 'Ville. Nullable.');
|
|
$this->comment('qualimat_carrier', 'phone', 'Telephone au format source "indicatif|numero" (ex: +33|0608890316). Nullable.');
|
|
$this->comment('qualimat_carrier', 'department', 'Departement au format source "code - libelle" (ex: 65 - Hautes-Pyrenees). Nullable.');
|
|
$this->comment('qualimat_carrier', 'status', "Statut d'agrement QUALIMAT (valeurs connues : Audite, Valide, Suspendu). Valeur brute de la source, non contrainte.");
|
|
$this->comment('qualimat_carrier', 'validity_date', 'Date de fin de validite de la certification (convertie depuis dd/mm/yyyy). Nullable.');
|
|
$this->comment('qualimat_carrier', 'is_active', 'Faux = transporteur absent du dernier import (soft-delete). Toute ligne non revue par le dernier run passe a FALSE.');
|
|
$this->comment('qualimat_carrier', 'last_synced_at', 'Horodatage du run de synchro ayant vu cette ligne en dernier (soft-delete : last_synced_at < run courant).');
|
|
|
|
$this->addSql(<<<'SQL'
|
|
CREATE TABLE qualimat_sync_log (
|
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
|
|
fetched_at TIMESTAMP(6) WITHOUT TIME ZONE NOT NULL,
|
|
rows_total INT NOT NULL,
|
|
rows_upserted INT NOT NULL,
|
|
rows_skipped INT NOT NULL,
|
|
rows_deactivated INT NOT NULL,
|
|
created_at TIMESTAMP(6) WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
|
|
PRIMARY KEY (id)
|
|
)
|
|
SQL);
|
|
|
|
$this->comment('qualimat_sync_log', '_table', 'Journal des synchronisations QUALIMAT (une ligne par run de la commande app:qualimat:sync).');
|
|
$this->comment('qualimat_sync_log', 'id', 'Cle technique auto-incrementee.');
|
|
$this->comment('qualimat_sync_log', 'fetched_at', "Horodatage de l'appel a l'API source (= run de synchro).");
|
|
$this->comment('qualimat_sync_log', 'rows_total', "Nombre d'items renvoyes par l'API.");
|
|
$this->comment('qualimat_sync_log', 'rows_upserted', 'Nombre de transporteurs inseres ou mis a jour.');
|
|
$this->comment('qualimat_sync_log', 'rows_skipped', "Nombre d'items ignores (sans SIRET exploitable).");
|
|
$this->comment('qualimat_sync_log', 'rows_deactivated', 'Nombre de transporteurs passes a is_active=false (absents de cet import).');
|
|
$this->comment('qualimat_sync_log', 'created_at', 'Horodatage de fin du run (insertion du journal).');
|
|
}
|
|
|
|
public function down(Schema $schema): void
|
|
{
|
|
$this->addSql('DROP TABLE IF EXISTS qualimat_sync_log');
|
|
$this->addSql('DROP TABLE IF EXISTS qualimat_carrier');
|
|
}
|
|
|
|
/**
|
|
* Pose un COMMENT ON TABLE/COLUMN en dollar-quoting Postgres ($_$...$_$)
|
|
* pour eviter tout echappement d'apostrophes dans les descriptions.
|
|
*/
|
|
private function comment(string $table, string $column, string $description): void
|
|
{
|
|
$quotedTable = '"'.str_replace('"', '""', $table).'"';
|
|
|
|
if ('_table' === $column) {
|
|
$this->addSql(sprintf('COMMENT ON TABLE %s IS $_$%s$_$', $quotedTable, $description));
|
|
|
|
return;
|
|
}
|
|
|
|
$this->addSql(sprintf(
|
|
'COMMENT ON COLUMN %s.%s IS $_$%s$_$',
|
|
$quotedTable,
|
|
'"'.str_replace('"', '""', $column).'"',
|
|
$description,
|
|
));
|
|
}
|
|
}
|