activeDate()]) * для перестройки project_routing_snapshots за активную дату. * * Механизм выбора (per README §4): * «Для живого портала (Task 14) — `php artisan snapshot:rebuild --date=` * (DELETE+INSERT, детерминированно)». * * В тестах `rebuild()` вызывается статически ПОСЛЕ создания проекта (фабрика), * до вызова LeadRouter. SnapshotRebuildCommand работает через pgsql_supplier * (BYPASSRLS crm_supplier_worker) — совместимо с SharesSupplierPdo. * * activeDate() возвращает строку 'YYYY-MM-DD' — ровно то, что LeadRouter передаёт * в SQL WHERE snap.snapshot_date = ?::date. * * Task 3 — Phase 1 Portal Client Imitation Harness. * Spec: docs/superpowers/specs/2026-06-03-portal-client-imitation-phase1-design.md */ final class SnapshotForge { /** * Активная дата слепка — зеркало LeadRouter::activeSnapshotDate(). * * До 21:00 МСК — сегодня, с 21:00 МСК — завтра (§4.2.3). * * Возвращает строку 'YYYY-MM-DD' (как LeadRouter передаёт в SQL). */ public static function activeDate(): string { $msk = Carbon::now('Europe/Moscow'); return $msk->hour >= 21 ? $msk->copy()->addDay()->toDateString() : $msk->toDateString(); } /** * Перестраивает project_routing_snapshots за активную дату из live-проектов. * * Использует команду `snapshot:rebuild --date=` (DELETE+INSERT), * которая отбирает все active + unfrozen проекты с подходящим delivery_days_mask * и вставляет строки в project_routing_snapshots. * * Вызывать ПОСЛЕ создания тестовых проектов (фабрика) — команда читает * projects из БД на момент вызова. */ public static function rebuild(): void { Artisan::call('snapshot:rebuild', [ '--date' => self::activeDate(), ]); } }