Перейти к содержанию

DOC-SPC-003. As-built реализация CRM_14

Документ актуализирован по фактической реализации в каталогах backend/ и frontend/. Остальные разделы docs/ описывают требования и проектные решения; этот документ — «как реализовано на самом деле» (as-built) и является источником правды о текущем коде.

Статусы в документе:

  • Реализовано — подтверждено кодом backend/frontend.
  • Частично реализовано — есть код, но не весь заявленный сценарий или требуется внешний контур.
  • Не реализовано — подтверждения в коде не найдено.
  • Требует проверки — код есть, но без проверки внешней среды нельзя подтвердить рабочий сценарий.
  • Заглушка / mock — используется упрощенная или временная реализация.

1. Общее описание проекта

CRM_14 — учебная MVP CRM-система для работы с лидами, стадиями воронки продаж и базовой аналитикой. Проект разделен на два основных приложения:

  • backend/ — API на FastAPI с clean-architecture разбиением на domain/application/infrastructure/interface.
  • frontend/ — SPA на React/Vite с выбором роли, таблицей лидов, канбаном, отчетами и очередью возвратов.

Фактическая реализация не является production CRM. Авторизация упрощена до выбора роли в сессии, данные могут храниться в PostgreSQL, in-memory репозитории или через 1С-адаптер.

2. Назначение системы

Система реализует базовый контур управления лидами:

  • создание лидов;
  • просмотр списка лидов с учетом роли;
  • фильтрацию лидов по владельцу, источнику и периоду создания;
  • отображение лидов в таблице и канбане;
  • перевод лидов по стадиям воронки;
  • фиксацию истории стадий;
  • комментарии к смене стадии;
  • запрос возврата лида на предыдущую стадию;
  • рассмотрение возвратов руководителем отдела продаж;
  • расчет базовых метрик воронки;
  • импорт лидов из CSV/XLSX;
  • экспорт лидов в CSV/XLSX;
  • аудит ключевых действий.

3. Реализованный функционал

Реализовано:

  • выбор роли через backend-сессию;
  • разграничение возможностей по ролям на backend и частично в UI;
  • CRUD-контур лидов: создание, чтение, обновление, удаление;
  • список лидов с фильтрами owner, source_code, date_from, date_to, limit, offset;
  • таблица лидов;
  • канбан по стадиям;
  • ручная смена стадии;
  • возврат на предыдущую стадию через заявку менеджера и решение РОП;
  • история стадий лида;
  • один комментарий на событие стадии;
  • импорт CSV/XLSX;
  • экспорт CSV/XLSX;
  • отчет /reports/summary;
  • audit log для основных мутаций.

Частично реализовано:

  • интеграция с 1С: реализован HTTP-адаптер OneCRepository; проверена на локальном 1С standalone-сервере (ibsrv) в демо-контуре (STORAGE_MODE=1c); промышленный 1С-сервис не подключался;
  • история изменений: сохраняются события стадий, комментарии, заявки возврата и audit log, но нет отдельной универсальной истории изменения каждого поля лида;
  • дата создания лида: отдельного поля created_at в таблице leads нет, frontend/API выводят дату создания как время первой записи стадии new;
  • экспорт отчетности: отдельного endpoint экспорта отчета нет, но XLSX-экспорт лидов содержит лист "Аналитика" с метриками и графиками.

Не реализовано:

  • полноценная регистрация/логин/пароли/JWT;
  • роль администратора;
  • справочники и экран настроек;
  • текстовый поиск по лидам;
  • JSON-импорт;
  • golden-файл и автоматическая сверка golden/funnel.csv;
  • телефония, почта, чат-боты;
  • production-интеграции с внешними CRM/ERP/BI.

4. Роли пользователей

В коде есть четыре роли приложения:

Роль Название в UI Назначение
manager_1 Менеджер 1 Операционная работа только со своими лидами
manager_2 Менеджер 2 Операционная работа только со своими лидами
sales_head Руководитель отдела продаж Управление всеми лидами, возвратами, отчетами и аудитом
analyst Аналитик Просмотр всех лидов, отчетов и экспорт без редактирования

Enum владельцев лидов Users содержит manager_1, manager_2, sales_head. analyst не может быть владельцем лида или автором комментария.

