Дмитрий
e8db184e99
feat(slepok): Task 2.5 — LeadRouter reads from project_routing_snapshots (R-01 closure)
...
LeadRouter SQL переписан на JOIN с project_routing_snapshots по active_slepok_date:
до 21:00 МСК = today, после 21:00 МСК = today+1. is_active / delivery_days_mask /
daily_limit / regions / signal_type / signal_identifier берутся из snapshot.
Из live projects — только delivered_today (счётчик остатка лимита). Из tenants —
balance_rub (live auto-pause при нулевом балансе).
Active snapshot date вычисляется в PHP (метод activeSnapshotDate()) и
передаётся в SQL как параметр — тестируемо через Carbon::setTestNow,
исключает дрейф между PHP- и DB-часами.
Fail-loud: Log::error('lead_router.no_snapshot_for_active_date', ...) если
по активной дате слепка вообще нет ни одной строки snapshot'а (cron не отработал).
Closes R-01, R-04, R-06, R-07, R-08, R-15.
Partial: R-02 (через шеринг), R-09 (race), R-10 (editable identifier) — закрываются Task 2.6+.
Plan: docs/superpowers/plans/2026-05-26-slepok-routing-protection.md §Task 2.5
Spec: docs/superpowers/specs/2026-05-26-slepok-routing-protection-design.md §4.2.3
Tests added:
- tests/Feature/LeadRouter/SnapshotRoutingTest.php (4 tests, all GREEN locally)
Tests patched (downstream — добавлен createRoutingSnapshotFromProject() helper):
- tests/Pest.php — global helper createRoutingSnapshotFromProject()
- tests/Feature/LeadRouter/BalanceFilterTest.php (2/2 GREEN)
- tests/Feature/Services/LeadRouterTest.php (10/10 GREEN)
- tests/Feature/Jobs/RouteSupplierLeadJobTest.php (14/14 GREEN)
- tests/Feature/Supplier/DirectPlatformTest.php (6/6 GREEN)
- tests/Feature/Supplier/RouteSupplierLeadJobBillingTest.php (3/3 GREEN)
- tests/Feature/Supplier/SupplierConnectionTest.php (5/5 GREEN)
- tests/Feature/Integration/SupplierLeadFlowTest.php (2/2 GREEN)
- tests/Feature/Pd/DealCreatePdLogTest.php (2/2 GREEN)
Each test file isolated regression: GREEN. Combined run 49/50 with 1 flake on
quirk #77 (Faker unique domainName + cross-connection pgsql/pgsql_supplier
DatabaseTransactions scope mismatch) — pre-existing, NOT regression от Task 2.5.
Patched via 7 parallel Sonnet subagents per Pravila §15.1; controller-verified
isolated + combined regression (latter caught 1 subagent over-application:
paused project in SupplierLeadFlowTest получил snapshot, что нарушило логику
теста — fixed inline, по semantic match with SnapshotBackfillCommand SQL
WHERE p.is_active = true).
2026-05-28 05:48:15 +03:00
Дмитрий
a3151b7809
fix(billing-v2): regression — A.5 downstream tests use rub balance arrange
2026-05-23 18:46:22 +03:00
Дмитрий
95ee6644f7
fix(tests): sync 3 stale эпик-тестов + schema.sql header под Plans 1-3 (v8.26)
...
Три pre-existing красных теста (ЭТАЛОН §6 «deferred») приведены к реальной
схеме v8.26 после project-migration-redesign Plans 1-3:
- SchemaDeltaTest: 64→65 base tables, 121→123 indexes (project_supplier_links
pivot + supplier_projects_platform_key_subject_unique).
- SupplierProjectsAccessTest: unique-constraint (platform, unique_key) →
(platform, unique_key, subject_code) — per-субъект экспорт (Plan 1).
- SupplierLeadFlowTest: routing eligibility теперь через pivot
project_supplier_links (LeadRouter), не legacy supplier_b1_project_id —
добавлены linkProjectToSupplier() связи.
- schema.sql header: v8.25→v8.26 + метрики (CHANGELOG уже содержал v8.26).
Production-код не менялся — тесты отставали от уже-смердженных Plans 1-3.
Pest full 1013/1010 passed/3 skipped/0 failed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-20 19:23:13 +03:00
Дмитрий
e401491947
feat(supplier): Plan 4 Task 4 — integrate LedgerService в RouteSupplierLeadJob + Task 3 carry-overs
...
Task 4 — integration:
- handle() / createDealCopyForProject() — +5-й параметр LedgerService.
- Заменён старый balance_leads-- + BalanceTransaction блок на
\$ledger->chargeForDelivery(\$tenant, \$deal, \$lead) с try/catch для
InsufficientBalanceException (Log::warning + rethrow; auto-pause flow
в Task 6).
- LeadRouter::matchEligibleProjects — расширен фильтр tenant balance с
(balance_leads > 0) на (balance_leads > 0 OR balance_rub > 0), чтобы
rub-only tenant дошёл до LedgerService (single arbiter for dual-balance).
- 4 E2E теста в tests/Feature/Supplier/RouteSupplierLeadJobBillingTest.php:
prepaid charge + BalanceTransaction (carry-over M-2), rub charge + BT,
supplier_lead_costs gap-fix (2 deal-копии), retry idempotency.
Plan 4 Task 3 carry-overs (минорные правки по code-review d2030f9 ):
- I-2: PHPDoc на LedgerService::chargeForDelivery — @throws + @precondition
(caller wraps в DB::transaction с lockForUpdate Tenant).
- I-4: trim() на raw_payload['project'] в resolveSupplierId (defense
against whitespace).
Прочие правки:
- tests/Feature/Jobs/RouteSupplierLeadJobTest.php — +PricingTierSeeder
в beforeEach + +5-й LedgerService параметр в runRouteJob().
- tests/Feature/Integration/SupplierLeadFlowTest.php — +PricingTierSeeder
в beforeEach (test использует full webhook→job pipeline).
- tests/Feature/Services/LeadRouterTest.php — rename теста про balance_leads
→ \"zero in BOTH balance_leads AND balance_rub\" + новый тест
\"rub-only tenant ДОЛЖЕН пройти\".
- phpstan-baseline.neon — +5 entries для TestCall::seed() + Tenant/LeadCharge
property.notFound в новых файлах (IDE helper @mixin re-generation —
отдельная задача).
Метрики: Pint clean, PHPStan 0 errors, Pest 646/643+3 skipped/0 failed
(21.1s parallel). Plan 4 Task 4 закрыт.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-11 10:06:38 +03:00
Дмитрий
8c70255d2b
fix(supplier): Plan 3 Task 3 code-review fixes (4 Important + 3 Minor)
...
Закрывает 4 Important issues из code-review Task 3 (6d6181b ):
- config/database.php: inline 11-key duplication заменён на single-source
pattern через локальную переменную $pgsqlConnection (config() внутри
config-файла не работает — Repository ещё не bootstrap'нут); 'pgsql' и
'pgsql_supplier' теперь оба ссылаются на $pgsqlConnection; PDO options
block с string-key _role_purpose удалён (PDO ждёт integer ATTR_* keys)
- tests/Concerns/SharesSupplierPdo.php (новый): trait для cross-connection
PDO visibility в DatabaseTransactions; setUp override из TestCase.php
удалён (был global на 562 теста, forced eager PDO connect);
trait применён к 5 supplier-flow тестам: SupplierConnectionTest,
LeadRouterTest, RouteSupplierLeadJobTest, ResetDeliveredTodayCommandTest,
SupplierLeadFlowTest (все нуждаются в cross-connection видимости)
- phpstan-baseline.neon: entry для Pest TestCall->artisan() в
SupplierConnectionTest заменён на inline @phpstan-ignore-next-line
— local + self-documenting; добавлен baseline-entry для
SharesSupplierPdo trait.unused (PHPStan не видит Pest uses() как trait usage)
Plus 3 Minor:
- typos 'dafault'/'corretly' (удалились с setUp override из TestCase.php)
- RouteSupplierLeadJob.php PHPDoc: \$connection → DB_CONNECTION консистентность
Pest: 562 tests, 560 passed + 2 skipped (без regression). PHPStan: 0 errors. Pint: clean.
2026-05-11 01:26:24 +03:00
Дмитрий
b6b5b0bc1f
test(integration): supplier webhook → N deals end-to-end (sharing-model)
...
Полный сценарий: 1 webhook на B1_vashinvestor.ru → 3 deal-копии у 3 активных
tenant'ов + счётчики + balance. Paused tenant пропущен. Orphan supplier_project
создаёт stub, processed_at установлен, deals_created_count=0.
Запуск через Laravel sync queue (default test env) — без Bus::fake().
Spec §5-§6 e2e validation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-10 19:43:44 +03:00