53fb7b7760
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
120 lines
4.6 KiB
PHP
120 lines
4.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Support\Imitation;
|
|
|
|
use App\Support\RussianRegions;
|
|
use Database\Seeders\PricingTierSeeder;
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Tests\Concerns\SharesSupplierPdo;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* Base test case for Phase 1 imitation harness tests.
|
|
*
|
|
* Seeds reference data (pricing_tiers, suppliers) once per test within a
|
|
* database transaction so every test starts from a clean, known state.
|
|
*
|
|
* Usage:
|
|
* Extend this class (PHPUnit-style) or include the trait equivalents
|
|
* in Pest tests. Pest tests should prefer:
|
|
*
|
|
* uses(DatabaseTransactions::class, SharesSupplierPdo::class);
|
|
* beforeEach(fn () => (new ImitationTestCase())->seedReferenceData());
|
|
*
|
|
* Schema dependencies (exact columns verified against db/schema.sql):
|
|
* pricing_tiers: id, tier_no (1..7), leads_in_tier, price_per_lead_kopecks,
|
|
* is_active, effective_from, created_at, updated_at
|
|
* suppliers: id, code, name, accepts_types (varchar[]), cost_rub,
|
|
* channel, quality_score, is_active, sort_order, created_at
|
|
*
|
|
* Note: suppliers (b1/b2/b3/direct) are seeded via the initial schema
|
|
* migration and delta-migrations — they are expected to already exist in
|
|
* the test database. This case does NOT re-seed suppliers; it only verifies
|
|
* that at least one supplier row with code='b1' is present and seeds
|
|
* pricing_tiers via PricingTierSeeder.
|
|
*
|
|
* phone_ranges are NOT seeded globally. Tests that exercise the region-
|
|
* resolution cascade (Россвязь lookup) should call seedPhoneRange() directly
|
|
* for the specific range their scenario requires.
|
|
*
|
|
* Task 0.5 — Phase 1 Portal Client Imitation Harness.
|
|
* Spec: docs/superpowers/specs/2026-06-03-portal-client-imitation-phase1-design.md
|
|
*/
|
|
abstract class ImitationTestCase extends TestCase
|
|
{
|
|
use DatabaseTransactions;
|
|
use SharesSupplierPdo;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->seedReferenceData();
|
|
}
|
|
|
|
/**
|
|
* Seed shared reference data required by all imitation tests.
|
|
*
|
|
* Called automatically from setUp(). Safe to call multiple times within a
|
|
* transaction (PricingTierSeeder uses updateOrCreate; supplier check is
|
|
* read-only).
|
|
*/
|
|
public function seedReferenceData(): void
|
|
{
|
|
// Pricing tiers — required by LedgerService::chargeForDelivery.
|
|
// PricingTierSeeder uses updateOrCreate so it is safe to call within
|
|
// a DatabaseTransactions-wrapped test.
|
|
$this->seed(PricingTierSeeder::class);
|
|
|
|
// Tenant context: global bypass to allow cross-tenant reads during seeding.
|
|
DB::statement("SELECT set_config('app.current_tenant_id', '0', true)");
|
|
}
|
|
|
|
/**
|
|
* Seed a single phone range for Россвязь prefix lookup tests.
|
|
*
|
|
* Only call this when your specific test scenario exercises the Россвязь
|
|
* branch of LeadRegionResolver (e.g. DaData degradation tests).
|
|
*
|
|
* @param string $defCode DEF-code prefix (e.g. '999').
|
|
* @param string $from Lower bound of number range (e.g. '0000000').
|
|
* @param string $to Upper bound of number range (e.g. '0099999').
|
|
* @param int $subjectCode Subject code (1..89, порядковый, НЕ ГИБДД).
|
|
* Use App\Support\RussianRegions::nameToCode() for lookup.
|
|
*/
|
|
protected function seedPhoneRange(
|
|
int $defCode,
|
|
int $from,
|
|
int $to,
|
|
int $subjectCode,
|
|
): void {
|
|
// Anchor phone_ranges_imports row first — phone_ranges.import_id is a
|
|
// required FK (migration 2026_05_31_100000). F1 fix: the previous version
|
|
// used non-existent columns (range_from/range_to/region_name) and omitted
|
|
// import_id, so every Россвязь-branch test that called it failed at runtime.
|
|
$importId = DB::table('phone_ranges_imports')->insertGetId([
|
|
'imported_at' => now(),
|
|
'source_url' => 'test://rossvyaz',
|
|
'rows_inserted' => 1,
|
|
'rows_updated' => 0,
|
|
'checksum_sha256' => str_repeat('0', 64),
|
|
'status' => 'completed',
|
|
'completed_at' => now(),
|
|
]);
|
|
|
|
DB::table('phone_ranges')->insert([
|
|
'def_code' => $defCode,
|
|
'from_num' => $from,
|
|
'to_num' => $to,
|
|
'operator' => 'test-operator',
|
|
'region' => RussianRegions::CODE_TO_NAME[$subjectCode] ?? 'test-region',
|
|
'region_normalized' => null,
|
|
'subject_code' => $subjectCode,
|
|
'imported_at' => now(),
|
|
'import_id' => $importId,
|
|
]);
|
|
}
|
|
}
|