Отдельной роли admin в backend/frontend не найдено.

5. Функционал по ролям

5.1 Администратор

Не реализовано.

В коде не найдено роли администратора, отдельного admin-экрана, управления пользователями, справочниками или системными настройками.

Часть административных возможностей фактически выполняет sales_head: видит все лиды, редактирует, удаляет, экспортирует, смотрит отчеты и audit log.

5.2 Менеджер

Роли manager_1 и manager_2 реализованы одинаково.

Реализовано:

  • выбор роли на стартовом экране;
  • просмотр только своих лидов;
  • создание лида;
  • импорт лидов CSV/XLSX, при котором owner назначается текущим менеджером;
  • перевод своих лидов вперед по цепочке:
new -> qualified -> proposal -> won/lost
  • запрос возврата на предыдущую стадию, если лид не в new;
  • просмотр истории и карточки своих лидов.

Ограничения:

  • менеджер не может редактировать произвольные поля существующего лида через PATCH;
  • менеджер не может удалить лид;
  • менеджер не может экспортировать лиды;
  • менеджер не может смотреть отчеты;
  • менеджер не может видеть чужие лиды;
  • менеджер не может сам вернуть лид назад без заявки и одобрения РОП.

5.3 Руководитель

Роль sales_head реализована как расширенная управленческая роль.

Реализовано:

  • просмотр всех лидов;
  • создание лида с выбором владельца;
  • импорт CSV/XLSX;
  • экспорт CSV/XLSX;
  • редактирование владельца, названия и заметок лида;
  • удаление лидов;
  • произвольная смена стадии, включая закрытые стадии;
  • просмотр отчетов;
  • просмотр audit log через API;
  • просмотр и обработка заявок на возврат;
  • одобрение возврата с фактическим перемещением лида на предыдущую стадию;
  • отклонение возврата без смены стадии.

Ограничения:

  • РОП не создает заявки на возврат, он рассматривает заявки менеджеров;
  • полноценного управления пользователями нет.

5.4 Аналитик

Роль analyst реализована как read-only роль для аналитики.

Реализовано:

  • просмотр всех лидов;
  • просмотр таблицы и канбана;
  • просмотр истории лида;
  • просмотр отчета /reports;
  • экспорт CSV/XLSX.

Ограничения:

  • аналитик не создает лиды;
  • не импортирует лиды;
  • не редактирует и не удаляет лиды;
  • не меняет стадии;
  • не рассматривает возвраты;
  • не имеет доступа к отдельному endpoint /audit-log.

Важно: при открытии карточки лида backend возвращает audit_entries внутри LeadDetailResponse, если пользователь имеет доступ к самому лиду. Это отличается от отдельного endpoint /audit-log, который разрешен только РОП.

6. Функционал по экранам

6.1 Главная страница / Dashboard

Реализовано как экран выбора роли.

Маршрут / показывает стартовую страницу CRM 14 с кнопкой "Выбрать роль". После выбора роли frontend вызывает:

POST /api/v1/session/role

Если сессия уже активна, пользователь перенаправляется на /leads/table.

Отдельный полноценный dashboard как стартовая панель с KPI не реализован. Аналитика вынесена на экран /reports.

6.2 Канбан лидов

Реализовано.

Маршрут:

/leads/kanban

Канбан строит колонки по стадиям:

  • new;
  • qualified;
  • proposal;
  • won;
  • lost.

Карточка лида показывает UID, владельца, название, заметки, источник, кнопку истории и для менеджеров кнопку возврата. Для РОП есть удаление карточки. Drag-and-drop реализован через HTML5 dataTransfer; перед фактическим перемещением вызывается backend endpoint смены стадии.

Ограничения по ролям:

  • аналитик не может перемещать карточки;
  • менеджер может перемещать только вперед по разрешенным переходам;
  • РОП может перемещать в любую другую стадию.

6.3 Список лидов

Реализовано.

Маршрут:

/leads/table

Таблица показывает:

  • lead_uid;
  • название;
  • описание/заметки;
  • источник;
  • текущую стадию;
  • владельца, если роль может видеть всех лидов;
  • действия по роли.

Для ролей с can_read_all_leads доступна панель фильтров:

  • владелец;
  • источник;
  • дата с;
  • дата по.

