ozma.io — это low-code-конструктор ПО, для работы с которым хватит и начальных навыков программирования. Например, в нём можно создать свою CRM-систему, потратив на это примерно 9 часов. Этим сегодня и займёмся.

От электронных таблиц до Битрикса и обратно

Когда компания только начинает заниматься управлением продаж, чаще всего это происходит в Экселе или гуглотаблицах. Со временем, когда таблицы разрастаются, а данных становится слишком много, компания обычно переходит на что-то посерьёзнее, но не сильно сложное и не очень дорогое,а лучше — бесплатное: Битрикс24, Zoho CRM, Мегаплан или любая другая подобная система. Тысячи их :-)

Если дела идут хорошо, то компания скоро начинает сталкиваться с ограничениями коробочных версий. Такие системы плохо масштабируются (или хорошо, но очень дорого), а ещё их нельзя до конца подстроить под конкретные рабочие бизнес-процессы.

Если пойти на уровень выше — Salesforce, Microsoft Dynamics, SAP и коробочный Битрикс24, то да, их можно настроить как угодно. Но чаще всего стоимость лицензии, внедрения, настройки и сопровождения сильно превысит выгоды от их внедрения. Не всегда, конечно, но для малого и среднего бизнеса чаще всего дела обстоят именно так.

Другая альтернатива: разработка на заказ. Себестоимость может быть дешевле, но будущие затраты на поддержку и модификации гарантированно превысят стоимость той же коробочной версии (ради интереса попробуйте поинтересоваться у разработчиков, сколько стоит их годовая поддержка и постоянная работа над продуктом :-)

Всё это приводит к тому, что каждая компания начинает свой тернистый путь с похожими граблями, проблемами и странными решениями. Например, собирают комбайн из нескольких разных программ и сервисов, каждый из которых работает сам по себе, а для синхронизации используют сервисы интеграций (которые, кстати говоря, тоже нужно поддерживать).

Решение — использовать low-code

В поисках подходящего CRM решения мы прошли примерно такой же путь. Изначально мы пробовали сделать всё на no-code-решениях, но столкнулись с проблемой настройки. Проще говоря, чтобы получить продукт, который бы нас устраивал, нужно было бы влезать в код, а ни один подобный сервис этого не позволяет сделать.

Разочаровавшись в таких решениях и их многочисленных ограничениях, мы решили попробовать другой подход — low-code. Здесь уже нужны навыки разработки, но не такие глубокие, как для создания продукта с нуля. Так мы получаем почти бесконечные возможности настройки системы, при этом сильно сокращая время на создание и развертывание готового решения и его доработок.

Так родилась ozma.io — low-code-платформа, которую мы сделали специально для быстрой разработки настраиваемых CRM и ERP. В ней есть готовые шаблоны, которые помогают сильно сократить затраты на адаптацию системы под конкретные требования и бизнес-кейсы. 

Переход на ozma.io позволил нашим партнёрам в 7 раз сократить времени разработки. В большинстве ситуаций теперь достаточно 3-5 минут, чтобы доработать решение и скинуть изменения клиенту. Дополнительно компании сэкономили на оплате программиста — для всех работ достаточно джуниора с навыками работы с JavaScript и SQL.

Создаём свою CRM: базовые требования

На старте нам требовался такой функционал:

  • Панели мониторинга: воронка продаж и ключевые метрики для анализа эффективности работы менеджеров.

  • Сделки: отображение записей в виде доски с карточками и в виде таблицы. Пока мы не будем добавлять никакой автоматизации (её можно будет добавить за 1-2 часа, но об этом позже).

Ещё у каждой сделки должна быть история изменений в виде лога событий, в котором менеджеры также могут оставлять комментарии.

  • Клиенты: сведения о клиенте с информацией о его контактных лицах, номерах телефонов и адресах электронной почты. Клиент может иметь разные наборы полей в зависимости от его типа - человек или организация.

  • Продукты: список продуктов, реализуемых в рамках сделки.

