Как я создал CRM-систему

Аватарка пользователя Dmitrii Starikov

Знакомим вас с личным опытом создания такой CRM-системы, которая позволила компании увеличить число закрываемых сделок почти в 3 раза.

Обложка поста Как я создал CRM-систему

Всем привет, меня зовут Дмитрий Стариков, я веб-разработчик с 10-ти летним опытом работы. CRM программы – это незаменимый инструмент для бизнеса — они значительно облегчают работу, структурируют взаимодействие сотрудников и клиентов внутри крупных компаний. Я познакомлю вас с личным опытом создания такой CRM-системы, которая позволила компании увеличить число закрываемых сделок почти в 3 раза!

Предыстория

Проект начался в ИТ-отделе одного крупного риэлтерского агентства. На момент моего трудоустройства там уже существовала CRM-система. Она позволяла вести внутренний учет сотрудников, документооборот, базы сделок и клиентов и самое важное — вести базу объектов и автоматически выгружать их в рекламу на различные площадки. Система имела устаревший интерфейс на ExtJS, а бэкенд строился на связке PHP (Yii и значительная часть самописного legacy-кода), MySQL. В целом, проект устраивал руководство в техническом плане (за исключением интерфейса), но была серьезная проблема для бизнеса — многие объекты недвижимости не выходили в рекламу из-за ошибок программы. По этой причине компания теряла клиентов, а как следствие, прибыль.

Руководство поставило программистам четкие задачи:

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

После исследования отчетов о выгрузках на рекламные площадки оказалось, что ситуация на самом деле плачевна — в рекламу выходило всего-лишь 20% всех объектов! Такие показатели возникли на фоне того, что разные рекламодатели предъявляли разные требования к полям и их структуре, содержимому и взаимосвязям.

Около года я работал над этой системой, и за это время ситуация кардинально изменилась — не выходило в рекламу уже всего лишь около 15% объектов, зачастую из-за невнимательности самих агентов. У компании увеличилось число закрываемых сделок, появились свободные средства для инвестиций в технологичность, и отсюда уже начинается история новой CRM. Набравшись экспертности в сфере риэлтинга и хорошо зарекомендовав себя, как разработчик, мне поручают заняться созданием новой CRM-системы.

Начало работы

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

Под наши задачи я выбрал архитектуру SPA (одностраничное приложение). То есть фронтенд подгружался при первом заходе, а дальше просто подгружал данные и позволял агенту с ними работать без перезагрузки страницы. Бэкенд же отвечал непосредственно за авторизацию, получение, изменение и выдачу данных, ничего не зная о шаблонах и представлении данных для пользователя. Такое разделение удобно тем, что при необходимости можно просто заменить любой из модулей (или же использовать уже готовый backend/API, например, для мобильного приложения), каждый модуль может писаться раздельно разными разработчиками и при этом они никак не будут друг другу мешать. Кроме того, JS-фреймворки (вроде AngularJS, React, VueJS) позволяют на порядок проще сделать фронтенд, чем в известных мне MVC-фреймворках на PHP.

Был выбран следующий стек:

  • frontend на AngularJS;
  • backend на легковесном PHP-фреймворке FlightPHP;
  • отдельно был создан микросервис на Python, отслеживающий изменения в объектах и создающий файлы для автоматической выгрузки в API рекламных порталов;
  • MariaDB.

Выбор был продиктован отчасти архитектурными решениями, отчасти опытом и пожеланиями разработчиков, которые занимались проектом. Так как системе по самой сути решаемой задачи не суждено было стать нагруженной, то, руководствуясь принципом YAGNI, я не стремился вкладывать много ресурсов в подготовку системы к таким нагрузкам, а делал ставку на ее легкость и гибкость. На первый план выходили:

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

Хранилища

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

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

Отдельно можно выделить описание ролей. Думаю, многим знакома ситуация, когда менеджмент просит добавить условную кнопку “вот здесь”, при этом кнопка должна делать “вот это”, должна быть видна одним, другим не видна вообще и т.д. Натерпевшись подобных пожеланий при разработке прошлой системы, мне удалось избежать таких проблем в новой.

Первая таблица с перечислением всех возможных прав (например, создавать/читать/обновлять/удалять объекты определенного типа, доступ к разделам и т.д., но позже там могли появляться и специфические права, которые вписываясь в архитектуру, не становились костылями). Вторая таблица была набором строк, в которых связывался идентификатор пользователя, группы (отделы) или роли (администратор, начальник отдела и т.д.), идентификатор права и к кому это право применяется (ко всему, к своему, или даже по идентификатору и типу). Таким образом, можно настроить любые права: понадобилось внутри отдела в обход начальника назначить человека, который может утверждать объекты для выхода в рекламу? Пожалуйста. Может быть какой-то из отделов хочет новую фичу? Без проблем. Еще в трех таблицах перечислялись те самые пользователи, роли и отделы — тут все стандартно. Также мы хранили фотографии и документы по сделкам. Файлы загружались на отдельный сервер, который просто подключался через символическую ссылку в директории проекта.

Интерфейс

AngularJS из коробки или с минимальными доработками предоставлял почти все необходимое: быстро появилась красивая архитектура, был прописан роутинг, создана авторизация через JWT-токены и поддержка прав пользователя, о которых рассказывалось выше. Сам UI создавали на основе Angular Material, что колоссально сэкономило время — был создан шаблон, куда постепенно включались все новые и новые разделы. Различные модули по возможности переиспользовали уже готовые представления.

Отдельное внимание уделю формам. Так как одна из основных задач — это дать агенту инструмент, при помощи которого он единожды опишет объект по всем параметрам и будет уверен, что он будет рекламироваться, то большое внимание было уделено именно этому, и снова AngularJS приятно удивил, буквально одним условием в атрибуте тэга проводилась валидация не только этого поля, но и других, выводились подсказки и ошибки, скрывались лишние опции в селектах, отображались и скрывались поля, которые актуальны именно для описываемого объекта — и все это в одной форме, разделенной для удобства на 3 экрана в слайдере. Забегая вперед, скажу, что такой подход полностью хоть и потребовал изрядно попотеть над документацией API рекламных площадок, совмещая различные описания полей, все же полностью себя окупил — после запуска новой CRM в продакшн были единичные случаи ошибок выгрузки, потому что агент уже на стадии заполнения вынужден был оформить все правильно. Немногочисленные ошибки касались в основном ситуаций, которые невозможно отловить программным путем: например, на фотографиях указывались контакты (что запрещено большинством площадок), в описании был какой-то фрагмент, приводящий к блокировке.

Как я создал CRM-систему 1

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

Как я создал CRM-систему 2
Как я создал CRM-систему 3
Как я создал CRM-систему 4

Backend

На фреймворке FlightPHP реализовали REST API с около сотни методов, осуществляющих CRUD-операции по всем сущностям, а также генерацию отчетов, PDF файлов с корпоративным оформлением т.д. Flight конечно не сравнится с Yii или Symfony в плане построения сложных систем. Простейший шаблонизатор и валидатор запросов, роутинг, работа с входящими данными, кэширование, вывод ошибок, триггеры позволили полностью покрыть задачи проекта. Кроме самого API к бэкенду можно отнести и микросервис по выгрузке в рекламу, задача которого в том, чтобы сформировать корректные XML-файлы, транслируя модель наших данных на модель данных конкретной площадки, а затем парсящий ответные отчеты от площадок и заносящий информацию об ошибках в систему.

Как я создал CRM-систему 5

Выводы

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

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

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

API
JavaScript
PHP
Angular
38362