Текстовый поиск и сортировка колонок в UI не реализованы.

6.4 Карточка лида

Реализована как модальная панель истории.

Отдельного маршрута вида /leads/:id нет. Карточка открывается модально из таблицы или канбана и загружает:

GET /api/v1/leads/{lead_uid}

Панель показывает:

  • владельца;
  • источник;
  • текущую стадию;
  • дату создания, рассчитанную из первой стадии new;
  • историю стадий;
  • комментарии к стадиям;
  • заявки на возврат;
  • audit log по лиду.

6.5 Форма создания / редактирования лида

Реализовано.

Компонент LeadFormModal.jsx используется для создания и редактирования.

Поля формы:

  • название;
  • комментарий/заметки;
  • источник;
  • владелец, если текущая роль может управлять owner.

Создание вызывает:

POST /api/v1/leads

Редактирование вызывает:

PATCH /api/v1/leads/{lead_uid}

Требует проверки / устаревший код: frontend/src/components/AddLeadModal.jsx существует, но не импортируется и не используется текущими маршрутами. Его нельзя считать активной частью интерфейса.

6.6 Отчёт / Воронка продаж

Реализовано.

Маршрут:

/reports

Доступен ролям analyst и sales_head.

Экран вызывает:

GET /api/v1/reports/summary

Показывает:

  • общее количество лидов;
  • количество лидов по текущим стадиям;
  • конверсии между стадиями;
  • среднюю длительность стадий в часах и секундах.

Фильтры:

  • владелец;
  • источник;
  • дата с;
  • дата по.

На экране также есть экспорт CSV/XLSX, но он выгружает лиды через /leads/export, а не отдельный отчетный endpoint.

6.7 Настройки / справочники

Не реализовано.

В frontend нет маршрута настроек и нет UI для редактирования справочников стадий, источников, ролей или пользователей. Стадии, источники и роли зафиксированы enum-ами в backend и массивами опций во frontend.

7. Backend

7.1 Структура backend

Фактическая структура:

backend/
  app/
    main.py
    core/
      auth.py
      config.py
      deps.py
      errors.py
      logging.py
    domain/
      entities.py
      enums.py
      rules.py
    application/
      ports.py
      dtos.py
      use_cases/
    infrastructure/
      memo/
      sql/
      onec/
    interface/
      api/
        schemas.py
        v1/
  alembic/
  tests/
  pyproject.toml
  Makefile
  Dockerfile

Стек backend:

  • Python >=3.12;
  • FastAPI;
  • Uvicorn;
  • Pydantic v2;
  • pydantic-settings;
  • SQLAlchemy async;
  • asyncpg;
  • Alembic;
  • Starlette SessionMiddleware;
  • python-multipart для upload;
  • xlsxwriter для Excel-экспорта;
  • requests для 1С HTTP-адаптера;
  • pytest/httpx для тестов.

7.2 Основные сущности

Доменные сущности:

Сущность Назначение
Lead Основная карточка лида
LeadStageEvent Событие пребывания лида на стадии
LeadComment Комментарий к событию стадии
StageReturnRequest Заявка менеджера на возврат стадии
AuditLogEntry Запись аудита действия

Поля Lead:

  • id;
  • lead_uid;
  • source_code;
  • current_stage;
  • owner;
  • title;
  • notes.

Поля LeadStageEvent:

  • id;
  • lead_id;
  • stage;
  • entered_at;
  • left_at;
  • approved.

Поля StageReturnRequest:

  • id;
  • lead_id;
  • from_stage;
  • to_stage;
  • requested_by;
  • request_comment;
  • requested_at;
  • status;
  • reviewed_by;
  • review_comment;
  • reviewed_at.

Enum-ы:

Enum Значения
LeadStage new, qualified, proposal, won, lost
SourcesCode advertisement, website, recommendation, event, other
Users manager_1, manager_2, sales_head
AppRole manager_1, manager_2, sales_head, analyst
ReturnRequestStatus pending, approved, rejected

PostgreSQL-таблицы по SQLAlchemy/Alembic:

  • leads;
  • leads_stage;
  • leads_comments;
  • stage_return_requests;
  • audit_log.

7.3 API endpoints

