feat: merge lead-region cascade to main — deals-city + rossvyaz normalize, prod-parity verified

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-06-16 07:17:38 +03:00
parent cc82665f5c
commit c975e16a14
45 changed files with 3347 additions and 97 deletions
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
use App\Support\DaDataRegionMap;
use App\Support\RussianRegions;
it('maps exact official names via RussianRegions', function (): void {
expect(DaDataRegionMap::toSubjectCode('Москва'))->toBe(82)
->and(DaDataRegionMap::toSubjectCode('Московская область'))->toBe(56)
->and(DaDataRegionMap::toSubjectCode('Санкт-Петербург'))->toBe(83)
->and(DaDataRegionMap::toSubjectCode('Ленинградская область'))->toBe(53);
});
it('trims surrounding whitespace before mapping', function (): void {
expect(DaDataRegionMap::toSubjectCode(' Москва '))->toBe(82);
});
it('flags ambiguous agglomeration strings', function (): void {
expect(DaDataRegionMap::isAmbiguous('Санкт-Петербург и область'))->toBeTrue()
->and(DaDataRegionMap::isAmbiguous('Москва и область'))->toBeTrue()
->and(DaDataRegionMap::isAmbiguous('Москва'))->toBeFalse()
->and(DaDataRegionMap::isAmbiguous('Санкт-Петербург'))->toBeFalse();
});
it('returns null for unmappable region', function (): void {
expect(DaDataRegionMap::toSubjectCode('Атлантида'))->toBeNull()
->and(DaDataRegionMap::toSubjectCode(''))->toBeNull();
});
it('resolves all 89 RussianRegions names', function (): void {
foreach (RussianRegions::CODE_TO_NAME as $code => $name) {
expect(DaDataRegionMap::toSubjectCode($name))->toBe($code);
}
});