Бетон CRM: Новые фишки

Beton CRM: От идеи до production — как мы создали современную систему управления заказами

Расскажу о разработке полнофункциональной CRM-системы для управления заказами бетона с интеграцией Bitrix24.
В процессе создания проекта мы внедрили множество интересных технических решений, включая Elasticsearch для
молниеносного поиска, периодические заявки, динамические формы и многое другое.

Что мы построили

Beton CRM — это полноценная система управления заказами на бетон с веб-интерфейсом,
которая решает реальные бизнес-задачи:

  • Прием и обработка заказов через динамические формы
  • Интеграция с Bitrix24 для управления сделками
  • Молниеносный поиск по всей базе заказов и клиентов
  • Создание периодических заявок (например, ежедневные поставки на месяц)
  • Адаптивный интерфейс для мобильных устройств и десктопа

Elasticsearch: Умный поиск на стероидах

Одна из самых интересных фич проекта — это система поиска на базе Elasticsearch.
Мы не просто добавили поиск, а создали интеллектуальную систему с множеством продвинутых возможностей.

Что умеет наш поиск:

1. Адаптивные стратегии поиска

Система автоматически выбирает оптимальную стратегию поиска в зависимости от длины запроса:

  • Короткие запросы (<5 символов): Агрессивный fuzzy-поиск с автокомплитом и высокой толерантностью к опечаткам
  • Средние запросы (5-20 символов): Сбалансированный подход с точным совпадением, wildcard-поиском и multi-match
  • Длинные запросы (>20 символов): Оптимизированный поиск по длинным текстам с точным фразовым совпадением

2. Специальные анализаторы для русского языка

product_search: {
    type: 'custom',
    tokenizer: 'standard',
    filter: [
        'lowercase',
        'russian_stop',      // Фильтрация стоп-слов
        'russian_stemmer',   // Стемминг для русского
        'product_synonyms',  // Синонимы для товаров
        'product_edge_ngram' // N-граммы для частичного совпадения
    ]
}

3. Умные синонимы для строительной отрасли

Система понимает отраслевую специфику и обрабатывает синонимы:

  • бетон ↔ цемент ↔ смесь
  • В25 ↔ В-25 ↔ бетон В25 ↔ марка В25
  • М300 ↔ М-300 ↔ марка 300 ↔ бетон М300
  • фундамент ↔ основание ↔ база ↔ фундаментный

4. Интеллектуальный скоринг результатов

Elasticsearch не просто находит документы, но и умно ранжирует их:

  • Boost ×2.0 для точных совпадений марок бетона (В25, М300)
  • Boost ×1.3 для заявок с высоким приоритетом
  • Boost ×1.2 для недавно созданных документов (последние 30 дней)
  • Boost ×1.15 для активных статусов (NEW, IN_PROCESS, PENDING)
  • Min score 0.5 для фильтрации нерелевантных результатов

5. Встроенное кэширование поисковых запросов

// In-memory кэш с TTL 2 минуты
private searchCache = new Map<string, {
    data: SearchResult[];
    timestamp: number
}>()
private readonly CACHE_TTL = 2 * 60 * 1000
private readonly MAX_CACHE_SIZE = 500

6. Подсветка найденных фрагментов

Результаты поиска отображаются с подсветкой найденных фрагментов в HTML-формате:

<mark>бетон В25</mark> для фундамента с доставкой

Периодические заявки: Автоматизация рутины

Еще одна инновационная фича — система периодических заявок. Представьте: клиенту нужна
ежедневная поставка бетона на месяц. Вместо создания 30 заявок вручную, система делает это автоматически!

Как это работает:

  1. Выбор периода: Пользователь включает режим «Периодические заявки» и выбирает диапазон дат
  2. Заполнение формы: Все поля (кроме даты доставки) заполняются один раз
  3. Магия транзакций: Система создает по одной заявке на каждый день выбранного периода
  4. Синхронизация с Bitrix24: Для каждой заявки автоматически создается сделка в CRM
  5. Атомарность: Если хоть одна заявка не создалась — откатывается вся транзакция

Технические детали:

// Создание периодической группы с транзакцией
const queryRunner = AppDataSource.createQueryRunner()
await queryRunner.startTransaction()