Все endpoint-ы имеют prefix /api/v1.

Метод Endpoint Назначение Доступ
GET /health Проверка API и storage mode Без роли
POST /session/role Выбрать роль Без роли
GET /session/me Получить текущую роль Нужна сессия
DELETE /session/role Очистить роль Без роли
GET /leads Список лидов Все роли после выбора роли
POST /leads Создать лид Менеджеры, РОП
POST /new-lead Legacy endpoint создания Менеджеры, РОП
GET /leads/{lead_uid} Детальная карточка С учетом видимости
PATCH /leads/{lead_uid} Обновить owner/title/notes РОП
DELETE /leads/{lead_uid} Удалить лид РОП
POST /leads/{lead_uid}/stage Сменить стадию Менеджер по правилам, РОП произвольно
GET /leads/{lead_uid}/stage История стадий С учетом видимости
GET /leads/{lead_uid}/stages Alias истории стадий С учетом видимости
POST /leads/import Импорт CSV/XLSX Менеджеры, РОП
GET /leads/export Экспорт CSV/XLSX РОП, аналитик
POST /leads/{lead_uid}/return-requests Создать заявку возврата Только менеджеры для своих лидов
GET /return-requests Список заявок РОП
POST /return-requests/{request_id}/approve Одобрить возврат РОП
POST /return-requests/{request_id}/reject Отклонить возврат РОП
GET /reports/summary Метрики воронки РОП, аналитик
GET /audit-log Общий audit log РОП

Параметры /leads:

  • owner;
  • stage;
  • source_code;
  • date_from;
  • date_to;
  • limit от 1 до 200;
  • offset от 0.

Параметры /leads/export:

  • file_type: csv, scv или xlsx; значение scv поддержано как alias/опечатка;
  • owner.

7.4 Бизнес-логика

Создание лида:

  • lead_uid генерируется автоматически;
  • длина UID — 5 символов;
  • алфавит — ASCII letters + digits;
  • при конфликте генерация повторяется до 20 попыток;
  • новый лид всегда создается в стадии new;
  • одновременно создается открытое событие стадии new.

Смена стадии:

  • при переходе закрывается текущее открытое событие стадии через left_at;
  • создается новое событие стадии с entered_at;
  • current_stage обновляется в leads;
  • комментарий сохраняется только если передан.

Правила менеджера:

  • менеджер работает только со своими лидами;
  • менеджер может двигаться только вперед:
new -> qualified
qualified -> proposal
proposal -> won/lost
  • из won и lost менеджер не может двигать лид дальше;
  • возврат назад выполняется только через заявку.

Правила РОП:

  • видит все лиды;
  • может менять стадию на любую другую;
  • может вернуть закрытый лид из won/lost на другую стадию;
  • рассматривает заявки возврата.

Возврат стадии:

  • менеджер создает заявку с обязательным комментарием;
  • target stage определяется автоматически через resolve_previous_stage;
  • нельзя создать вторую pending-заявку по тому же лиду;
  • РОП одобряет или отклоняет заявку с обязательным комментарием;
  • при одобрении backend проверяет, что текущая стадия лида не изменилась с момента заявки;
  • при одобрении лид перемещается на предыдущую стадию;
  • при отклонении стадия не меняется.

7.5 Валидации

Реализовано:

  • Pydantic enum-валидация ролей, стадий, владельцев, источников;
  • title ограничен max_length=255;
  • LeadUpdateRequest требует хотя бы одно поле;
  • owner при обновлении не может быть null;
  • комментарий заявки возврата обязателен и min_length=1;
  • комментарий решения по возврату обязателен и min_length=1;
  • limit ограничен диапазоном 1..200;
  • offset >= 0;
  • импорт проверяет наличие колонок owner, title, notes, source_code, кроме случая менеджера, когда owner может быть подставлен автоматически;
  • импорт проверяет enum-значения через Pydantic;
  • CSV декодируется как utf-8-sig, utf-8 или cp1251;
  • CSV допускает разделители ; и ,;
  • XLSX читается из первой worksheet.

Ограничения:

  • импорт не принимает lead_uid, current_stage, entered_at, left_at;
  • повторный импорт одного и того же файла создаст новые лиды с новыми UID, то есть идемпотентность по lead_uid не реализована;
  • нет проверки lost reason;
  • нет отдельной валидации дат истории при импорте, потому что история стадий не импортируется.