С такой системой уже можно полноценно работать и решать задачи бизнеса, а если чего-то будет не хватать — это легко доработать в следующей итерации без остановки процессов.

Доска со сделками (простой канбан)

Чтобы создать базовую доску, достаточно пятнадцати строк кода. По факту для этого нужен только запрос, который указывает как и какие данные отображать на экране. После этого можно сразу перетаскивать карточки между столбцами, менять статусы сделок и видеть общее количество задач — это стандартный функционал платформы.

Добавим в запрос еще 40 строк кода, сделаем карточки более полезными — у них появятся подписи к полям, значки и ссылки на другие представления. Например, чтобы быстро создать новую запись, достаточно просто нажать «+» и заполнить данные о сделке в отдельной форме. Некоторые поля теперь выделяются разными цветами: незавершенные и просроченные сделки выделены красным, а сделки, ожидающие действия — жёлтым. Естественно, палитру статусов можно настроить как угодно, добавив в неё любые цвета.

Последний шаг — фильтрация записей. Пользователи смогут фильтровать сделки по ответственным или по дате последней коммуникации. Еще добавим кнопки для быстрой установки фильтров, чтобы не заполнять их вручную каждый раз. 

В итоге, за 15 минут мы собрали довольно сложную кастомную доску для работы со сделками. В такой скорости и кроется суперсила ozma.io.

