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? Вы разрабатываете аналогичные продукты и внедряете их для своих клиентов или используете в бизнесе? Какие еще примеры и шаблоны вам было бы интересно увидеть? Напишите нам в комментариях, если появились вопросы по коду или по продукту — будем рады ответить на каждый из них.