7.6 Обработка ошибок

Backend регистрирует обработчики:

  • AppError возвращает JSON {"detail": ...} со статусом конкретного исключения;
  • NotImplementedError возвращает 501;
  • прочие исключения возвращают 500.

Основные статусы:

  • 400 — общая ошибка приложения или недопустимый переход;
  • 401 — роль в сессии отсутствует или некорректна;
  • 403 — действие запрещено текущей роли;
  • 404 — лид или заявка не найдены;
  • 409 — конфликт, например pending-заявка уже существует или UID занят;
  • 422 — ошибки FastAPI/Pydantic или ошибки импорта.

Frontend показывает ошибки через error-banner и сообщения из detail.

7.7 Импорт и экспорт данных

Импорт:

POST /api/v1/leads/import

Поддерживается:

  • .csv;
  • .xlsx.

Ожидаемые поля:

  • owner;
  • title;
  • notes;
  • source_code.

Для менеджера owner может отсутствовать: backend назначит владельцем текущего менеджера. Для РОП owner должен быть указан в файле.

JSON-импорт не реализован.

Экспорт:

GET /api/v1/leads/export?file_type=csv
GET /api/v1/leads/export?file_type=xlsx

CSV содержит колонки:

  • lead_uid;
  • title;
  • notes;
  • owner;
  • stage;
  • entered_at;
  • source_code.

XLSX содержит:

  • лист Аналитика;
  • лист Данные;
  • метрики;
  • таблицы по стадиям, источникам, менеджерам;
  • графики воронки, длительности, конверсии по источникам и нагрузки менеджеров.

7.8 Расчёт KPI и метрик

Endpoint:

GET /api/v1/reports/summary

Параметры:

  • owner;
  • source_code;
  • date_from;
  • date_to.

Метрики:

  • total_leads;
  • counts — количество лидов по текущей стадии;
  • conversions — конверсии:
  • new -> qualified;
  • qualified -> proposal;
  • proposal -> won;
  • proposal -> lost;
  • average_stage_durations — средняя длительность стадии в секундах и часах.

Особенность расчета:

  • для фильтра периода используется дата создания, полученная из первого события new;
  • для длительности открытых стадий используется разница между текущим временем и entered_at;
  • conversion rate в /reports/summary возвращается в процентах, округленных до 2 знаков.

XLSX-экспорт дополнительно считает:

  • общую конверсию в won;
  • долю lost;
  • неподтвержденные переходы;
  • зависшие лиды в активных стадиях больше 3 дней;
  • конверсию won по источникам;
  • количество лидов по менеджерам;
  • среднюю длительность по менеджерам;
  • активную нагрузку менеджеров.

8. Frontend

8.1 Структура frontend

Фактическая структура:

frontend/
  src/
    App.jsx
    main.jsx
    auth/
      SessionProvider.jsx
    components/
      HomePage.jsx
      LeadsPage.jsx
      LeadsTable.jsx
      LeadsKanban.jsx
      LeadFormModal.jsx
      ImportModal.jsx
      LeadHistoryModal.jsx
      ReportsPage.jsx
      RequestsPage.jsx
      AddLeadModal.jsx
    lib/
      leadsApi.js
      ui.js

Стек frontend:

  • React 19;
  • React DOM 19;
  • Vite 7;
  • react-router-dom 7;
  • plain CSS.

8.2 Страницы

Маршруты:

Route Компонент Доступ
/ HomePage Без роли
/leads/table LeadsPage + LeadsTable Все выбранные роли
/leads/kanban LeadsPage + LeadsKanban Все выбранные роли
/leads Redirect на /leads/table Все выбранные роли
/reports ReportsPage analyst, sales_head
/requests RequestsPage sales_head
* Redirect на / Все

8.3 Компоненты

Активные компоненты:

  • SessionProvider — загружает сессию, выбирает роль, очищает сессию;
  • HomePage — стартовый экран выбора роли;
  • LeadsPage — контейнер таблицы/канбана, фильтры, импорт, экспорт, мутации;
  • LeadsTable — табличное представление лидов;
  • LeadsKanban — канбан по стадиям;
  • LeadFormModal — создание/редактирование лида;
  • ImportModal — загрузка CSV/XLSX;
  • LeadHistoryModal — карточка лида, история, возвраты, audit entries;
  • ReportsPage — отчет по воронке;
  • RequestsPage — очередь возвратов для РОП.

