3f356f0679
Auto Tag Develop / tag (push) Successful in 9s
## Objectif (ERP-116, 1re iteration minimale) Sortir la liste des pays du **code en dur** cote front et la poser en base comme **referentiel `country`**, source unique du select pays. **Perimetre volontairement minimal** : code ISO + libelle + ordre uniquement — **aucune longueur bancaire/fiscale** (numero de compte, IBAN, TVA, BIC, SIREN) a ce stade. ## Backend - Entite `Country` (`code` ISO 3166-1 alpha-2 unique, `name`, `position`), calquee sur `Bank` : referentiel statique **lecture seule** (`GetCollection` + `Get`), gating `commercial.clients.view OR commercial.suppliers.view`. - Migration `Version20260609100000` : table `country` + `COMMENT ON COLUMN` + seed des **6 pays** (France, Allemagne, Belgique, Espagne, Italie, Royaume-Uni), `ON CONFLICT DO NOTHING`. - `CommercialReferentialFixtures` : re-seed des pays en dev/test. - Garde-fous : ajout au `ColumnCommentsCatalog` + whitelist `EntitiesAreTimestampableBlamableTest`. ## Frontend - `useClientReferentials` charge `/countries` (value = **nom** du pays : l'adresse stocke `country` en chaine libre, **pas de FK ni migration de donnees**). - Les 3 listes `countryOptions` en dur (clients new / edit / consultation) sont supprimees ; la consultation derive ses options de l'embed. ## Hors-scope (iterations suivantes du ticket) - Longueurs bancaires/fiscales par pays + validation associee. - FK `country_id` sur les adresses + migration de donnees. ## Tests - Back : suite complete verte (583), tests API dedies countries (200/seed/405/403/401). - Front : Vitest vert (256), spec `useClientReferentials` mise a jour. - Migration appliquee en dev + test. --------- Co-authored-by: Matthieu <contact@malio.fr> Reviewed-on: #79
136 lines
4.9 KiB
PHP
136 lines
4.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Module\Commercial\Infrastructure\DataFixtures;
|
|
|
|
use App\Module\Commercial\Domain\Entity\Bank;
|
|
use App\Module\Commercial\Domain\Entity\Country;
|
|
use App\Module\Commercial\Domain\Entity\PaymentDelay;
|
|
use App\Module\Commercial\Domain\Entity\PaymentType;
|
|
use App\Module\Commercial\Domain\Entity\TvaMode;
|
|
use Doctrine\Bundle\FixturesBundle\Fixture;
|
|
use Doctrine\Persistence\ObjectManager;
|
|
|
|
/**
|
|
* Fixtures du module Commercial : re-seed des 4 referentiels comptables
|
|
* (tva_mode, payment_delay, payment_type, bank) seedes par la migration M1
|
|
* (Version20260601000000) + du referentiel pays (country) seede par la
|
|
* migration ERP-116 (Version20260609100000).
|
|
*
|
|
* Pourquoi cette fixture EN PLUS du seed de la migration : ces tables sont des
|
|
* entites managees par l'ORM, donc le purger Doctrine les
|
|
* vide avant chaque `doctrine:fixtures:load`. Sans cette fixture, les
|
|
* referentiels seedes par la migration disparaitraient apres `make db-reset`
|
|
* (0 ligne en dev/test) — cassant les FK Client -> referentiels et les tests
|
|
* RG-1.12/1.13. Le seed migration couvre la prod (ou les fixtures ne tournent
|
|
* pas) ; cette fixture re-aligne dev et test. Memes valeurs des deux cotes.
|
|
*
|
|
* Idempotence : lookup par `code` avant insertion (sur le modele de
|
|
* CategoryTypeFixtures). Rejouable sans doublon meme si le purger est desactive.
|
|
*/
|
|
class CommercialReferentialFixtures extends Fixture
|
|
{
|
|
/**
|
|
* Source unique des referentiels : classe d'entite => [code => [label, position]].
|
|
* Doit rester aligne sur le seed de la migration Version20260601000000.
|
|
*
|
|
* @var array<class-string, array<string, array{string, int}>>
|
|
*/
|
|
private const REFERENTIALS = [
|
|
TvaMode::class => [
|
|
'FRANCE_VENTES' => ['France (ventes)', 10],
|
|
'EXPORT_VENTES' => ['Export (ventes)', 20],
|
|
'INTRACOM_VENTES' => ['Intracom (ventes)', 30],
|
|
],
|
|
PaymentDelay::class => [
|
|
'J15' => ['15 jours', 10],
|
|
'J30' => ['30 jours', 20],
|
|
'A_RECEPTION' => ['À réception', 30],
|
|
],
|
|
PaymentType::class => [
|
|
'VIREMENT' => ['Virement', 10],
|
|
'LCR' => ['LCR', 20],
|
|
'NON_SOUMISE' => ['Non soumise', 30],
|
|
'CHEQUE' => ['Chèque', 40],
|
|
],
|
|
Bank::class => [
|
|
'SG' => ['Société Générale', 10],
|
|
'CIC' => ['CIC', 20],
|
|
'CA' => ['Crédit Agricole', 30],
|
|
],
|
|
];
|
|
|
|
/**
|
|
* Referentiel pays (ERP-116) : code ISO alpha-2 => [name, position].
|
|
* Doit rester aligne sur le seed de la migration Version20260609100000.
|
|
* Traite a part car Country porte `name` (et non `label`).
|
|
*
|
|
* @var array<string, array{string, int}>
|
|
*/
|
|
private const COUNTRIES = [
|
|
'FR' => ['France', 10],
|
|
'DE' => ['Allemagne', 20],
|
|
'BE' => ['Belgique', 30],
|
|
'ES' => ['Espagne', 40],
|
|
'IT' => ['Italie', 50],
|
|
'GB' => ['Royaume-Uni', 60],
|
|
'CH' => ['Suisse', 70],
|
|
];
|
|
|
|
public function load(ObjectManager $manager): void
|
|
{
|
|
foreach (self::REFERENTIALS as $entityClass => $rows) {
|
|
$this->seedReferential($manager, $entityClass, $rows);
|
|
}
|
|
|
|
$this->seedCountries($manager);
|
|
|
|
$manager->flush();
|
|
}
|
|
|
|
/**
|
|
* Upsert idempotent du referentiel pays (lookup par code). Distinct de
|
|
* seedReferential car Country utilise setName au lieu de setLabel.
|
|
*/
|
|
private function seedCountries(ObjectManager $manager): void
|
|
{
|
|
$existingByCode = [];
|
|
foreach ($manager->getRepository(Country::class)->findAll() as $country) {
|
|
$existingByCode[$country->getCode()] = $country;
|
|
}
|
|
|
|
foreach (self::COUNTRIES as $code => [$name, $position]) {
|
|
$country = $existingByCode[$code] ?? new Country();
|
|
$country->setCode($code);
|
|
$country->setName($name);
|
|
$country->setPosition($position);
|
|
$manager->persist($country);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Upsert idempotent d'un referentiel : indexe l'existant par code puis
|
|
* cree/met a jour chaque entree. Les 4 entites partagent le meme contrat
|
|
* setCode/setLabel/setPosition.
|
|
*
|
|
* @param class-string $entityClass
|
|
* @param array<string, array{string, int}> $rows
|
|
*/
|
|
private function seedReferential(ObjectManager $manager, string $entityClass, array $rows): void
|
|
{
|
|
$existingByCode = [];
|
|
foreach ($manager->getRepository($entityClass)->findAll() as $entity) {
|
|
$existingByCode[$entity->getCode()] = $entity;
|
|
}
|
|
|
|
foreach ($rows as $code => [$label, $position]) {
|
|
$entity = $existingByCode[$code] ?? new $entityClass();
|
|
$entity->setCode($code);
|
|
$entity->setLabel($label);
|
|
$entity->setPosition($position);
|
|
$manager->persist($entity);
|
|
}
|
|
}
|
|
}
|