Запрос, с помощью которого собирается доска со сделками
{   
    /* Arguments of the user view */ 
    $contact reference(base.contacts) null @{
        caption = 'Клиент',
        options_view = &crm.ref_clients_view
    },
    $responsible array(reference(base.people)) null @{
        caption = 'Ответственный',
        /* Available values in popup will be restricted with the results of the specified user view */
        options_view = &base.ref_team_members_view    
    },
    $status enum('open', 'closed') null @{
        caption = 'Статус',
        text = mapping
            WHEN 'open'   THEN 'Открыто'
            WHEN 'closed' THEN 'Закрыто'
        END
    },
    $stage array(enum('first_contact', 'negotiations', 'decision_pending', 'payment_pending', 'completed')) null @{
        caption = 'Стадия',
        text = array mapping
            WHEN 'first_contact'    THEN 'Первый контакт'
            WHEN 'negotiations'     THEN 'Переговоры'
            WHEN 'decision_pending' THEN 'Принимают решение'
            WHEN 'payment_pending'  THEN 'Ожидание оплаты'
            WHEN 'completed'        THEN 'Завершено'
        END,
    },
    $start_date_from datetime null @{
        caption = 'Дата начала <c>'
    },
    $start_date_to datetime null @{
        caption = 'Дата начала <по>'
    },
    $due_date_from datetime null @{
        caption = 'Срок <c>'
    },
    $due_date_to datetime null @{
        caption = 'Срок <по>'
    },
    $is_archived bool null @{
        caption = 'Архив'
    },
}:
SELECT 
    /* User view type */    
    @type = 'board',
    /* User view title */
    @title = 'Сделки'
        || COALESCE('. Стадия: ' || (
            SELECT string_agg(value.@text, ', ') 
              FROM DOMAIN OF FIELD crm.deals.stage as stages 
             WHERE value = ANY($stage)
        ), '')
        || COALESCE(' (Ответственный - ' || (
            SELECT string_agg(last_name, ',') 
              FROM base.people 
             WHERE id = ANY($responsible)
        ) || ')', ''),
    /* "Filters" panel is hidden by default */
    @show_argument_editor = false,  
    /* "Filters" button will be showed on the top of the board */                     
    @show_argument_button = true,   
    /* Reference to the user view opened by clicking the "Open entry in modal" button */
    @row_link = &crm.deal_form,  
    /* Set the user view used for creating new entries */
    @card_create_view = { 
        /* Reference to the user view */
        ref: &crm.deal_form,
        /* Default values for the entry being created */
        default_values: {                              
            responsible: $responsible
        }
    },
    /* Specifications of the interface buttons */
    @buttons = [                                       
        {
            caption: 'Статус',
            icon: 'filter_alt',
            display: 'desktop',
            buttons: [
                {
                    caption: 'Открытые',
                    icon: '',
                    ref: &crm.deals_board,
                    args: {
                        status: 'open',
                        is_archived: $is_archived,
                        responsible: $responsible
                    },
                    target: 'top'
                },
                {
                    caption: 'Просроченные',
                    icon: 'flag',
                    ref: &crm.deals_board,
                    args: {
                        status: 'open',
                        due_date_to: $$transaction_time,
                        is_archived: $is_archived,
                        responsible: $responsible
                    },
                    target: 'top'
                },
                {
                    caption: 'Закрытые',
                    icon: 'done_all',
                    ref: &crm.deals_board,
                    args: {
                        status: 'closed',
                        is_archived: $is_archived,
                        responsible: $responsible
                    },
                    target: 'top'
                },
                {
                    caption: 'Все',
                    icon: 'filter_list_alt',
                    ref: &crm.deals_board,
                    args: {
                        is_archived: $is_archived,
                        responsible: $responsible
                    },
                    target: 'top'
                }
            ]
        },                              
        {   
            /* Open table with tasks instead task board */ 
            caption: 'Таблица',  
            tooltip: 'Отобразить сделки в виде таблицы',  
            icon: 'table_chart',
            variant: 'dark', 
            display: 'desktop',
            ref: &crm.deals_table, 
            /* Use filters from deals board for deals table */
            args: {
                is_archived: $is_archived,
                status: $status,
                contact: $contact,
                stage: $stage,
                start_date_from: $start_date_from,
                start_date_to: $start_date_to,
                due_date_from: $due_date_from,
                due_date_to: $due_date_to,
                responsible: $responsible
            },  
            target: 'top'
        }
    ],
    subject @{
        /* Color variant using for the field */
        cell_variant = 'outline-info'
    },
    '₽' || CASE WHEN stage = 'completed' THEN fact_amount_string ELSE amount_string END as amount @{
        /* Material design icon that will be displayed with the field data on the board card */
        icon =  'payment',
        cell_variant = CASE WHEN stage = 'completed' THEN 'outline-success' END
    },
    contact @{
        icon = 'business',
        default_value = $contact,
        visible = $contact IS NULL,
        cell_variant = null
    },
    'Статус: ' || status.@text as status @{
        icon = 'flag'
    },
    'Срок: ' || due_date_string as due_date @{
        icon = 'schedule',
        /* Use color variant value from default attribute "cell_variant" of the "due_date" field */
        cell_variant = due_date.@cell_variant,
        visible = status = 'open'
    },
    responsible @{
        icon = 'account_circle',
        cell_variant = null
    },
    stage @{
        /* Group entries by this field */
        board_group = true,
        /* Do not display status field on the card */               
        visible = false        
    },
    "order" @{
        /* Use the value from the "order" field as a sorting number for all entries */
        board_order = true,  
        visible = false
    }
FROM 
    crm.deals 
WHERE ($is_archived IS NULL OR is_archived = $is_archived)
     AND ($contact IS NULL OR contact = $contact)
     AND ($responsible IS NULL OR responsible = ANY($responsible))
     AND ($status IS NULL OR status = $status)
     AND ($stage IS NULL OR stage = ANY($stage))
     AND ($start_date_to IS NULL OR start_date <= $start_date_to)
     AND ($start_date_from IS NULL OR start_date >= $start_date_from)
     AND ($due_date_to IS NULL OR due_date <= $due_date_to)
     AND ($due_date_from IS NULL OR due_date <= $due_date_to)
ORDER BY 
    "order"
FOR INSERT INTO 
    crm.deals

Этот же запрос в демо-инстансе

Воронка продаж, активность сотрудников и аналитика для начальника

