From 36ea9cde049c47760de9d0ab14d64f7738858471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Mon, 18 May 2026 14:33:33 +0300 Subject: [PATCH] =?UTF-8?q?feat(deals):=20=D1=83=D0=B1=D1=80=D0=B0=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BF=D1=80=D0=B5=D1=84=D0=B8=D0=BA=D1=81=20B1=5F/B2?= =?UTF-8?q?=5F/B3=5F=20=D0=B8=D0=B7=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20=C2=AB=D0=98=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D1=87=D0=BD=D0=B8=D0=BA=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Поставщик crm.bp префиксует имена проектов признаком канала-провайдера (B1_/B2_/B3_ — три базы лидов). В UI Лидерры префикс — шум: пользователю интересен сам проект, не канал. Трансформация display-only — данные в БД не трогаем, фильтрация идёт по project_id (не name). Утилита: app/resources/js/composables/projectName.ts → stripChannelPrefix. Регэксп ^B[123]_ case-insensitive; null/undefined/'' → ''. Применено в 4 точках: - DealsTable «Источник» (item.project) - DealsFilters «Проект» dropdown (через computed-маппинг в DealsView) - KanbanCard карточка - DealDetailBody параметры панели Тесты: 8 unit-тестов на утилиту (B1/B2/B3 case-insensitive, не трогать B0/B4/Bx, не трогать префикс в середине строки, null/undefined/''), 38/38 на затронутых компонентах, 868/3sk/0 full Vitest, build 2.62s. Smoke /deals: 20 строк, ни одна не начинается с B1_/B2_/B3_ (был «B1_73912557675 [35]», стал «73912557675 [35]»; «B3_krk-finance.ru/...» → «krk-finance.ru/...»). Скриншот deals-no-bprefix-2026-05-18.png. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../js/components/deals/DealDetailBody.vue | 3 +- .../js/components/deals/DealsTable.vue | 3 +- .../js/components/kanban/KanbanCard.vue | 3 +- app/resources/js/composables/projectName.ts | 22 +++++++++ app/resources/js/views/DealsView.vue | 8 +++- app/tests/Frontend/projectName.spec.ts | 46 +++++++++++++++++++ 6 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 app/resources/js/composables/projectName.ts create mode 100644 app/tests/Frontend/projectName.spec.ts diff --git a/app/resources/js/components/deals/DealDetailBody.vue b/app/resources/js/components/deals/DealDetailBody.vue index dec04b43..3b8903b8 100644 --- a/app/resources/js/components/deals/DealDetailBody.vue +++ b/app/resources/js/components/deals/DealDetailBody.vue @@ -10,6 +10,7 @@ import { computed, defineAsyncComponent, ref, watch } from 'vue'; import type { MockDeal } from '../../composables/mockDeals'; import { type DealEvent } from '../../composables/mockDealEvents'; import { mapApiDealEvent } from '../../composables/dealsApiMapper'; +import { stripChannelPrefix } from '../../composables/projectName'; import * as dealsApi from '../../api/deals'; import * as remindersApi from '../../api/reminders'; import type { ApiReminder } from '../../api/reminders'; @@ -162,7 +163,7 @@ defineExpose({
Проект
-
{{ deal.project }}
+
{{ stripChannelPrefix(deal.project) }}
Стоимость лида
diff --git a/app/resources/js/components/deals/DealsTable.vue b/app/resources/js/components/deals/DealsTable.vue index ed0872c7..207f1958 100644 --- a/app/resources/js/components/deals/DealsTable.vue +++ b/app/resources/js/components/deals/DealsTable.vue @@ -6,6 +6,7 @@ */ import type { MockDeal } from '../../composables/mockDeals'; import type { LeadStatus } from '../../composables/leadStatuses'; +import { stripChannelPrefix } from '../../composables/projectName'; import StatusPill from '../ui/StatusPill.vue'; const props = withDefaults( @@ -71,7 +72,7 @@ function rowProps(deal: MockDeal): Record {