try {
    // Генерируем массив дат
    const dates = this.generateDateRange(startDate, endDate)

    // Создаем группу периода
    const periodGroup = queryRunner.manager.create(SubmissionPeriodGroup, {
        startDate, endDate,
        totalSubmissions: dates.length,
        status: PeriodGroupStatus.ACTIVE
    })

    // Создаем заявки для каждой даты
    for (const date of dates) {
        // Создаем сделку в Bitrix24
        const bitrixDealId = await bitrix24Service.createDeal(dealData)

        // Создаем заявку в БД
        const submission = await queryRunner.manager.save(...)
    }

    await queryRunner.commitTransaction()
} catch (error) {
    await queryRunner.rollbackTransaction()
    throw error
}

Система также умеет:

  • Массово обновлять все заявки периода (кроме даты)
  • Отменять весь период одной кнопкой
  • Отслеживать прогресс выполнения периода
  • Хранить метаданные для аудита

 Динамический конструктор форм

В CRM реализован мощный drag-and-drop конструктор форм с административной панелью:

Возможности конструктора:

  • 15+ типов полей: текст, число, дата, время, выпадающий список, автокомплит, чекбокс, радио, файлы, заголовки, разделители
  • Секционная организация: Поля группируются в разделы с аккордеонами
  • Drag & Drop: Перетаскивание полей между секциями и изменение порядка
  • Связанные поля: Автозаполнение данных из Bitrix24 по выбранному клиенту
  • Условная логика: Поля могут показываться/скрываться в зависимости от других полей
  • Валидация: Кастомные правила проверки на фронте и бэкенде
  • Bitrix24 mapping: Автоматическое связывание полей формы с полями Bitrix24

Адаптивность:

Формы автоматически переключаются между десктопной и мобильной версией:

  • Desktop: Аккордеоны с секциями, кнопки управления, прогресс заполнения
  • Mobile: Упрощенная версия с touch-friendly элементами и оптимизацией под экраны смартфонов

 Миграция с MongoDB на PostgreSQL

Проект изначально использовал MongoDB, но мы провели полную миграцию на PostgreSQL с TypeORM. Почему?

  • ACID-транзакции: Критично для периодических заявок и финансовых операций
  • Сложные связи: Множество отношений между сущностями (формы → поля → заявки → пользователи)
  • Миграции схемы: TypeORM предоставляет удобный механизм версионирования БД
  • Производительность JOIN: Эффективная работа со связанными данными

Ключевые сущности:

User ← (1:N) → Submission ← (N:1) → Form ← (1:N) → FormField
                    ↓
              (N:1) SubmissionPeriodGroup
                    ↓
            (1:N) Submission (periodic)

Интеграция с Bitrix24

Система плотно интегрирована с Bitrix24 CRM через webhook API:

Что интегрировано:

  • Автоматическое создание сделок: При отправке формы создается сделка в Bitrix24
  • Синхронизация статусов: Двусторонняя синхронизация статусов сделок
  • Подгрузка справочников: Автокомплит клиентов, компаний, товаров из Bitrix24
  • Связанные поля: При выборе клиента автоматически заполняются телефон, email, адрес
  • Кэширование: Redis-кэш для API-ответов Bitrix24 (TTL: 30 минут — 2 часа)
  • Обратная связь: ID заявки записывается в пользовательское поле Bitrix24

In-Memory кэширование

Для оптимизации производительности реализована многоуровневая система кэширования:

1. CacheService (базовый)

const memoryCache = new Map<string, {
    data: any;
    expires: number
}>()

// Паттерн get-or-set
async getOrSet<T>(
    key: string,
    setter: () => Promise<T>,
    options?: CacheOptions
): Promise<T | null>

2. BitrixCacheService (специализированный)

  • Категории сделок: TTL 2 часа
  • Стадии сделок: TTL 1 час
  • Динамические опции (клиенты, товары): TTL 30 минут

3. FormCacheService (для форм)

  • Формы с полями: TTL 30 минут
  • Список активных форм: TTL 10 минут

4. Elasticsearch SearchCache

  • Результаты поиска: TTL 2 минуты
  • Максимальный размер: 500 записей
  • Auto-cleanup устаревших записей

