Commit Graph

4 Commits

Author SHA1 Message Date
Дмитрий 789e7dcdb6 feat(deals/drawer): убрать «Менеджер», добавить «Тип» + «Источник» read-only
UX-request 18.05.2026 (пп.4/6/7):
- удалена секция «Менеджер»/«Не назначен» (менеджеров в системе пока нет)
- добавлен параметр «Тип» (Сайт/Звонок/СМС) — project.signal_type
- добавлен параметр «Источник» (read-only):
  - site/call → project.signal_identifier (домен или телефон)
  - sms → sms_senders[0] + ' (KEYWORD)' если sms_keyword не пустой
- удалён hardcoded «Я.Директ → landing-1»

Backend: DealController index + show + update payload расширены 4 полями
project_signal_type/identifier/sms_keyword/sms_senders + eager-load
project relation расширен.

Редактирование источника — только в карточке проекта (Task 5 плана).

Larastan baseline bumped (DealShowTest: tenant 13→20, getJson 7→10 для 3 новых тестов).
Pest 51/51 на Deal-endpoints.
Vitest 108 files / 875 passed / 3 skipped (5 новых тестов DealDetailBody).
Build 2.30s.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 15:24:57 +03:00
Дмитрий b4138bbc82 feat(deals): sweep 14->5 funnel slugs — controllers, mocks, stories, tests 2026-05-18 03:42:41 +03:00
Дмитрий 447ef593fa feat(api): J1 — auth:sanctum+tenant middleware на /api/deals*
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:18:13 +03:00
Дмитрий cba76c5d18 phase2(deal-show): GET /api/deals/{id} + DealDetailDrawer на реальный ActivityLog
Закрывает gap «timeline в drawer'е показывает hard-coded MOCK_EVENTS» —
теперь drawer fetch'ит реальные activity-events на open из tenant-filtered
activity_log. Без tenant_id — fallback на MOCK_EVENTS как раньше.

Backend (DealController::show):
- GET /api/deals/{id}?tenant_id={id} — возвращает {deal, events}.
- Deal extended (project_name, manager_name/initials, comment, assigned_at).
- Events — последние 50 записей activity_log по (tenant_id, deal_id)
  ORDER BY created_at DESC, с актором (user через belongsTo).
- RLS-обёртка + defense-in-depth where(tenant_id) — 404 если чужая.

Pest +8 (DealShowTest):
- 422/404 базовые / 404 чужая сделка / deal-relations / events ORDER BY +
  actor + actor=null для system-event / RLS+app-фильтр изоляция событий /
  лимит 50 событий.

Frontend:
- api/deals.ts::getDeal — типизированный helper c ApiDealEvent/Detail/Response.
- composables/dealsApiMapper.ts::mapApiDealEvent — converter ApiDealEvent →
  DealEvent: clamp event-slug на known types с fallback на 'deal.viewed';
  detail зависит от type (status_changed: 'from → to'; created: source;
  остальные: JSON-сводка context).
- DealDetailDrawer: optional tenantId prop, watch([open, deal.id, tenantId])
  с immediate=true → loadEvents() на open. Reject → eventsFetchError +
  v-alert warning + MOCK_EVENTS fallback.
- DealsView/KanbanView передают :tenant-id="auth.user?.tenant_id".

Vitest +4 (DealDetailDrawerApi.spec.ts):
- Без tenantId — getDeal не вызывается + MOCK_EVENTS видны.
- С tenantId — getDeal + events замещены + 'new → paid' виден.
- reject → fetchError + alert + MOCK_EVENTS fallback.
- open=false → getDeal не вызывается.

PHPStan baseline регенерирован.

Регресс:
- Lint+type-check+format passed.
- Vitest 273/273 за 20.76 сек (+4 от 269).
- Vite build 1.12 сек.
- Pint + PHPStan passed.
- Pest 205/205 за 24.19 сек (+8 от 197, 812 assertions).

Реестр v1.62→v1.63 / CLAUDE.md v1.53→v1.54.

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