Неиспользуемый компонент:

  • AddLeadModal.jsx — найден в frontend/src/components, но не импортируется текущими экранами.

8.4 Работа с API

Все вызовы API собраны в frontend/src/lib/leadsApi.js.

Базовый URL:

VITE_API_BASE_URL=http://127.0.0.1:8000/api/v1

Если переменная окружения не задана, используется fallback http://127.0.0.1:8000/api/v1.

Запросы выполняются через fetch с:

credentials: 'include'

Это нужно для cookie-сессии mini_crm_session.

Frontend API-клиент реализует:

  • fetchSession;
  • selectRole;
  • clearSession;
  • fetchLeads;
  • fetchLeadDetail;
  • createLead;
  • updateLead;
  • deleteLead;
  • moveLeadStage;
  • requestReturnToPreviousStage;
  • fetchReturnRequests;
  • approveReturnRequest;
  • rejectReturnRequest;
  • fetchReportsSummary;
  • fetchAuditLog;
  • importLeads;
  • exportLeads.

fetchAuditLog есть в API-клиенте, но отдельного экрана общего audit log во frontend не найдено.

8.5 Состояния интерфейса

Реализовано:

  • состояние загрузки сессии;
  • protected routes;
  • redirect при отсутствии роли;
  • redirect при отсутствии доступа к маршруту;
  • загрузка списка лидов;
  • состояние мутации isMutating;
  • error banner;
  • loading panels для лидов, отчетов и заявок;
  • пустые состояния таблицы, канбана и очереди возвратов;
  • модальные состояния формы, импорта и истории.

Ограничения:

  • комментарий к смене стадии вводится через window.prompt, не через полноценную форму;
  • подтверждение удаления через window.confirm;
  • нет глобального toast/notification слоя;
  • нет сохранения фильтров в URL или localStorage.

8.6 Формы, таблицы, канбан

Формы:

  • выбор роли;
  • создание/редактирование лида;
  • импорт файла;
  • комментарий РОП к approve/reject возврата;
  • prompt-комментарий к смене стадии;
  • prompt-комментарий к заявке возврата.

Таблицы:

  • таблица лидов;
  • таблица конверсий;
  • таблица средней длительности стадий.

Канбан:

  • группировка по current_stage;
  • счетчик лидов в колонке;
  • drag-and-drop смена стадии;
  • отображение доступных переходов;
  • блокировка перемещения для аналитика.

9. Данные и модели

Основная модель данных строится вокруг лида и истории стадий.

leads:

  • хранит текущую карточку и текущую стадию;
  • не хранит created_at;
  • не хранит сумму сделки, телефон, email, lost reason.

leads_stage:

  • хранит историю стадий;
  • текущее событие имеет left_at = null;
  • содержит флаг approved, но текущая логика создает stage events с approved=True.

leads_comments:

  • привязана к stage event;
  • уникальность по stage_event_id;
  • фактически один комментарий на событие.

stage_return_requests:

  • хранит управляемый процесс возврата стадии.

audit_log:

  • хранит события действий с actor_role, action_type, JSON payload и временем.

10. KPI и аналитика

Реализовано в API и UI:

  • количество лидов всего;
  • количество лидов по стадиям;
  • конверсия между основными переходами;
  • средняя длительность стадий.

Реализовано в XLSX-экспорте:

  • воронка продаж;
  • средняя длительность стадий в днях;
  • конверсия по источникам;
  • лиды по менеджерам;
  • средняя длительность по менеджеру;
  • нагрузка менеджеров по активным стадиям;
  • количество зависших лидов больше 3 дней;
  • графики.

Не реализовано:

  • отдельный экран с графиками;
  • сравнение с golden/funnel.csv;
  • прогнозирование продаж;
  • когортный анализ;
  • причины отказов.

11. История изменений и логирование

