Files
portal/docs
Дмитрий 2d9e84ef1d phase1(antifraud): DuplicateDetector сервис (Биз-19) — антифрод-дедуп по phone в окне 24ч
Закрыт Биз-19 (§10.8.1) на код-уровне. При создании НОВОЙ сделки сервис
DuplicateDetector ищет master по (tenant_id, phone) в окне 24 ч. Если
найден — новой сделке проставляется duplicate_of_id = master.id, баланс
НЕ списывается, SupplierLeadCost НЕ создаётся. ActivityLog пишется с
context.duplicate_of = master.id.

Реализация:
  - app/app/Services/DuplicateDetector.php — отдельный сервис:
    findMaster(tenantId, phone, ?Carbon $now): ?Deal. Ищет deals с
    duplicate_of_id IS NULL и received_at >= now - 24h. Возвращает
    первую по received_at ASC или null. WINDOW_HOURS = 24 — константа.
  - App\Jobs\ProcessWebhookJob::handle() — после upsertDeal() для новой
    сделки вызывает findMaster(). Если master !== создаваемая сделка —
    markAsDuplicate(): UPDATE duplicate_of_id + ActivityLog с context.
  - DI через app(DuplicateDetector::class) внутри handle() (не в
    сигнатуре — для совместимости с прямыми вызовами из Pest без
    Bus::dispatchSync).

4 новых Pest-теста:
  - master в окне 24ч → дубль, баланс НЕ списывается
  - master старше 24ч → НЕ дубль, баланс списан дважды
  - дубли изолированы по tenant_id
  - ActivityLog для дубля содержит context.duplicate_of

Pest 41/41 зелёные за 4.1 сек. Pint + Larastan чисто.

CLAUDE.md v1.13 → v1.14. Реестр Открытые_вопросы v1.22 → v1.23.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:41:37 +03:00
..