Files
portal/app/resources/views/emails/csv_drift_alert.blade.php
T
Дмитрий deca81c2d7 feat(supplier): Plan 4 Task 8 — CsvReconcileJob hourly + drift>5% email + supplier_csv_reconcile_log
CsvReconcileJob — hourly резерв-канал приёма лидов через CSV-экспорт поставщика:
- Cache::lock 600s (overlap protection).
- Окно [now-25h, now] (запас 1ч над hourly cron).
- INSERT supplier_csv_reconcile_log status='running' → 'ok' | 'drift_alert' | 'failed'.
- Missing vids → INSERT supplier_leads (platform extracted из project, source='csv_recovery',
  recovered_from_csv_at=now) + dispatch RouteSupplierLeadJob.
- Drift > 5% → CsvDriftAlertMail на services.supplier.alert_email.
- UNIQUE-vid conflict → log + skip (idempotency).
- На SupplierTransientException/любой Throwable → status='failed', error_message, rethrow.

CsvDriftAlertMail + blade-template emails/csv_drift_alert.

routes/console.php — Schedule::job(new CsvReconcileJob)->hourly().
config/services.php — supplier.alert_email default 'ops@liderra.ru'.

6 integration tests (CsvReconcileJobTest) + Schedule registration test (через
Http::fake + Bus::fake + Mail::fake + SharesSupplierPdo trait для cross-connection).

Parallel-test race fix: putSupplierSession() вызывается прямо перед SUT, потому
что Sync/Cleanup tests'ы в afterEach делают forget('supplier:session'), а в
--parallel режиме воркеры делят Redis DB+prefix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 11:04:49 +03:00

16 lines
872 B
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ru">
<head><meta charset="UTF-8"><title>CSV drift alert</title></head>
<body style="font-family: Arial, sans-serif;">
<h3>Расхождение CSV-сверки с базой Лидерры</h3>
<p>Окно: <strong>{{ $windowStart->format('Y-m-d H:i') }} {{ $windowEnd->format('Y-m-d H:i') }}</strong></p>
<ul>
<li>Всего строк в CSV: <strong>{{ $totalCsvRows }}</strong></li>
<li>Пропущено webhook'ом (recovered): <strong>{{ $missingCount }}</strong></li>
<li>Восстановлено в БД: <strong>{{ $recoveredCount }}</strong></li>
<li>Drift ratio: <strong>{{ number_format($driftRatio * 100, 2, ',', ' ') }}%</strong> (порог 5%)</li>
</ul>
<p>Подробности в таблице <code>supplier_csv_reconcile_log.id = {{ $reconcileLogId }}</code>.</p>
</body>
</html>