История стадий реализована через leads_stage:

  • при создании лида создается стадия new;
  • при переходе закрывается предыдущая стадия и создается новая;
  • история доступна через /leads/{lead_uid}/stage и /leads/{lead_uid}/stages;
  • детальная карточка лида включает stage_info.

Комментарии:

  • сохраняются к новой стадии при смене стадии, если передан comment;
  • при approve возврата комментарий РОП сохраняется как комментарий к stage event.

Audit log реализован для действий:

  • lead_created;
  • lead_created_legacy;
  • lead_imported;
  • lead_deleted;
  • lead_updated;
  • lead_stage_changed;
  • return_request_created;
  • return_request_approved;
  • return_request_rejected.

Отдельный общий endpoint /audit-log доступен РОП. Детальная карточка лида также возвращает последние audit entries по конкретному лиду.

12. Интеграции и моки

Режимы хранения задаются STORAGE_MODE:

  • postgres — PostgreSQL через SQLAlchemy async;
  • memo — in-memory репозиторий для тестов/демо;
  • 1c — HTTP-адаптер к 1С.

PostgreSQL:

  • основная persist-реализация;
  • миграция Alembic создает таблицы и enum-ы.

Memo:

  • хранит данные в памяти процесса;
  • используется в smoke-тестах;
  • данные пропадают после перезапуска.

1С:

  • в коде есть OneCRepository, который читает/пишет лиды через HTTP endpoints /leads;
  • локально хранит синтетические stage events, comments, return requests и audit entries;
  • удаление лидов через 1С-адаптер не поддержано;
  • проверена на локальном 1С standalone-сервере (ibsrv) в демо-контуре; промышленный 1С-сервис не подключался.

REST-моки как отдельные mock endpoints не найдены. Режим memo можно использовать как демонстрационное in-memory хранилище, но это не отдельный REST-mock слой.

13. Ограничения текущей реализации

  • Упрощенная авторизация: роль выбирается пользователем вручную.
  • Нет пользователей, паролей, регистрации и JWT.
  • Session cookie используется для хранения роли.
  • CORS в app.main фактически разрешен через allow_origin_regex=".*", несмотря на наличие настройки CORS_ALLOWED_ORIGINS.
  • Нет роли администратора.
  • Нет справочников и настроек.
  • Нет текстового поиска.
  • Нет импорта истории стадий.
  • Нет JSON-импорта.
  • Импорт не идемпотентен по lead_uid.
  • Нет отдельного created_at у лида в БД.
  • Нет суммы сделки и финансовых полей.
  • Нет контактных данных клиента.
  • Нет причины проигрыша lost_reason.
  • Нет полноценного журнала изменения всех полей.
  • AddLeadModal.jsx не используется.
  • Frontend не содержит отдельного экрана общего audit log.
  • 1С-интеграция проверена на локальном учебном 1С-сервере (ibsrv); промышленный 1С-контур не подключался.

14. Нереализованный функционал

Функция описана в исходной документации, но в текущей реализации не обнаружена:

  • администратор;
  • управление пользователями;
  • редактирование справочников;
  • JSON-импорт;
  • импорт истории стадий из отдельного файла;
  • идемпотентная повторная загрузка по lead_uid;
  • golden-сверка;
  • экспорт отдельного отчета с колонками stage, leads_cnt, conv_from_prev;
  • текстовый поиск;
  • сортировка колонок в таблице;
  • отдельная карточка лида как маршрут;
  • полноценный dashboard на главной странице;
  • реальные коммуникационные интеграции;
  • работа с персональными данными клиента;
  • сделки, счета, документы продаж.

15. Функционал в разработке

Явных feature flags или TODO-статусов в коде для функций "в разработке" не найдено. По структуре проекта можно считать требующими дальнейшей доработки:

  • 1С-адаптер и проверка реального обмена;
  • импорт с поддержкой lead_uid и идемпотентности;
  • экран общего audit log;
  • удаление устаревшего AddLeadModal.jsx или его приведение к текущему API;
  • синхронизация документации docs/ с текущими файлами PROJECT_DOCUMENTATION.md и DOCUMENTATION_AUDIT.md.

16. Инструкция запуска проекта

16.1 Запуск backend

Требования:

  • Python 3.12+;
  • uv;
  • PostgreSQL, если используется STORAGE_MODE=postgres.

Команды:

