Files
portal/app/tests
Дмитрий 8fc9d3ec8a feat(supplier): Plan 3 Task 4 — SupplierPortalClient HTTP-обёртка над rt-*
Компоненты:
- SupplierProjectDto (readonly DTO, fromModel + equals)
- SupplierException иерархия (Auth/Transient/Client + abstract base)
  - SupplierAuthException: 401/403 sticky после refresh-retry
  - SupplierTransientException: 5xx/network/timeout (retryable)
  - SupplierClientException: 4xx 400/404/422 (наша ошибка payload)
- SupplierPortalClient: list/save/update/delete projects через Http facade
  + Redis cache cookie/CSRF (key 'supplier:session', TTL 6h)
  + auto-retry на 401/403 через dispatch_sync(RefreshSupplierSessionJob)
  + classification HTTP errors → 3 exception types
- RefreshSupplierSessionJob stub (handle() пустой; full impl в Task 5)
- config/services.supplier (login/password/portal_url/alert_email)

+9 тестов через Http::fake() в Unit/Supplier/SupplierPortalClientTest.php:
- cookie/CSRF attach
- 401 retry flow (single retry, sticky 401 → SupplierAuthException)
- 5xx → SupplierTransientException
- 4xx → SupplierClientException
- network error → SupplierTransientException
- save/update/delete payload shapes + responses

NOTE: toPayload() shape — placeholder; точные поля адаптируются
после Task 1 discovery + Task 2 spec §4.4 (отдельный fixup commit
перед Task 6 при расхождении наблюдаемого формата с предполагаемым).
2026-05-11 06:46:13 +03:00
..