Docker-инфраструктура

Весь проект упакован в Docker с продакшн-оптимизацией:

Сервисы в docker-compose:

  • PostgreSQL 16 Alpine: Компактная БД с health checks
  • Redis 7 Alpine: Кэш с AOF persistence
  • Elasticsearch 8.11: Поисковый движок с ограниченной памятью (512MB)
  • Backend: Node.js API с multi-stage build
  • Frontend: Nginx + статика React с оптимизацией

Особенности конфигурации:

services:
  postgres:
    ports:
      - '127.0.0.1:5489:5432'  # Доступ только через localhost
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready']

  elasticsearch:
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - 'ES_JAVA_OPTS=-Xms512m -Xmx512m'

  backend:
    depends_on:
      postgres: { condition: service_healthy }
      redis: { condition: service_healthy }
      elasticsearch: { condition: service_healthy }

E2E тестирование с Playwright

Для обеспечения качества реализованы E2E-тесты на Playwright:

  • Тестирование аутентификации (вход/выход)
  • Создание и отправка заявок
  • Административные функции
  • Тесты API endpoints
  • Интеграция с Bitrix24

Производительность и оптимизации

Backend оптимизации:

  • Connection pooling для PostgreSQL
  • Индексы БД на часто запрашиваемые поля
  • Lazy loading связанных сущностей в TypeORM
  • Background jobs для тяжелых операций (синхронизация с Bitrix24)
  • Elasticsearch refresh_interval: 30s для лучшей производительности индексации

Frontend оптимизации:

  • React Query для кэширования серверных данных
  • Code splitting на уровне роутов
  • Debouncing для автокомплита и поиска
  • Виртуализация длинных списков в таблицах
  • Lazy loading компонентов форм

Безопасность

  • JWT токены с refresh механизмом (access: 7 дней, refresh: 30 дней)
  • Bcrypt хэширование паролей с солью
  • Role-based access control (user/admin)
  • CORS с белым списком доменов
  • Input validation на фронте (Yup) и бэкенде (class-validator)
  • SQL injection protection через TypeORM query builder
  • Rate limiting для API endpoints

Мобильная адаптация

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

  • Responsive breakpoints: xs, sm, md, lg, xl
  • Touch-friendly: Увеличенные кнопки и поля ввода
  • Упрощенные формы: Автопереключение на SimpleMobileBetoneForm
  • Progressive disclosure: Секции открываются по одной
  • Оптимизация трафика: Сжатие данных, ленивая загрузка

Чему я научился

Этот проект был отличным опытом работы с современным стеком технологий:

  • Настройка и тонкая настройка Elasticsearch для русскоязычного контента
  • Проектирование сложных транзакций с TypeORM
  • Оптимизация производительности с многоуровневым кэшированием
  • Интеграция с внешними API (Bitrix24 webhook)
  • Создание type-safe приложений с TypeScript
  • Docker-оркестрация для продакшен-окружения
  • E2E тестирование с Playwright
  • Работа с Material-UI и создание адаптивных интерфейсов

Что дальше?

Планы по развитию проекта:

  • Внедрение WebSocket для real-time уведомлений
  • Добавление аналитики и отчетов (дашборды, графики)
  • Интеграция с 1C для учета
  • Мобильное приложение на React Native
  • Система уведомлений (email, SMS, push)
  • AI-ассистент для предсказания спроса

Заключение

Beton CRM — это пример того, как современные технологии могут решать реальные бизнес-задачи.
Мы создали систему, которая не только автоматизирует процессы, но и делает работу с заказами приятной и эффективной.

Особенно горжусь реализацией Elasticsearch с умным поиском, системой периодических заявок
с транзакциями и динамическим конструктором форм. Эти фичи действительно выделяют проект среди типовых CRM.

Если у вас есть вопросы по реализации каких-то частей или хотите обсудить архитектурные решения —
пишите! Буду рад поделиться опытом.


Технологии: React 19, TypeScript, Node.js, Express, PostgreSQL, TypeORM,
Elasticsearch 8.11, Redis, Docker, Material-UI 7, React Query, Bitrix24 API, Playwright