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:
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use App\Shared\Infrastructure\Database\CategoryCodeSql;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
@@ -75,18 +76,19 @@ final class Version20260602100000 extends AbstractMigration
|
||||
// 3. Re-pointer toute categorie pre-existante (rattachee a un ancien type)
|
||||
// vers le type CLIENT, en lui donnant un code derive du nom si absent.
|
||||
// En prod la table est vide -> no-op ; defensif pour les envs qui
|
||||
// auraient deja seede des categories sous les anciens types.
|
||||
$this->addSql(<<<'SQL'
|
||||
UPDATE category c
|
||||
SET category_type_id = (SELECT id FROM category_type WHERE code = 'CLIENT'),
|
||||
code = COALESCE(
|
||||
c.code,
|
||||
LEFT(UPPER(REGEXP_REPLACE(c.name, '[^A-Za-z0-9]+', '_', 'g')), 50)
|
||||
)
|
||||
WHERE c.category_type_id IN (
|
||||
SELECT id FROM category_type WHERE code IN (:legacyCodes)
|
||||
)
|
||||
SQL, ['legacyCodes' => self::LEGACY_TYPE_CODES], ['legacyCodes' => \Doctrine\DBAL\ArrayParameterType::STRING]);
|
||||
// auraient deja seede des categories sous les anciens types. Le slug
|
||||
// SQL est le miroir EXACT de CategoryCodeGenerator::slugify (cf.
|
||||
// CategoryCodeSql + CategoryCodeSqlSlugTest) : un nom accentue produit
|
||||
// le meme code que la generation applicative (« Independant » ->
|
||||
// INDEPENDANT, et non IND_PENDANT).
|
||||
$this->addSql(
|
||||
'UPDATE category c '
|
||||
."SET category_type_id = (SELECT id FROM category_type WHERE code = 'CLIENT'), "
|
||||
.'code = COALESCE(c.code, '.CategoryCodeSql::slugExpression('c.name').') '
|
||||
.'WHERE c.category_type_id IN (SELECT id FROM category_type WHERE code IN (:legacyCodes))',
|
||||
['legacyCodes' => self::LEGACY_TYPE_CODES],
|
||||
['legacyCodes' => \Doctrine\DBAL\ArrayParameterType::STRING],
|
||||
);
|
||||
|
||||
// 4. Creer les 4 categories systeme sous CLIENT (si leur code est libre
|
||||
// parmi les actifs). created_at/updated_at NOT NULL -> now() ; le blame
|
||||
@@ -104,12 +106,11 @@ final class Version20260602100000 extends AbstractMigration
|
||||
}
|
||||
|
||||
// 5. Backfill defensif : toute categorie encore sans code recoit un slug
|
||||
// de son nom (garantit que le SET NOT NULL passe).
|
||||
$this->addSql(<<<'SQL'
|
||||
UPDATE category
|
||||
SET code = LEFT(UPPER(REGEXP_REPLACE(name, '[^A-Za-z0-9]+', '_', 'g')), 50)
|
||||
WHERE code IS NULL
|
||||
SQL);
|
||||
// de son nom (garantit que le SET NOT NULL passe). Meme expression de
|
||||
// slug fidele au generateur applicatif (CategoryCodeSql).
|
||||
$this->addSql(
|
||||
'UPDATE category SET code = '.CategoryCodeSql::slugExpression('name').' WHERE code IS NULL',
|
||||
);
|
||||
|
||||
// 6. Index unique partiel sur le code parmi les actifs (non exprimable en
|
||||
// ORM : recree aussi dans `test-db-setup` apres schema:update).
|
||||
|
||||
Reference in New Issue
Block a user