fix(catalog) : align SQL backfill slug with CategoryCodeGenerator (ERP-78)
Le backfill de code de la migration Version20260602100000 utilisait un slug SQL (REGEXP_REPLACE) qui ne translitterait pas les accents : « Independant » produisait IND_PENDANT la ou le generateur applicatif (AsciiSlugger) produit INDEPENDANT. Le code categorie, cle censee etre deterministe entre environnements, divergeait selon le chemin (SQL migration vs PHP runtime). - CategoryCodeSql : source unique de l'expression SQL de slug, miroir fidele de CategoryCodeGenerator::slugify (translate() des accents Latin-1, trim _, fallback CATEGORY). - Migration : etapes 3 et 5 du backfill branchees sur ce helper. - CategoryCodeSqlSlugTest : garde-fou verrouillant l'egalite SQL = PHP sur le domaine accentue, pour empecher toute future derive (cause racine du bug).
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Module\Catalog\Api;
|
||||
|
||||
use App\Module\Catalog\Application\Service\CategoryCodeGenerator;
|
||||
use App\Shared\Infrastructure\Database\CategoryCodeSql;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
|
||||
/**
|
||||
* Garde-fou ERP-78 : l'expression SQL de slug (CategoryCodeSql, utilisee par le
|
||||
* backfill de la migration Version20260602100000) doit produire EXACTEMENT le
|
||||
* meme code que le generateur applicatif (CategoryCodeGenerator::slugify), sur
|
||||
* tout le domaine de noms francais / Latin-1.
|
||||
*
|
||||
* Verrouille la cause racine du bug initial : deux implementations d'un meme
|
||||
* slug qui derivent silencieusement (« Independant » -> IND_PENDANT cote SQL
|
||||
* faute de translitteration des accents, vs INDEPENDANT cote PHP). On ne couvre
|
||||
* volontairement PAS les ligatures (`Œ`, `ß`) : `translate()` est 1->1 et ne
|
||||
* peut produire `OE`/`SS` ; elles sont hors du domaine des categories CLIENT.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class CategoryCodeSqlSlugTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
* Noms representatifs du domaine reel : accents, cedille, apostrophe,
|
||||
* separateurs varies, parentheses, majuscules accentuees.
|
||||
*
|
||||
* @return iterable<string, array{string}>
|
||||
*/
|
||||
public static function nameProvider(): iterable
|
||||
{
|
||||
yield 'sans accent' => ['Distributeur'];
|
||||
yield 'tiret' => ['Agro-alimentaire'];
|
||||
yield 'slash' => ['Transport/Logistique'];
|
||||
yield 'accent aigu' => ['Indépendant'];
|
||||
yield 'apostrophe + accent' => ["L'Oréal"];
|
||||
yield 'esperluette' => ['Forêt & Bûcheron'];
|
||||
yield 'cedille majuscule' => ['Ça va'];
|
||||
yield 'accents multiples' => ['Naïve façade'];
|
||||
yield 'circonflexe' => ["Côte d'Azur"];
|
||||
yield 'parentheses' => ['Zone (Sud)'];
|
||||
}
|
||||
|
||||
#[DataProvider('nameProvider')]
|
||||
public function testSqlSlugMatchesPhpSlug(string $name): void
|
||||
{
|
||||
self::bootKernel();
|
||||
$container = self::getContainer();
|
||||
|
||||
/** @var Connection $conn */
|
||||
$conn = $container->get('doctrine')->getConnection();
|
||||
/** @var CategoryCodeGenerator $generator */
|
||||
$generator = $container->get(CategoryCodeGenerator::class);
|
||||
|
||||
// Evaluation pure de l'expression (aucune table requise) : le nom est
|
||||
// passe en parametre lie a la place de la colonne.
|
||||
$sqlSlug = $conn->fetchOne(
|
||||
'SELECT '.CategoryCodeSql::slugExpression(':name'),
|
||||
['name' => $name],
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$generator->slugify($name),
|
||||
$sqlSlug,
|
||||
sprintf('SQL et PHP doivent produire le meme slug pour "%s".', $name),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user