Теперь к дашбордам. Дашборды можно создать любой сложности и настроить их под любые задачи. Все элементы встраиваются на страницу с помощью iframe и базового JavaScript. Данные из базы визуализируются с помощью сторонних библиотек, например, d3.js. Они как раз и предназначены для быстрого создания анимированных графиков и диаграмм.

Для нашей CRM мы собрали интерактивную панель с несколькими ключевыми показателями: воронкой продаж, диаграммами и сводками для отслеживания прогресса команды:

Использование iframe позволяет добавлять любые произвольные элементы: карты, чаты и многое другое. Например, наши клиенты так встраивают сервисы для автозаполнения адресов доставки или поиска данных организации по ИНН. Работает этот по тем же принципам: выбираем данные с помощью запроса и передаём их компоненту для отображения.

Другие типы страниц, которые мы называем пользовательскими представлениями (или просто «юзервью»), можно реализовать таким же образом, в том числе:

  • таблицы

  • формы

  • древовидные таблицы

  • журналы событий

  • меню

По нашей статистике, разработчику с небольшим опытом работы с нашей low-code платформой нужно примерно 4 часа, чтобы собрать 23 таких представления, включая сделки, клиентов, продукты, задачи и сотрудников. Главное, что будет при этом использоваться — SQL и JavaScript, языки, которые знают большинство разработчиков.

Ещё ozma.io поддерживает модули —  предварительно написанные схемы или код. Их можно найти на нашем сайте и на сайтах партнёров. Использование готовых модулей сокращает время разработки в несколько раз: за час получится собрать полностью готовый продукт, сложив вместе несколько уже реализованных вами или другими разработчиками схем.

Например, вы можете создать модуль таск-трекера для своей команды,а позже добавить его в CRM, изменив пару полей и добавив ссылки из пользовательских CRM-представлений в таск-трекер.

Результат: CRM-продукт за 9 часов

Давайте посчитаем время, которое потребуется одному разработчику для создания своей CRM с нуля с минимальной автоматизацией:

  • 1 час — проектирование архитектуры базы данных (хотя, это время зависит от опыта разработчика в работе с бизнес-продуктами: если нет опыта, может затянуться и на пару дней);

  • 1 час — создание самой базы данных в интерфейсе;

  • 5 часов — создание 23 пользовательских представлений и связей между ними. По сути, это и будет ядро нашей CRM;

  • 1-2 часа — создание дашборда с ключевыми показателями (время сильно сокращается, когда у разработчика уже есть своя библиотека готовых диаграмм или он пользуется нашими шаблонами)

  • От 30 минут — прописывание специфичной для клиента автоматики. Кому-то нужны сложные автоматизации на десятки часов с промежуточными согласованиями, а некоторые могут обойтись вообще без триггеров и процедур.

В целом, 9 часов уже может быть достаточно, чтобы реализовать полезный продукт, пусть и в базовой версии. Если потратить еще десяток часов — получится уже расширенная версия, покрывающая почти все задачи бизнеса.

Конечно, решение со временем поменяется: появятся новые данные и новые бизнес-процессы, но главный плюс в том, что для поддержки и развития проекта достаточно разработчика с базовыми знаниями SQL и JavaScript.

О low-code платформе ozma.io

ozma.io была основана Кириллом Маркиным и Николаем Амиантовым. Большая часть статьи и демо написана Ириной Гороховой. Спасибо Константину, Ренату Дарыбаеву, Даниилу и Любови за большой вклад в проект, Михаилу Полянину за помощь в статье и Роману Белякову за иллюстрации.

Расскажите нам, чего вам не хватает в вашей CRM? Вы разрабатываете аналогичные продукты и внедряете их для своих клиентов или используете в бизнесе? Какие еще примеры и шаблоны вам было бы интересно увидеть? Напишите нам в комментариях, если появились вопросы по коду или по продукту — будем рады ответить на каждый из них.

Комментарии (0)