cd backend
uv sync
cp .env.example .env
make migrate
make run

API:

http://localhost:8000

Swagger:

http://localhost:8000/docs

ReDoc:

http://localhost:8000/redoc

Проверки:

cd backend
make test
make lint

16.2 Запуск frontend

Требования:

  • Node.js;
  • npm.

Команды:

cd frontend
npm ci
npm run dev

Frontend по умолчанию запускается Vite dev server на:

http://localhost:5173

Сборка:

cd frontend
npm run build

16.3 Переменные окружения

Backend .env.example:

STORAGE_MODE=postgres
DATABASE_URL=postgresql+asyncpg://postgres:postgres@127.0.0.1:5432/mini_crm_simple
LOG_LEVEL=INFO
SESSION_SECRET=mini-crm-simple-dev-secret
CORS_ALLOWED_ORIGINS=http://127.0.0.1:5173,http://localhost:5173
SESSION_HTTPS_ONLY=false

Frontend .env.example:

VITE_API_BASE_URL=http://localhost:8000/api/v1

Docker Compose из корня проекта поднимает:

  • postgres;
  • backend;
  • frontend.

Команда:

docker compose up --build

Особенность: backend/docker-compose.yml отдельно запускает только backend и по умолчанию использует STORAGE_MODE=memo.

17. Сценарий демонстрации

Рекомендуемый сценарий, соответствующий текущей реализации:

  1. Запустить backend и frontend.
  2. Открыть /.
  3. Выбрать роль manager_1.
  4. Создать лид через "Добавить лид".
  5. Показать, что лид появился в таблице в стадии new.
  6. Перейти в канбан и показать карточку в колонке Новый.
  7. Перевести лид в qualified с комментарием.
  8. Открыть "История" и показать стадии, дату создания и комментарий.
  9. Создать заявку на возврат.
  10. Сменить роль на sales_head.
  11. Открыть "Запросы" и одобрить заявку с комментарием.
  12. Вернуться к лиду и показать, что стадия изменилась назад.
  13. Открыть "Отчёты" и показать counts, conversions, average durations.
  14. Выполнить экспорт CSV и XLSX.
  15. Сменить роль на analyst и показать read-only доступ к лидам/канбану/отчетам.

18. Acceptance-критерии текущей реализации

ID Критерий Статус
AC-01 Пользователь выбирает роль и попадает в интерфейс Реализовано
AC-02 Менеджер видит только свои лиды Реализовано
AC-03 Менеджер создает лид в стадии new Реализовано
AC-04 История стадии new создается вместе с лидом Реализовано
AC-05 Менеджер переводит new -> qualified Реализовано
AC-06 Менеджер переводит qualified -> proposal Реализовано
AC-07 Менеджер переводит proposal -> won/lost Реализовано
AC-08 Менеджер не возвращает стадию напрямую Реализовано
AC-09 Менеджер создает заявку возврата Реализовано
AC-10 РОП одобряет возврат Реализовано
AC-11 РОП отклоняет возврат Реализовано
AC-12 Аналитик видит лиды и отчеты без редактирования Реализовано
AC-13 Импорт CSV/XLSX создает лиды Реализовано
AC-14 Повторный импорт не создает дубли по lead_uid Не реализовано
AC-15 Экспорт CSV формируется Реализовано
AC-16 Экспорт XLSX формируется с аналитикой и данными Реализовано
AC-17 Отчет показывает конверсии Реализовано
AC-18 Отчет показывает среднюю длительность стадий Реализовано
AC-19 Сверка с golden-файлом Не реализовано
AC-20 Администратор управляет справочниками Не реализовано

19. Краткий вывод

Текущая CRM_14 реализует рабочий учебный контур лидов, ролей, стадий, возвратов, импорта, экспорта и базовой аналитики. Реализация заметно шире простого REST-мока: есть backend API, ролевая матрица, PostgreSQL-модель, in-memory режим, 1С-адаптер, frontend-экраны и smoke-тесты.

Главные ограничения перед защитой: отсутствие полноценной авторизации, администратора, справочников, поиска, JSON-импорта, golden-сверки и идемпотентности импорта по lead_uid. Эти ограничения нужно явно проговаривать как границы текущего MVP, а не как реализованные функции.