<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>portfolio - Portfolio</title>
	<atom:link href="https://shknv.ru/category/portfolio/feed/" rel="self" type="application/rss+xml" />
	<link>https://shknv.ru</link>
	<description>Евгений Шикунов</description>
	<lastBuildDate>Thu, 18 Dec 2025 15:41:41 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>

<image>
	<url>https://shknv.ru/wp-content/uploads/2024/12/web-app-manifest-512x512-1-150x150.png</url>
	<title>portfolio - Portfolio</title>
	<link>https://shknv.ru</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Система учёта визитов медицинских представителей</title>
		<link>https://shknv.ru/sistema-uchjota-vizitov-medicinskih-predstavitelej/</link>
		
		<dc:creator><![CDATA[Evgeniy Shikunov]]></dc:creator>
		<pubDate>Wed, 12 Nov 2025 19:30:06 +0000</pubDate>
				<category><![CDATA[portfolio]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=501</guid>

					<description><![CDATA[<p>&#160; Система учёта визитов медицинских представителей: от идеи до 7,500 визитов в месяц Ключевые цифры проекта: 7,580 визитов за 3 месяца в одной компании 1 минута 15 секунд — среднее время фиксации визита 411 часов в месяц экономии рабочего времени +12% рост продаж за квартал после внедрения 205,500 рублей в месяц экономии для команды из [&#8230;]</p>
<p>The post <a href="https://shknv.ru/sistema-uchjota-vizitov-medicinskih-predstavitelej/">Система учёта визитов медицинских представителей</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>&nbsp;</p>
<article>
<h1>Система учёта визитов медицинских представителей: от идеи до 7,500 визитов в месяц</h1>
<p><strong>Ключевые цифры проекта:</strong></p>
<ul>
<li><strong>7,580 визитов</strong> за 3 месяца в одной компании</li>
<li><strong>1 минута 15 секунд</strong> — среднее время фиксации визита</li>
<li><strong>411 часов в месяц</strong> экономии рабочего времени</li>
<li><strong>+12% рост продаж</strong> за квартал после внедрения</li>
<li><strong>205,500 рублей в месяц</strong> экономии для команды из 20 человек</li>
</ul>
<p>В дополнение к статье <a href="https://shknv.ru/320-2/">https://shknv.ru/320-2/</a></p>
<h2>Предыстория: как всё начиналось</h2>
<p>Работая с фармацевтическими компаниями последние несколько лет, я постоянно наблюдал одну и ту же картину: медицинские представители ездят по клиникам, встречаются с врачами, проводят презентации — но вся эта ценная информация оседает в блокнотах, телефонных заметках или вообще теряется. Руководители не видят реальной картины работы, а при уходе сотрудника вся его база знаний исчезает.</p>
<p>Три года назад я работал с одной фармацевтической компанией над интеграцией их систем. В офисе на стене висел огромный календарь, весь исписанный маркерами разных цветов — это была попытка визуализировать, кто из представителей где был и куда едет. Выглядело впечатляще, но совершенно неэффективно.</p>
<p>Коммерческий директор жаловался: &#171;У нас 15 представителей в Петербурге, каждый делает по 10-15 визитов в неделю. Но я понятия не имею, что происходит на этих встречах. Раз в неделю мы собираемся на планёрку, они рассказывают по памяти, что было. Половина деталей уже забыта, конкретики никакой&#187;.</p>
<p>Тогда я решил создать специализированное решение, которое закроет эту боль. Не универсальную CRM, а именно инструмент для учёта визитов полевых сотрудников.</p>
<h2>Постановка задачи: что на самом деле нужно пользователям</h2>
<p>Я провёл серию интервью с медицинскими представителями, руководителями отделов и директорами. Выяснилось, что у каждой роли свои потребности, и система должна закрывать их все одновременно.</p>
<h3>Потребности медицинских представителей</h3>
<ul>
<li><strong>Скорость фиксации.</strong> Не хочется тратить 5-10 минут на заполнение формы сразу после встречи. Идеально — 1 минута</li>
<li><strong>Работа без интернета.</strong> В подвале клиники или на окраине города связи может не быть</li>
<li><strong>Доступ к истории.</strong> Перед визитом нужно быстро вспомнить, что обсуждали в прошлый раз</li>
<li><strong>Простота.</strong> Никаких сложных интерфейсов — только самое важное</li>
<li><strong>Мобильность.</strong> Работать с телефона, а не только с ноутбука</li>
</ul>
<h3>Потребности руководителей отделов</h3>
<ul>
<li><strong>Видимость активности.</strong> Кто где был, сколько визитов сделано за день/неделю/месяц</li>
<li><strong>Качество работы.</strong> Не просто факт визита, а что именно обсуждалось, какой результат</li>
<li><strong>Быстрая реакция на проблемы.</strong> Если представитель пять раз подряд получает отказы в одной клинике — нужно помочь</li>
<li><strong>Распределение нагрузки.</strong> Понимать, кто перегружен, а у кого свободное время</li>
<li><strong>Передача клиентов.</strong> Когда сотрудник уходит или переходит на другую территорию — новичок должен быстро войти в курс дела</li>
</ul>
<h3>Потребности директоров</h3>
<ul>
<li><strong>Общая картина по компании.</strong> Сколько визитов в месяц делается в целом, динамика по регионам</li>
<li><strong>ROI полевой работы.</strong> Сколько стоит один визит, как это коррелирует с продажами</li>
<li><strong>Стратегические решения.</strong> В какие клиники имеет смысл вкладываться, а какие бесперспективны</li>
<li><strong>История как актив.</strong> База знаний о клиентах — это актив компании, а не личная записная книжка сотрудника</li>
</ul>
<table border="1" cellspacing="0" cellpadding="10">
<thead>
<tr>
<th>Роль</th>
<th>Главная боль ДО системы</th>
<th>Что даёт система</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Медпредставитель</strong></td>
<td>1 час вечером на отчёты вместо семьи</td>
<td>5-10 минут в день, всё на ходу</td>
</tr>
<tr>
<td><strong>Руководитель отдела</strong></td>
<td>Узнаёт о проблемах через неделю на планёрке</td>
<td>Видит проблемы в реальном времени</td>
</tr>
<tr>
<td><strong>Директор</strong></td>
<td>Решения на основе интуиции и анекдотов</td>
<td>Решения на основе данных и статистики</td>
</tr>
</tbody>
</table>
<h2>Как работает система: схема процесса</h2>
<h3>Процесс работы представителя (пользовательский сценарий)</h3>
<table border="1" cellspacing="0" cellpadding="10">
<thead>
<tr>
<th>Этап</th>
<th>Действие представителя</th>
<th>Что происходит в системе</th>
<th>Время</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>1. Подготовка</strong></td>
<td>Открывает приложение перед визитом, смотрит историю встреч с клиникой</td>
<td>Показываются все предыдущие визиты, комментарии, статусы</td>
<td>30 сек</td>
</tr>
<tr>
<td><strong>2. Визит</strong></td>
<td>Встречается с врачом, проводит презентацию</td>
<td>—</td>
<td>15-30 мин</td>
</tr>
<tr>
<td><strong>3. Фиксация</strong></td>
<td>Сразу после встречи заполняет минимальную форму: клиника, врач, результат, комментарий</td>
<td>Данные сохраняются локально в телефон (IndexedDB)</td>
<td>40-60 сек</td>
</tr>
<tr>
<td><strong>4. Синхронизация</strong></td>
<td>Ничего не делает — всё автоматически</td>
<td>Когда появляется интернет, данные отправляются на сервер</td>
<td>Авто</td>
</tr>
<tr>
<td><strong>5. Интеграция</strong></td>
<td>Ничего не делает</td>
<td>Сервер создаёт запись в Bitrix24, связывает с клиентом, врачом</td>
<td>Авто</td>
</tr>
</tbody>
</table>
<p><strong>Итого:</strong> представитель тратит ~1 минуту вместо 1 часа вечером на заполнение Excel</p>
<h3>Технический процесс синхронизации (для понимания надёжности)</h3>
<ol>
<li><strong>Создание визита:</strong> пользователь заполняет форму в приложении (React PWA)</li>
<li><strong>Локальное сохранение:</strong> данные сохраняются в IndexedDB браузера (работает без интернета)</li>
<li><strong>Очередь синхронизации:</strong> визит добавляется в очередь на отправку</li>
<li><strong>Попытка отправки:</strong> при появлении сети автоматически отправляется на сервер (FastAPI)</li>
<li><strong>Повторные попытки:</strong> если ошибка — повторная попытка через 5 сек, 30 сек, 2 мин, 5 мин</li>
<li><strong>Валидация:</strong> сервер проверяет данные, связывает с пользователем и компанией</li>
<li><strong>Сохранение в БД:</strong> запись в PostgreSQL с timestamp</li>
<li><strong>Отправка в Bitrix24:</strong> через REST API создаётся элемент в смарт-процессе</li>
<li><strong>Связывание записей:</strong> ID из Bitrix24 сохраняется в нашей БД (для двусторонней синхронизации)</li>
<li><strong>Подтверждение клиенту:</strong> приложение получает статус &#171;синхронизировано&#187;</li>
</ol>
<p><strong>Надёжность:</strong> даже если представитель целый день был без связи (15 визитов), вечером при подключении к Wi-Fi всё синхронизируется автоматически за 2-3 минуты.</p>
<h2>Бизнес-кейсы: реальные истории внедрения</h2>
<h3>Кейс 1: Фармацевтическая компания в Санкт-Петербурге</h3>
<p><strong>О компании:</strong></p>
<ul>
<li>Поставка медицинского оборудования и препаратов для клиник</li>
<li>Команда: 18 медицинских представителей + 3 руководителя отделов + 1 региональный директор</li>
<li>География: Санкт-Петербург и Ленинградская область (350+ клиник в базе)</li>
<li>До внедрения: Excel-таблицы, которые представители заполняли вечером по памяти</li>
</ul>
<p><strong>Проблемы до внедрения:</strong></p>
<ul>
<li>Представители тратили по 1 часу каждый вечер на заполнение отчётов</li>
<li>Много деталей терялось — люди забывали, что обсуждали утром</li>
<li>Руководители видели информацию только раз в неделю на планёрке</li>
<li>При уходе сотрудника новичок начинал с нуля — не знал историю клиентов</li>
<li>Невозможно было понять, какие клиники перспективные, а какие тратят время впустую</li>
</ul>
<p><strong>Процесс внедрения:</strong></p>
<ol>
<li><strong>Неделя 1:</strong> Анализ потребностей, встреча с руководством (2 дня)</li>
<li><strong>Неделя 2:</strong> Настройка интеграции с Bitrix24, загрузка базы клиник (3 дня)</li>
<li><strong>Неделя 3:</strong> Пилот с 3 продвинутыми пользователями (5 дней)</li>
<li><strong>Неделя 4:</strong> Обучение всех 18 представителей (1 день), старт работы (3 дня адаптации)</li>
</ol>
<p><strong>Результаты через 3 месяца:</strong></p>
<table border="1" cellspacing="0" cellpadding="10">
<thead>
<tr>
<th>Показатель</th>
<th>До внедрения</th>
<th>После внедрения</th>
<th>Изменение</th>
</tr>
</thead>
<tbody>
<tr>
<td>Инструмент учёта</td>
<td>Excel вручную</td>
<td>Автоматизированная система</td>
<td>—</td>
</tr>
<tr>
<td>Время на отчёты (в день)</td>
<td>1 час</td>
<td>5-10 минут</td>
<td><strong>-85%</strong></td>
</tr>
<tr>
<td>Количество визитов</td>
<td>~110-120 в неделю</td>
<td>140 в неделю</td>
<td><strong>+20%</strong></td>
</tr>
<tr>
<td>Оперативность данных</td>
<td>Раз в неделю</td>
<td>В реальном времени</td>
<td>—</td>
</tr>
<tr>
<td>Детализация</td>
<td>Минимальная</td>
<td>Полная история</td>
<td>—</td>
</tr>
<tr>
<td>Время ввода нового сотрудника</td>
<td>1 месяц</td>
<td>1 неделя</td>
<td><strong>-75%</strong></td>
</tr>
</tbody>
</table>
<p><strong>Конкретные цифры за первые 3 месяца:</strong></p>
<ul>
<li>Зафиксировано <strong>7,580 визитов</strong> (в среднем 140 визитов в неделю на команду из 18 человек)</li>
<li>Среднее время создания одного визита: <strong>1 минута 15 секунд</strong></li>
<li>Общая экономия времени: <strong>с 18 часов в день до 3 часов</strong> (18 человек × 1 час → 18 человек × 10 минут)</li>
<li>Это освободило <strong>15 часов в день</strong> или <strong>~330 часов в месяц</strong> рабочего времени</li>
<li>В деньгах (при ставке 500₽/час): экономия <strong>165,000₽ в месяц</strong> только на представителях</li>
</ul>
<p><strong>Неожиданный эффект — аналитика:</strong></p>
<p>Через месяц работы руководитель отдела обратил внимание на статистику и обнаружил интересное: три крупные клиники показывали стабильно низкий результат визитов. Из 15 последних визитов в каждую — 12-13 отказов. Раньше эта информация терялась в общем потоке.</p>
<p>Провели анализ: оказалось, что в этих клиниках уже были долгосрочные контракты с конкурентами, и закупщики просто из вежливости принимали представителей, но решения не принимали. Представители продолжали ездить по инерции, тратя время впустую.</p>
<p><strong>Решение:</strong> перераспределили усилия на 12 других клиник с более высокой конверсией. Результат — <strong>рост продаж на 12% за следующий месяц</strong> при том же количестве визитов.</p>
<blockquote><p>&#171;Раньше я каждый вечер тратила по часу на отчёты. Сейчас просто фиксирую визиты на месте за минуту, всё автоматически синхронизируется с Битрикс24. Сэкономленное время трачу на дополнительные визиты. За месяц сделала на 15 визитов больше, чем раньше.&#187;</p>
<footer>— Марина, медицинский представитель</footer>
</blockquote>
<blockquote><p>&#171;Главная ценность — это история. Когда мы берём нового сотрудника на территорию, он за вечер изучает всю базу знаний по клиентам: кто там работает, какие были встречи, что обсуждали, какие препараты интересны. Раньше нужно было месяц вникать, ездить вместе со старшим коллегой. Сейчас новичок после недели уже работает самостоятельно.&#187;</p>
<footer>— Алексей, руководитель отдела</footer>
</blockquote>
<h3>Кейс 2: Компания с распределёнными командами (Москва + Краснодар)</h3>
<p><strong>О компании:</strong></p>
<ul>
<li>Дистрибьютор фармацевтической продукции</li>
<li>Команда: 25 представителей в Москве + 8 представителей в Краснодаре</li>
<li>Особенность: разные часовые пояса, разные руководители, общий директор</li>
<li>До внедрения: две разные системы учёта (Москва вела в Google Sheets, Краснодар в Excel)</li>
</ul>
<p><strong>Проблемы до внедрения:</strong></p>
<ul>
<li>Директор не мог увидеть общую картину по компании</li>
<li>Московская и краснодарская команды использовали разные форматы отчётности</li>
<li>Невозможно было сравнивать эффективность регионов</li>
<li>При обмене опытом между командами не было единой базы знаний</li>
<li>Путаница с временными зонами: когда какой визит состоялся?</li>
</ul>
<p><strong>Решение:</strong></p>
<ul>
<li>Единая система для всех регионов с разграничением прав доступа</li>
<li>Московская команда видит только своих клиентов, краснодарская — только своих</li>
<li>Руководители видят свои команды, директор — всё</li>
<li>Автоматический учёт часовых поясов (время визита записывается в UTC, показывается в локальном времени пользователя)</li>
<li>Единый формат данных для аналитики и сравнения</li>
</ul>
<p><strong>Результаты через 8 месяцев:</strong></p>
<ul>
<li>Обрабатывает <strong>600-700 визитов в неделю</strong> стабильно</li>
<li>Никаких жалоб на права доступа или путаницу с данными</li>
<li>Директор получает еженедельный автоматический отчёт: сколько визитов в каждом регионе, динамика, проблемные зоны</li>
<li>Выявили лучшие практики краснодарской команды (у них была выше конверсия визитов) и распространили на Москву</li>
<li>Общая эффективность выросла на <strong>8% за полгода</strong></li>
</ul>
<blockquote><p>&#171;Наконец-то я вижу реальную картину работы обоих офисов, а не только то, что мне рассказывают на еженедельных созвонах. Могу быстро заметить, если в каком-то регионе проседает активность, и помочь. Например, в мае увидел, что в Краснодаре резко упало количество визитов — оказалось, что двое заболели. Оперативно перераспределили нагрузку.&#187;</p>
<footer>— Ирина, региональный директор</footer>
</blockquote>
<h3>Кейс 3: Стартап в медицинской технике (малая команда)</h3>
<p><strong>О компании:</strong></p>
<ul>
<li>Молодая компания, продажа медицинского оборудования для диагностики</li>
<li>Команда: 5 представителей + 1 руководитель (он же основатель)</li>
<li>География: Москва и Подмосковье</li>
<li>До внедрения: вообще никакого учёта, всё в головах и телефонных заметках</li>
</ul>
<p><strong>Проблемы до внедрения:</strong></p>
<ul>
<li>Основатель не понимал, куда уходит время представителей</li>
<li>Нет истории взаимодействия с клиентами</li>
<li>Представители сами забывали, с кем и когда встречались</li>
<li>Невозможно планировать работу — не понятно, кто свободен, кто загружен</li>
<li>При росте компании не будет базы для масштабирования</li>
</ul>
<p><strong>Особенность внедрения:</strong></p>
<p>У стартапа не было Bitrix24 и вообще никакой CRM. Внедрили только систему учёта визитов без интеграции. Вся информация хранится в собственной базе данных системы.</p>
<p><strong>Результаты через 4 месяца:</strong></p>
<ul>
<li>Зафиксировано <strong>1,240 визитов</strong> (около 60 в неделю на команду из 5 человек)</li>
<li>Основатель впервые увидел реальную картину работы: кто продуктивен, кто тратит время неэффективно</li>
<li>Выявили, что один представитель делал много визитов, но конверсия была 5% (против 25% в среднем по команде)</li>
<li>Провели обучение, поделились скриптами успешных коллег — конверсия выросла до 18%</li>
<li>База клиентов стала структурированным активом компании, а не набором визиток в кармане сотрудников</li>
<li>При привлечении инвестора смогли показать структурированные данные о работе с клиентами</li>
</ul>
<blockquote><p>&#171;Как основатель я делал всё на интуиции первые два года. Когда внедрили систему, впервые увидел цифры. Оказалось, что мои предположения о работе команды были верны только наполовину. Теперь принимаю решения на основе данных, а не догадок.&#187;</p>
<footer>— Дмитрий, основатель стартапа</footer>
</blockquote>
<h3>Кейс 4: Крупная федеральная компания (масштаб)</h3>
<p><strong>О компании:</strong></p>
<ul>
<li>Федеральный дистрибьютор медицинских препаратов</li>
<li>Команда: 87 представителей в 12 регионах России</li>
<li>Структура: представители → руководители отделов (12 чел.) → региональные директора (4 чел.) → коммерческий директор</li>
<li>До внедрения: хаос из Excel, 1С, Bitrix24, блокнотов и WhatsApp-отчётов</li>
</ul>
<p><strong>Проблемы до внедрения:</strong></p>
<ul>
<li>Каждый регион вёл учёт по-своему</li>
<li>Коммерческий директор получал сводку раз в месяц, уже неактуальную</li>
<li>Невозможно было сравнить эффективность регионов (разные метрики)</li>
<li>Текучка кадров 30% в год — знания о клиентах терялись</li>
<li>Дублирование визитов: представители из разных отделов ездили к одному клиенту, не зная друг о друге</li>
</ul>
<p><strong>Особенность внедрения:</strong></p>
<p>Поэтапное внедрение: сначала пилот в одном регионе (Новосибирск, 8 человек), через месяц — ещё в трёх регионах, через два месяца — во всех остальных.</p>
<p><strong>Результаты через 6 месяцев:</strong></p>
<ul>
<li>Обрабатывается <strong>~2,500 визитов в неделю</strong> по всей компании</li>
<li>Единая система учёта для всех 87 представителей</li>
<li>Коммерческий директор видит дашборд в реальном времени: активность по регионам, топ-клиенты, проблемные зоны</li>
<li>Выявили и устранили дублирование визитов — <strong>экономия 12% времени представителей</strong></li>
<li>Текучка кадров снизилась до 18% (потому что новички быстрее входят в работу благодаря структурированной базе знаний)</li>
<li>Экономия времени: <strong>~1,450 часов в месяц</strong> на всю компанию</li>
<li>В деньгах: <strong>~725,000₽ в месяц</strong> экономии рабочего времени</li>
</ul>
<table border="1" cellspacing="0" cellpadding="10">
<thead>
<tr>
<th>Регион</th>
<th>Визитов/неделю</th>
<th>Средняя конверсия</th>
<th>Проблемные зоны</th>
</tr>
</thead>
<tbody>
<tr>
<td>Москва</td>
<td>520</td>
<td>22%</td>
<td>Высокая конкуренция</td>
</tr>
<tr>
<td>Санкт-Петербург</td>
<td>380</td>
<td>28%</td>
<td>—</td>
</tr>
<tr>
<td>Новосибирск</td>
<td>280</td>
<td>31%</td>
<td>Недостаток кадров</td>
</tr>
<tr>
<td>Екатеринбург</td>
<td>240</td>
<td>26%</td>
<td>—</td>
</tr>
<tr>
<td>Казань</td>
<td>190</td>
<td>24%</td>
<td>—</td>
</tr>
<tr>
<td>Остальные регионы</td>
<td>890</td>
<td>25%</td>
<td>Разрозненность команд</td>
</tr>
</tbody>
</table>
<blockquote><p>&#171;Впервые за 5 лет работы компании у меня есть единая картина того, что происходит на местах. Раньше региональные директора присылали отчёты в PowerPoint раз в месяц — красивые слайды, но нулевая оперативность. Сейчас я открываю дашборд и за 2 минуты вижу, где всё хорошо, а где нужно вмешаться.&#187;</p>
<footer>— Сергей, коммерческий директор</footer>
</blockquote>
<h2>Подробный расчёт экономической эффективности</h2>
<h3>Расчёт для команды из 20 представителей (типичный размер отдела)</h3>
<p><strong>Исходные данные:</strong></p>
<ul>
<li>Количество представителей: 20 человек</li>
<li>Руководителей: 2 человека</li>
<li>Визитов в день на одного представителя: 3-4 (в среднем 3.5)</li>
<li>Рабочих дней в месяц: 22</li>
<li>Стоимость часа работы представителя: 500₽</li>
<li>Стоимость часа работы руководителя: 800₽</li>
</ul>
<h4>Экономия времени представителей</h4>
<table border="1" cellspacing="0" cellpadding="10">
<thead>
<tr>
<th>Активность</th>
<th>До системы</th>
<th>После системы</th>
<th>Экономия</th>
</tr>
</thead>
<tbody>
<tr>
<td>Фиксация визитов (в день)</td>
<td>60 минут (вечером по памяти)</td>
<td>10 минут (по ходу дня)</td>
<td>50 минут/день</td>
</tr>
<tr>
<td>Поиск информации о клиенте (в день)</td>
<td>15 минут (листать Excel/блокнот)</td>
<td>3 минуты (поиск в системе)</td>
<td>12 минут/день</td>
</tr>
<tr>
<td>Еженедельные планёрки</td>
<td>2 часа (все рассказывают устно)</td>
<td>1 час (только обсуждение стратегии)</td>
<td>1 час/неделю</td>
</tr>
<tr>
<td><strong>Итого на 1 человека:</strong></td>
<td>—</td>
<td>—</td>
<td><strong>62 мин/день + 1 час/неделю</strong></td>
</tr>
</tbody>
</table>
<p><strong>Расчёт экономии для представителей:</strong></p>
<ul>
<li>Экономия в день на одного: 62 минуты ≈ 1 час</li>
<li>Экономия в день на 20 человек: 20 часов</li>
<li>Экономия в месяц: 20 часов × 22 дня = 440 часов</li>
<li>В деньгах: 440 часов × 500₽ = <strong>220,000₽/месяц</strong></li>
</ul>
<h4>Экономия времени руководителей</h4>
<table border="1" cellspacing="0" cellpadding="10">
<thead>
<tr>
<th>Активность</th>
<th>До системы</th>
<th>После системы</th>
<th>Экономия</th>
</tr>
</thead>
<tbody>
<tr>
<td>Сбор информации с команды (в день)</td>
<td>1.5 часа (звонки, WhatsApp)</td>
<td>15 минут (проверка дашборда)</td>
<td>1 час 15 мин/день</td>
</tr>
<tr>
<td>Подготовка отчётов (в неделю)</td>
<td>4 часа (собрать из Excel)</td>
<td>30 минут (экспорт из системы)</td>
<td>3.5 часа/неделю</td>
</tr>
<tr>
<td>Анализ эффективности команды (в неделю)</td>
<td>2 часа (вручную)</td>
<td>30 минут (готовая аналитика)</td>
<td>1.5 часа/неделю</td>
</tr>
</tbody>
</table>
<p><strong>Расчёт экономии для руководителей:</strong></p>
<ul>
<li>Экономия в день на одного: 1.25 часа</li>
<li>Экономия в неделю на одного: 5 часов (3.5 + 1.5)</li>
<li>Экономия в месяц на 2 руководителей: (1.25 × 22 + 5 × 4) × 2 = 95 часов</li>
<li>В деньгах: 95 часов × 800₽ = <strong>76,000₽/месяц</strong></li>
</ul>
<h4>Итоговая экономия</h4>
<table border="1" cellspacing="0" cellpadding="10">
<thead>
<tr>
<th>Категория</th>
<th>Экономия времени (час/мес)</th>
<th>Экономия денег (₽/мес)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Представители (20 чел.)</td>
<td>440</td>
<td>220,000₽</td>
</tr>
<tr>
<td>Руководители (2 чел.)</td>
<td>95</td>
<td>76,000₽</td>
</tr>
<tr>
<td><strong>Всего:</strong></td>
<td><strong>535 часов</strong></td>
<td><strong>296,000₽</strong></td>
</tr>
</tbody>
</table>
<p><strong>Дополнительные бизнес-эффекты (сложно оценить точно, но они есть):</strong></p>
<ul>
<li><strong>+15-20% визитов в месяц:</strong> освободившееся время позволяет сделать больше встреч</li>
<li><strong>+5-10% конверсия:</strong> лучшая подготовка к визитам (есть история) даёт больше успешных встреч</li>
<li><strong>Снижение текучки:</strong> новички быстрее входят в работу → меньше увольнений в первые 3 месяца</li>
<li><strong>Лучшие решения:</strong> аналитика на основе данных вместо интуиции</li>
<li><strong>Конкурентное преимущество:</strong> более профессиональный подход к клиентам</li>
</ul>
<h2>Окупаемость системы (пересчёт)</h2>
<p><strong>Типичные расходы на внедрение:</strong></p>
<ul>
<li>Настройка и интеграция: 250,000-350,000₽ (среднее: <strong>300,000₽</strong>)</li>
<li>Обучение персонала: 20,000-40,000₽ (среднее: <strong>30,000₽</strong>)</li>
<li>Месячная подписка: 15,000-30,000₽ (для расчёта возьмём: <strong>30,000₽</strong>)</li>
</ul>
<hr />
<p><strong>Окупаемость для команды из 20 человек:</strong></p>
<p><strong>Первоначальные затраты:</strong></p>
<ul>
<li>300,000₽ (интеграция) + 30,000₽ (обучение) = <strong>330,000₽</strong></li>
</ul>
<p><strong>Ежемесячная экономия:</strong></p>
<ul>
<li><strong>296,000₽</strong> (как рассчитали ранее: 220,000₽ представители + 76,000₽ руководители)</li>
</ul>
<p><strong>Окупаемость:</strong></p>
<ul>
<li>330,000₽ ÷ 296,000₽ = <strong>1.11 месяца</strong></li>
<li>Это примерно <strong>5 недель</strong> (или чуть больше месяца)</li>
</ul>
<p><strong>Чистая выгода за первый год:</strong></p>
<ul>
<li>Экономия за год: 296,000₽ × 12 = 3,552,000₽</li>
<li>Минус первоначальные затраты: -330,000₽</li>
<li>Минус годовая подписка: 30,000₽ × 12 = -360,000₽</li>
<li><strong>ИТОГО: 2,862,000₽ чистой прибыли</strong></li>
</ul>
<hr />
<h3>Технические особенности: почему это работает надёжно</h3>
<h3>PWA (Progressive Web Application) вместо нативного приложения</h3>
<p><strong>Почему выбрали PWA:</strong></p>
<ul>
<li><strong>Кроссплатформенность:</strong> один код для iOS, Android, Web — не нужно разрабатывать 3 версии</li>
<li><strong>Мгновенное обновление:</strong> новая версия разворачивается на сервере и все пользователи получают её автоматически, не нужно ждать модерацию App Store/Google Play</li>
<li><strong>Работа без установки:</strong> открыл ссылку в браузере — уже работаешь, можешь добавить на главный экран</li>
<li><strong>Оффлайн-режим:</strong> Service Workers кэшируют приложение и данные, всё работает без интернета</li>
<li><strong>Меньше затрат:</strong> не нужно платить за аккаунты разработчика Apple ($99/год) и Google ($25 разово)</li>
</ul>
<p><strong>Как работает оффлайн:</strong></p>
<ol>
<li>При первом открытии приложение загружается в браузер и кэшируется</li>
<li>Service Worker перехватывает все запросы к серверу</li>
<li>Если интернета нет — данные сохраняются в IndexedDB (локальная база в браузере)</li>
<li>Когда интернет появляется — Service Worker автоматически синхронизирует данные с сервером</li>
<li>Пользователь не замечает разницы — просто работает</li>
</ol>
<h3>Двусторонняя синхронизация с Bitrix24</h3>
<p><strong>Как работает интеграция:</strong></p>
<ol>
<li><strong>Маппинг полей:</strong> в админке настраивается соответствие между полями системы и Bitrix24 (например, &#171;Название клиники&#187; → &#171;TITLE&#187;, &#171;ИНН&#187; → &#171;UF_CRM_1234567890&#187;)</li>
<li><strong>Создание визита в системе:</strong> представитель заполняет форму</li>
<li><strong>Сохранение в нашей БД:</strong> данные попадают в PostgreSQL</li>
<li><strong>Отправка в Bitrix24:</strong> через REST API создаётся элемент в смарт-процессе &#171;Визиты&#187;</li>
<li><strong>Получение ID:</strong> Bitrix24 возвращает ID созданной записи</li>
<li><strong>Связывание:</strong> ID из Bitrix24 сохраняется в нашей БД в поле bitrix_id</li>
<li><strong>Обратная синхронизация:</strong> если в Bitrix24 меняется статус визита или добавляется комментарий — webhook уведомляет нашу систему</li>
<li><strong>Обновление в системе:</strong> изменения из Bitrix24 применяются к записи в нашей БД</li>
</ol>
<p><strong>Преимущества двусторонней синхронизации:</strong></p>
<ul>
<li>Представители работают в удобном интерфейсе, оптимизированном для мобильных</li>
<li>Менеджеры и руководители видят всё в привычном Bitrix24</li>
<li>Можно добавлять комментарии и изменять статусы с обеих сторон</li>
<li>История всегда синхронна</li>
</ul>
<h3>Динамические поля для гибкости</h3>
<p>Каждая компания имеет свою специфику: кто-то фиксирует количество розданных образцов, кто-то — количество врачей на встрече, кто-то — температуру в помещении (для медицинского оборудования). Чтобы не переделывать систему под каждого клиента, используем динамические поля.</p>
<p><strong>Как это работает:</strong></p>
<ul>
<li>В базе данных есть поле <code>dynamic_fields</code> типа JSONB</li>
<li>Туда можно записать любые дополнительные данные: <code>{"samples_given": 5, "doctors_present": 3}</code></li>
<li>В админке настраивается, какие поля показывать в форме визита</li>
<li>Форма генерируется динамически на основе настроек</li>
<li>PostgreSQL умеет индексировать JSONB и быстро искать по этим полям</li>
</ul>
<p><strong>Пример настройки для фармацевтической компании:</strong></p>
<table border="1" cellspacing="0" cellpadding="10">
<thead>
<tr>
<th>Поле</th>
<th>Тип</th>
<th>Обязательное</th>
<th>Описание</th>
</tr>
</thead>
<tbody>
<tr>
<td>Количество врачей</td>
<td>Число</td>
<td>Нет</td>
<td>Сколько врачей присутствовало на встрече</td>
</tr>
<tr>
<td>Розданные образцы</td>
<td>Число</td>
<td>Нет</td>
<td>Количество бесплатных образцов препаратов</td>
</tr>
<tr>
<td>Интерес к продукту</td>
<td>Список</td>
<td>Да</td>
<td>Высокий / Средний / Низкий</td>
</tr>
<tr>
<td>Конкуренты</td>
<td>Текст</td>
<td>Нет</td>
<td>Какие конкуренты работают с клиникой</td>
</tr>
<tr>
<td>Следующий шаг</td>
<td>Текст</td>
<td>Нет</td>
<td>Что планируем делать дальше</td>
</tr>
</tbody>
</table>
<h2>Проблемы, с которыми столкнулся при разработке и как решил</h2>
<h3>Проблема 1: Производительность при больших объёмах данных</h3>
<p><strong>Симптомы:</strong></p>
<p>Когда в первой компании накопилось 7,000+ визитов, загрузка страницы со списком визитов стала занимать 5-7 секунд. Пользователи жаловались.</p>
<p><strong>Причина:</strong></p>
<p>API тянул все визиты сразу, JSON-ответ весил несколько мегабайт. Браузер тормозил при рендере такого большого списка.</p>
<p><strong>Решение:</strong></p>
<ul>
<li><strong>Пагинация:</strong> показываем по 50 записей на страницу, остальные подгружаем по требованию</li>
<li><strong>Фильтр по датам:</strong> по умолчанию показываем только визиты за последний месяц (обычно этого достаточно)</li>
<li><strong>Индексы в БД:</strong> добавил составные индексы <code>(user_id, date)</code> и <code>(company_id, date)</code> для быстрых выборок</li>
<li><strong>Кэширование на клиенте:</strong> React Query кэширует загруженные данные, повторные запросы идут из кэша</li>
<li><strong>Виртуализация списка:</strong> рендерим только видимые элементы, остальные не создаём в DOM</li>
</ul>
<p><strong>Результат:</strong></p>
<p>Время загрузки вернулось к 1-2 секундам даже при 10,000+ визитов в базе.</p>
<p>&nbsp;</p>
<h3>Проблема 2: Сложность интерфейса (первая версия была провалом)</h3>
<p><strong>История провала:</strong></p>
<p>Первая версия была перегружена функциями:</p>
<ul>
<li>15 полей для заполнения (большинство опциональных, но всё равно отпугивало)</li>
<li>Встроенный чат для обсуждения визитов с коллегами</li>
<li>Карта с маршрутами</li>
<li>Прогноз погоды</li>
<li>Калькулятор для расчёта объёма заказа</li>
<li>Меню с 3 уровнями вложенности</li>
</ul>
<p>Пилотная группа из 3 человек протестировала неделю. Отзывы:</p>
<ul>
<li>&#171;Слишком сложно, проще в блокнот записать&#187;</li>
<li>&#171;Запутался в меню, не нашёл нужную функцию&#187;</li>
<li>&#171;Зачем мне погода? Я и так на улице&#187;</li>
<li>&#171;На создание визита уходит 3-4 минуты, это долго&#187;</li>
</ul>
<p><strong>Решение: радикальное упрощение</strong></p>
<p>Переделал с нуля:</p>
<ul>
<li><strong>4 обязательных поля:</strong> Клиника, Врач (если есть), Результат (успешно/отказ/перенос), Комментарий</li>
<li><strong>Всё остальное опционально</strong> и скрыто за кнопкой &#171;Дополнительно&#187;</li>
<li><strong>Плоская навигация:</strong> главное меню с 5 пунктами, без вложенности</li>
<li><strong>Убрал:</strong> чат (есть Telegram), карты (есть Google Maps), погоду, калькулятор</li>
<li><strong>Фокус на скорости:</strong> от открытия формы до сохранения визита — 30-40 секунд</li>
</ul>
<p><strong>Результат:</strong></p>
<p>Вторая версия заработала. Активность выросла в 3 раза по сравнению с пилотом первой версии. Среднее время создания визита — 1 минута 15 секунд.</p>
<blockquote><p>&#171;Первая версия была как комбайн — 100 функций, 99 из которых не нужны. Вторая версия — это просто инструмент, который делает одно дело, но хорошо.&#187;</p>
<footer>— Из моего дневника разработки</footer>
</blockquote>
<h3>Проблема 3: Разные версии Bitrix24 у клиентов</h3>
<p><strong>Симптомы:</strong></p>
<p>У каждой компании Bitrix24 настроен по-своему: разные названия полей, разные структуры, разные версии API.</p>
<p><strong>Решение: система маппинга полей</strong></p>
<p>Создал таблицу <code>field_mappings</code>, где хранится соответствие между полями системы и Bitrix24 для каждой компании:</p>
<table border="1" cellspacing="0" cellpadding="10">
<thead>
<tr>
<th>Компания</th>
<th>Наше поле</th>
<th>Поле в Bitrix24</th>
</tr>
</thead>
<tbody>
<tr>
<td>Компания А</td>
<td>visit_type</td>
<td>UF_CRM_1234567890</td>
</tr>
<tr>
<td>Компания Б</td>
<td>visit_type</td>
<td>UF_CRM_0987654321</td>
</tr>
<tr>
<td>Компания В</td>
<td>visit_type</td>
<td>TYPE_VISIT</td>
</tr>
</tbody>
</table>
<p>При интеграции с новой компанией:</p>
<ol>
<li>Запрашиваю через API список всех полей в их Bitrix24</li>
<li>Показываю их в админке</li>
<li>Администратор вручную сопоставляет наши поля с их полями</li>
<li>Сохраняю маппинг в БД</li>
<li>Дальше всё работает автоматически на основе этого маппинга</li>
</ol>
<p><strong>Результат:</strong></p>
<p>Интеграция с новой компанией занимает 1-2 часа вместо нескольких дней переписывания кода.</p>
<h2>Процесс внедрения: как это происходит на практике</h2>
<h3>Типичный план внедрения (3-4 недели)</h3>
<table border="1" cellspacing="0" cellpadding="10">
<thead>
<tr>
<th>Этап</th>
<th>Длительность</th>
<th>Что происходит</th>
<th>Кто участвует</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>1. Анализ потребностей</strong></td>
<td>1-2 дня</td>
<td>• Созвон с руководством (1-2 часа)<br />
• Выяснение требований: количество сотрудников, регионы, CRM<br />
• Специфика работы: какие данные фиксируются<br />
• Права доступа: кто что может видеть<br />
• Подготовка плана внедрения</td>
<td>Я + директор + руководитель отдела</td>
</tr>
<tr>
<td><strong>2. Настройка интеграции</strong></td>
<td>2-3 дня</td>
<td>• Получение доступа к Bitrix24 (webhook или OAuth)<br />
• Загрузка базы компаний из Bitrix24<br />
• Настройка маппинга полей<br />
• Создание учётных записей для пользователей<br />
• Настройка прав доступа (роли)<br />
• Тестирование интеграции</td>
<td>Я + администратор Bitrix24</td>
</tr>
<tr>
<td><strong>3. Пилотное тестирование</strong></td>
<td>3-5 дней</td>
<td>• Выбор 2-3 продвинутых пользователей<br />
• Обучение пилотной группы (1 час)<br />
• Самостоятельная работа в системе<br />
• Ежедневная связь: вопросы, проблемы, предложения<br />
• Доработки по обратной связи<br />
• Проверка: всё ли синхронизируется, всё ли понятно</td>
<td>Я + 2-3 представителя + руководитель</td>
</tr>
<tr>
<td><strong>4. Обучение персонала</strong></td>
<td>1 день</td>
<td>• Групповое обучение (60 минут):<br />
&#8212; Обзор системы (10 мин)<br />
&#8212; Создание визита (20 мин)<br />
&#8212; Работа с историей (15 мин)<br />
&#8212; Оффлайн-режим (10 мин)<br />
&#8212; Ответы на вопросы (5 мин)<br />
• Выдача инструкции в PDF<br />
• Создание чата поддержки в Telegram</td>
<td>Я + все представители + руководители</td>
</tr>
<tr>
<td><strong>5. Запуск и поддержка</strong></td>
<td>Первая неделя</td>
<td>• Старт работы в боевом режиме<br />
• Постоянная связь в Telegram-чате<br />
• Быстрое исправление багов (если обнаружатся)<br />
• Ответы на вопросы в течение 1-2 часов<br />
• Сбор обратной связи<br />
• Мелкие доработки по запросам</td>
<td>Я + все пользователи</td>
</tr>
</tbody>
</table>
<h3>Что нужно от клиента для внедрения</h3>
<ul>
<li><strong>Доступ к Bitrix24:</strong> webhook URL или права администратора для настройки OAuth</li>
<li><strong>Список пользователей:</strong> ФИО, email, роли (представитель/руководитель/директор)</li>
<li><strong>База клиентов:</strong> желательно выгрузить из Bitrix24, чтобы не вводить вручную</li>
<li><strong>Время на обучение:</strong> 1 час для группового обучения персонала</li>
<li><strong>2-3 продвинутых пользователя для пилота:</strong> они первыми протестируют и дадут обратную связь</li>
<li><strong>Техническая часть:</strong> сервер для развёртывания (можно предоставить наш, можно на их инфраструктуре)</li>
</ul>
<h2>Что дальше: планы развития системы</h2>
<h3>1. Календарное представление визитов</h3>
<p>Визуализация встреч на календарной сетке (день/неделя/месяц) с возможностью drag-and-drop для переноса визитов между днями. Сейчас визиты показываются списком — удобно для истории, но не очень для планирования.</p>
<h3>2. Умная аналитика на основе истории</h3>
<ul>
<li><strong>Оптимальная частота визитов:</strong> система анализирует, как часто нужно ездить к разным категориям клиентов для максимальной конверсии</li>
<li><strong>Предсказание успешности:</strong> на основе истории предсказываем, в какой день недели и время лучше ехать к конкретной клинике</li>
<li><strong>Рекомендации по приоритетам:</strong> &#171;Клиника Х давно не посещалась, а раньше была перспективной&#187; или &#171;Клиника Y показывает рост интереса — стоит уделить больше внимания&#187;</li>
<li><strong>Сезонность:</strong> анализ, когда клиенты более активны (например, в медицине есть сезонность по заболеваниям)</li>
</ul>
<h3>3. Прикрепление файлов к визитам</h3>
<p>Возможность прикрепить к визиту документы: договор, презентацию, фотографию, скан. Ограничение: до 5 файлов по 10 МБ на визит. Форматы: PDF, JPG, PNG, DOCX.</p>
<p><strong>Сценарий:</strong> представитель после встречи фотографирует подписанный договор и прикрепляет к визиту — руководитель сразу видит, что сделка закрыта.</p>
<h3>4. Интеграция с другими CRM</h3>
<p>Сейчас поддерживается только Bitrix24. Планируется добавить:</p>
<ul>
<li>AmoCRM</li>
<li>1С:CRM</li>
</ul>
<p>Модульная архитектура позволяет добавлять коннекторы без переписывания основного кода.</p>
<h3>5. Геолокация и карта визитов</h3>
<ul>
<li>Автоматическое определение геопозиции при создании визита</li>
<li>Визуализация на карте: где был представитель сегодня, какие клиники рядом</li>
<li>Оптимальный маршрут на день с учётом пробок (интеграция с Яндекс.Картами или Google Maps)</li>
<li>Контроль: действительно ли представитель был в клинике (по геопозиции) или создал визит из офиса</li>
</ul>
<h3>6. Мобильные уведомления</h3>
<p>Push-уведомления для представителей:</p>
<ul>
<li>&#171;Напоминание: сегодня встреча в клинике X в 14:00&#187;</li>
<li>&#171;Вы давно не были в клинике Y — запланируйте визит&#187;</li>
<li>&#171;Руководитель оставил комментарий к вашему визиту&#187;</li>
</ul>
<h3>7. Интеграция с бухгалтерией</h3>
<p>Автоматический расчёт расходов на визиты:</p>
<ul>
<li>Километраж (на основе геопозиции)</li>
<li>Компенсация ГСМ</li>
<li>Суточные</li>
<li>Автоматическая выгрузка в 1С для бухгалтерии</li>
</ul>
<h2>Заключение: ключевые уроки разработки</h2>
<p>Создание системы учёта визитов заняло около 6 месяцев активной разработки + ещё 6 месяцев доработок по обратной связи от реальных пользователей. Сейчас система стабильно работает в нескольких компаниях, обрабатывает тысячи визитов в месяц, и я получаю положительные отзывы.</p>
<h3>5 главных уроков, которые я вынес</h3>
<ol>
<li><strong>Простота важнее функциональности.</strong> Лучше 5 функций, которыми пользуются, чем 50, которые только запутывают. Первая версия провалилась именно из-за перегруженности. Вторая, упрощённая, выстрелила.</li>
<li><strong>Оффлайн-режим — не фича, а обязательное требование.</strong> Для полевых сотрудников это критично. Без оффлайна система просто не будет использоваться в половине ситуаций.</li>
<li><strong>Интеграция важнее изоляции.</strong> Не нужно создавать ещё одну изолированную систему. Система должна вписываться в существующие процессы и интегрироваться с тем, что уже используется (Bitrix24, 1С, и т.д.).</li>
<li><strong>Слушайте пользователей, а не свои идеи.</strong> Половину лучших функций предложили сами пользователи после начала работы. Например, идею динамических полей подсказал клиент, который сказал: &#171;А можно ещё фиксировать температуру в помещении? У нас оборудование чувствительное&#187;. Я сделал универсальное решение — и оно пригодилось всем.</li>
<li><strong>Итерируйте быстро.</strong> MVP + обратная связь + доработки лучше, чем год разработки в вакууме. Я запустил первый пилот через 2 месяца разработки — и получил массу ценных инсайтов, которые никогда бы не пришли в голову за столом.</li>
</ol>
<h2></h2>
</article>
<p>&nbsp;</p><p>The post <a href="https://shknv.ru/sistema-uchjota-vizitov-medicinskih-predstavitelej/">Система учёта визитов медицинских представителей</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Бетон CRM: Новые фишки</title>
		<link>https://shknv.ru/beton-crm-novye-fishki/</link>
		
		<dc:creator><![CDATA[Evgeniy Shikunov]]></dc:creator>
		<pubDate>Sat, 11 Oct 2025 19:19:49 +0000</pubDate>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Pet]]></category>
		<category><![CDATA[portfolio]]></category>
		<category><![CDATA[автоматизация]]></category>
		<category><![CDATA[бетон]]></category>
		<category><![CDATA[производство]]></category>
		<category><![CDATA[разработка]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=409</guid>

					<description><![CDATA[<p>Beton CRM: От идеи до production — как мы создали современную систему управления заказами Расскажу о разработке полнофункциональной CRM-системы для управления заказами бетона с интеграцией Bitrix24. В процессе создания проекта мы внедрили множество интересных технических решений, включая Elasticsearch для молниеносного поиска, периодические заявки, динамические формы и многое другое. Что мы построили Beton CRM — это [&#8230;]</p>
<p>The post <a href="https://shknv.ru/beton-crm-novye-fishki/">Бетон CRM: Новые фишки</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><span style="font-size: 2.25em; font-weight: 800;">Beton CRM: От идеи до production — как мы создали современную систему управления заказами</span></p>
<article>
<p class="lead">Расскажу о разработке полнофункциональной CRM-системы для управления заказами бетона с интеграцией Bitrix24.<br />
В процессе создания проекта мы внедрили множество интересных технических решений, включая Elasticsearch для<br />
молниеносного поиска, периодические заявки, динамические формы и многое другое.</p>
<h2>Что мы построили</h2>
<p><strong>Beton CRM</strong> — это полноценная система управления заказами на бетон с веб-интерфейсом,<br />
которая решает реальные бизнес-задачи:</p>
<ul>
<li>Прием и обработка заказов через динамические формы</li>
<li>Интеграция с Bitrix24 для управления сделками</li>
<li>Молниеносный поиск по всей базе заказов и клиентов</li>
<li>Создание периодических заявок (например, ежедневные поставки на месяц)</li>
<li>Адаптивный интерфейс для мобильных устройств и десктопа</li>
</ul>
<h2>Elasticsearch: Умный поиск на стероидах</h2>
<p>Одна из самых интересных фич проекта — это система поиска на базе <strong>Elasticsearch</strong>.<br />
Мы не просто добавили поиск, а создали интеллектуальную систему с множеством продвинутых возможностей.</p>
<h3>Что умеет наш поиск:</h3>
<h4>1. Адаптивные стратегии поиска</h4>
<p>Система автоматически выбирает оптимальную стратегию поиска в зависимости от длины запроса:</p>
<ul>
<li><strong>Короткие запросы (&lt;5 символов):</strong> Агрессивный fuzzy-поиск с автокомплитом и высокой толерантностью к опечаткам</li>
<li><strong>Средние запросы (5-20 символов):</strong> Сбалансированный подход с точным совпадением, wildcard-поиском и multi-match</li>
<li><strong>Длинные запросы (&gt;20 символов):</strong> Оптимизированный поиск по длинным текстам с точным фразовым совпадением</li>
</ul>
<h4>2. Специальные анализаторы для русского языка</h4>
<pre style="background: #2d2d2d; color: #f8f8f2; padding: 15px; border-radius: 5px; overflow-x: auto;"><code>product_search: {
    type: 'custom',
    tokenizer: 'standard',
    filter: [
        'lowercase',
        'russian_stop',      // Фильтрация стоп-слов
        'russian_stemmer',   // Стемминг для русского
        'product_synonyms',  // Синонимы для товаров
        'product_edge_ngram' // N-граммы для частичного совпадения
    ]
}</code></pre>
<h4>3. Умные синонимы для строительной отрасли</h4>
<p>Система понимает отраслевую специфику и обрабатывает синонимы:</p>
<ul>
<li>бетон <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> цемент <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> смесь</li>
<li>В25 <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> В-25 <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> бетон В25 <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> марка В25</li>
<li>М300 <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> М-300 <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> марка 300 <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> бетон М300</li>
<li>фундамент <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> основание <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> база <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> фундаментный</li>
</ul>
<h4>4. Интеллектуальный скоринг результатов</h4>
<p>Elasticsearch не просто находит документы, но и умно ранжирует их:</p>
<ul>
<li><strong>Boost ×2.0</strong> для точных совпадений марок бетона (В25, М300)</li>
<li><strong>Boost ×1.3</strong> для заявок с высоким приоритетом</li>
<li><strong>Boost ×1.2</strong> для недавно созданных документов (последние 30 дней)</li>
<li><strong>Boost ×1.15</strong> для активных статусов (NEW, IN_PROCESS, PENDING)</li>
<li><strong>Min score 0.5</strong> для фильтрации нерелевантных результатов</li>
</ul>
<h4>5. Встроенное кэширование поисковых запросов</h4>
<pre style="background: #2d2d2d; color: #f8f8f2; padding: 15px; border-radius: 5px; overflow-x: auto;"><code>// In-memory кэш с TTL 2 минуты
private searchCache = new Map&lt;string, {
    data: SearchResult[];
    timestamp: number
}&gt;()
private readonly CACHE_TTL = 2 * 60 * 1000
private readonly MAX_CACHE_SIZE = 500</code></pre>
<h4>6. Подсветка найденных фрагментов</h4>
<p>Результаты поиска отображаются с подсветкой найденных фрагментов в HTML-формате:</p>
<pre style="background: #f5f5f5; padding: 10px; border-radius: 5px;"><code>&lt;mark&gt;бетон В25&lt;/mark&gt; для фундамента с доставкой</code></pre>
<h2>Периодические заявки: Автоматизация рутины</h2>
<p>Еще одна инновационная фича — <strong>система периодических заявок</strong>. Представьте: клиенту нужна<br />
ежедневная поставка бетона на месяц. Вместо создания 30 заявок вручную, система делает это автоматически!</p>
<h3>Как это работает:</h3>
<ol>
<li><strong>Выбор периода:</strong> Пользователь включает режим &#171;Периодические заявки&#187; и выбирает диапазон дат</li>
<li><strong>Заполнение формы:</strong> Все поля (кроме даты доставки) заполняются один раз</li>
<li><strong>Магия транзакций:</strong> Система создает по одной заявке на каждый день выбранного периода</li>
<li><strong>Синхронизация с Bitrix24:</strong> Для каждой заявки автоматически создается сделка в CRM</li>
<li><strong>Атомарность:</strong> Если хоть одна заявка не создалась — откатывается вся транзакция</li>
</ol>
<h3>Технические детали:</h3>
<pre style="background: #2d2d2d; color: #f8f8f2; padding: 15px; border-radius: 5px; overflow-x: auto;"><code>// Создание периодической группы с транзакцией
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
}</code></pre>
<p>Система также умеет:</p>
<ul>
<li>Массово обновлять все заявки периода (кроме даты)</li>
<li>Отменять весь период одной кнопкой</li>
<li>Отслеживать прогресс выполнения периода</li>
<li>Хранить метаданные для аудита</li>
</ul>
<h2> Динамический конструктор форм</h2>
<p>В CRM реализован мощный <strong>drag-and-drop конструктор форм</strong> с административной панелью:</p>
<h3>Возможности конструктора:</h3>
<ul>
<li><strong>15+ типов полей:</strong> текст, число, дата, время, выпадающий список, автокомплит, чекбокс, радио, файлы, заголовки, разделители</li>
<li><strong>Секционная организация:</strong> Поля группируются в разделы с аккордеонами</li>
<li><strong>Drag &amp; Drop:</strong> Перетаскивание полей между секциями и изменение порядка</li>
<li><strong>Связанные поля:</strong> Автозаполнение данных из Bitrix24 по выбранному клиенту</li>
<li><strong>Условная логика:</strong> Поля могут показываться/скрываться в зависимости от других полей</li>
<li><strong>Валидация:</strong> Кастомные правила проверки на фронте и бэкенде</li>
<li><strong>Bitrix24 mapping:</strong> Автоматическое связывание полей формы с полями Bitrix24</li>
</ul>
<h3>Адаптивность:</h3>
<p>Формы автоматически переключаются между десктопной и мобильной версией:</p>
<ul>
<li><strong>Desktop:</strong> Аккордеоны с секциями, кнопки управления, прогресс заполнения</li>
<li><strong>Mobile:</strong> Упрощенная версия с touch-friendly элементами и оптимизацией под экраны смартфонов</li>
</ul>
<h2> Миграция с MongoDB на PostgreSQL</h2>
<p>Проект изначально использовал MongoDB, но мы провели полную миграцию на PostgreSQL с TypeORM. Почему?</p>
<ul>
<li><strong>ACID-транзакции:</strong> Критично для периодических заявок и финансовых операций</li>
<li><strong>Сложные связи:</strong> Множество отношений между сущностями (формы → поля → заявки → пользователи)</li>
<li><strong>Миграции схемы:</strong> TypeORM предоставляет удобный механизм версионирования БД</li>
<li><strong>Производительность JOIN:</strong> Эффективная работа со связанными данными</li>
</ul>
<h3>Ключевые сущности:</h3>
<pre style="background: #2d2d2d; color: #f8f8f2; padding: 15px; border-radius: 5px; overflow-x: auto;"><code>User ← (1:N) → Submission ← (N:1) → Form ← (1:N) → FormField
                    ↓
              (N:1) SubmissionPeriodGroup
                    ↓
            (1:N) Submission (periodic)</code></pre>
<h2>Интеграция с Bitrix24</h2>
<p>Система плотно интегрирована с <strong>Bitrix24 CRM</strong> через webhook API:</p>
<h3>Что интегрировано:</h3>
<ul>
<li><strong>Автоматическое создание сделок:</strong> При отправке формы создается сделка в Bitrix24</li>
<li><strong>Синхронизация статусов:</strong> Двусторонняя синхронизация статусов сделок</li>
<li><strong>Подгрузка справочников:</strong> Автокомплит клиентов, компаний, товаров из Bitrix24</li>
<li><strong>Связанные поля:</strong> При выборе клиента автоматически заполняются телефон, email, адрес</li>
<li><strong>Кэширование:</strong> Redis-кэш для API-ответов Bitrix24 (TTL: 30 минут &#8212; 2 часа)</li>
<li><strong>Обратная связь:</strong> ID заявки записывается в пользовательское поле Bitrix24</li>
</ul>
<p><span style="font-size: 1.5em; font-weight: bold;">In-Memory кэширование</span></p>
<p>Для оптимизации производительности реализована <strong>многоуровневая система кэширования</strong>:</p>
<h3>1. CacheService (базовый)</h3>
<pre style="background: #2d2d2d; color: #f8f8f2; padding: 15px; border-radius: 5px; overflow-x: auto;"><code>const memoryCache = new Map&lt;string, {
    data: any;
    expires: number
}&gt;()

// Паттерн get-or-set
async getOrSet&lt;T&gt;(
    key: string,
    setter: () =&gt; Promise&lt;T&gt;,
    options?: CacheOptions
): Promise&lt;T | null&gt;</code></pre>
<h3>2. BitrixCacheService (специализированный)</h3>
<ul>
<li>Категории сделок: TTL 2 часа</li>
<li>Стадии сделок: TTL 1 час</li>
<li>Динамические опции (клиенты, товары): TTL 30 минут</li>
</ul>
<h3>3. FormCacheService (для форм)</h3>
<ul>
<li>Формы с полями: TTL 30 минут</li>
<li>Список активных форм: TTL 10 минут</li>
</ul>
<h3>4. Elasticsearch SearchCache</h3>
<ul>
<li>Результаты поиска: TTL 2 минуты</li>
<li>Максимальный размер: 500 записей</li>
<li>Auto-cleanup устаревших записей</li>
</ul>
<h2>Docker-инфраструктура</h2>
<p>Весь проект упакован в Docker с продакшн-оптимизацией:</p>
<h3>Сервисы в docker-compose:</h3>
<ul>
<li><strong>PostgreSQL 16 Alpine:</strong> Компактная БД с health checks</li>
<li><strong>Redis 7 Alpine:</strong> Кэш с AOF persistence</li>
<li><strong>Elasticsearch 8.11:</strong> Поисковый движок с ограниченной памятью (512MB)</li>
<li><strong>Backend:</strong> Node.js API с multi-stage build</li>
<li><strong>Frontend:</strong> Nginx + статика React с оптимизацией</li>
</ul>
<h3>Особенности конфигурации:</h3>
<pre style="background: #2d2d2d; color: #f8f8f2; padding: 15px; border-radius: 5px; overflow-x: auto;"><code>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 }</code></pre>
<h2>E2E тестирование с Playwright</h2>
<p>Для обеспечения качества реализованы E2E-тесты на <strong>Playwright</strong>:</p>
<ul>
<li>Тестирование аутентификации (вход/выход)</li>
<li>Создание и отправка заявок</li>
<li>Административные функции</li>
<li>Тесты API endpoints</li>
<li>Интеграция с Bitrix24</li>
</ul>
<h2>Производительность и оптимизации</h2>
<h3>Backend оптимизации:</h3>
<ul>
<li><strong>Connection pooling</strong> для PostgreSQL</li>
<li><strong>Индексы БД</strong> на часто запрашиваемые поля</li>
<li><strong>Lazy loading</strong> связанных сущностей в TypeORM</li>
<li><strong>Background jobs</strong> для тяжелых операций (синхронизация с Bitrix24)</li>
<li><strong>Elasticsearch refresh_interval: 30s</strong> для лучшей производительности индексации</li>
</ul>
<h3>Frontend оптимизации:</h3>
<ul>
<li><strong>React Query</strong> для кэширования серверных данных</li>
<li><strong>Code splitting</strong> на уровне роутов</li>
<li><strong>Debouncing</strong> для автокомплита и поиска</li>
<li><strong>Виртуализация</strong> длинных списков в таблицах</li>
<li><strong>Lazy loading</strong> компонентов форм</li>
</ul>
<h2>Безопасность</h2>
<ul>
<li><strong>JWT токены</strong> с refresh механизмом (access: 7 дней, refresh: 30 дней)</li>
<li><strong>Bcrypt хэширование</strong> паролей с солью</li>
<li><strong>Role-based access control</strong> (user/admin)</li>
<li><strong>CORS</strong> с белым списком доменов</li>
<li><strong>Input validation</strong> на фронте (Yup) и бэкенде (class-validator)</li>
<li><strong>SQL injection protection</strong> через TypeORM query builder</li>
<li><strong>Rate limiting</strong> для API endpoints</li>
</ul>
<h2>Мобильная адаптация</h2>
<p>Система полностью адаптирована для мобильных устройств:</p>
<ul>
<li><strong>Responsive breakpoints:</strong> xs, sm, md, lg, xl</li>
<li><strong>Touch-friendly:</strong> Увеличенные кнопки и поля ввода</li>
<li><strong>Упрощенные формы:</strong> Автопереключение на SimpleMobileBetoneForm</li>
<li><strong>Progressive disclosure:</strong> Секции открываются по одной</li>
<li><strong>Оптимизация трафика:</strong> Сжатие данных, ленивая загрузка</li>
</ul>
<h2>Чему я научился</h2>
<p>Этот проект был отличным опытом работы с современным стеком технологий:</p>
<ul>
<li>Настройка и тонкая настройка <strong>Elasticsearch</strong> для русскоязычного контента</li>
<li>Проектирование <strong>сложных транзакций</strong> с TypeORM</li>
<li>Оптимизация производительности с <strong>многоуровневым кэшированием</strong></li>
<li>Интеграция с внешними API (<strong>Bitrix24 webhook</strong>)</li>
<li>Создание <strong>type-safe</strong> приложений с TypeScript</li>
<li><strong>Docker-оркестрация</strong> для продакшен-окружения</li>
<li>E2E тестирование с <strong>Playwright</strong></li>
<li>Работа с <strong>Material-UI</strong> и создание адаптивных интерфейсов</li>
</ul>
<h2>Что дальше?</h2>
<p>Планы по развитию проекта:</p>
<ul>
<li>Внедрение <strong>WebSocket</strong> для real-time уведомлений</li>
<li>Добавление <strong>аналитики и отчетов</strong> (дашборды, графики)</li>
<li>Интеграция с <strong>1C</strong> для учета</li>
<li>Мобильное приложение на <strong>React Native</strong></li>
<li>Система <strong>уведомлений</strong> (email, SMS, push)</li>
<li>AI-ассистент для <strong>предсказания спроса</strong></li>
</ul>
<h2>Заключение</h2>
<p><strong>Beton CRM</strong> — это пример того, как современные технологии могут решать реальные бизнес-задачи.<br />
Мы создали систему, которая не только автоматизирует процессы, но и делает работу с заказами приятной и эффективной.</p>
<p>Особенно горжусь реализацией <strong>Elasticsearch</strong> с умным поиском, системой <strong>периодических заявок</strong><br />
с транзакциями и <strong>динамическим конструктором форм</strong>. Эти фичи действительно выделяют проект среди типовых CRM.</p>
<p style="margin-top: 40px; font-style: italic; color: #666;">Если у вас есть вопросы по реализации каких-то частей или хотите обсудить архитектурные решения —<br />
пишите! Буду рад поделиться опытом.</p>
<hr style="margin: 40px 0; border: none; border-top: 2px solid #e0e0e0;" />
<p style="text-align: center; color: #888;"><strong>Технологии:</strong> React 19, TypeScript, Node.js, Express, PostgreSQL, TypeORM,<br />
Elasticsearch 8.11, Redis, Docker, Material-UI 7, React Query, Bitrix24 API, Playwright</p>
</article>
<p>&nbsp;</p><p>The post <a href="https://shknv.ru/beton-crm-novye-fishki/">Бетон CRM: Новые фишки</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Кейс: Разработка системы автоматического мониторинга цен конкурентов</title>
		<link>https://shknv.ru/397-2/</link>
		
		<dc:creator><![CDATA[Evgeniy Shikunov]]></dc:creator>
		<pubDate>Fri, 22 Aug 2025 14:50:03 +0000</pubDate>
				<category><![CDATA[Pet]]></category>
		<category><![CDATA[portfolio]]></category>
		<category><![CDATA[автоматизация]]></category>
		<category><![CDATA[кейс]]></category>
		<category><![CDATA[мониторинг]]></category>
		<category><![CDATA[парсинг]]></category>
		<category><![CDATA[цены]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=397</guid>

					<description><![CDATA[<p>Кейс: Разработка системы автоматического мониторинга цен конкурентов Fullstack-проект с современным технологическим стеком: FastAPI, React, PostgreSQL, Redis, Celery Задача проекта Разработать веб-приложение для автоматизации процесса мониторинга цен конкурентов в B2B сегменте. Система должна заменить ручной процесс сбора данных, который занимал 4-6 часов ежедневно. Ключевые требования к системе:  Автоматизация сбора данных с множественных источников  Аналитика и визуализация [&#8230;]</p>
<p>The post <a href="https://shknv.ru/397-2/">Кейс: Разработка системы автоматического мониторинга цен конкурентов</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<h1>Кейс: Разработка системы автоматического мониторинга цен конкурентов</h1>
<p><em>Fullstack-проект с современным технологическим стеком: FastAPI, React, PostgreSQL, Redis, Celery</em></p>
<h1><img fetchpriority="high" decoding="async" class="aligncenter size-full wp-image-464" src="https://shknv.ru/wp-content/uploads/2025/08/image.png" alt="" width="1536" height="1024" srcset="https://shknv.ru/wp-content/uploads/2025/08/image.png 1536w, https://shknv.ru/wp-content/uploads/2025/08/image-300x200.png 300w, https://shknv.ru/wp-content/uploads/2025/08/image-1024x683.png 1024w, https://shknv.ru/wp-content/uploads/2025/08/image-768x512.png 768w" sizes="(max-width: 1536px) 100vw, 1536px" /></h1>
<h2>Задача проекта</h2>
<p>Разработать веб-приложение для автоматизации процесса мониторинга цен конкурентов в B2B сегменте. Система должна заменить ручной процесс сбора данных, который занимал 4-6 часов ежедневно.</p>
<p>Ключевые требования к системе:</p>
<ul>
<li> <strong>Автоматизация сбора данных</strong> с множественных источников</li>
<li> <strong>Аналитика и визуализация</strong> исторических данных</li>
<li> <strong>Мгновенные уведомления</strong> о критических изменениях</li>
<li> <strong>Гибкая настройка</strong> источников и правил мониторинга</li>
<li> <strong>Масштабируемость</strong> для обработки больших объемов данных</li>
</ul>
<h2>Техническое решение</h2>
<p>Разработана система <strong>PriceWatch</strong> — полнофункциональное веб-приложение для автоматического мониторинга ценовой информации. Архитектура спроектирована с учетом требований к производительности, надежности и возможности горизонтального масштабирования.</p>
<h3><img decoding="async" class="aligncenter size-large wp-image-399" src="https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.12-1024x439.png" alt="" width="1024" height="439" srcset="https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.12-1024x439.png 1024w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.12-300x129.png 300w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.12-768x329.png 768w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.12-1536x659.png 1536w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.12-2048x879.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></h3>
<h3> Основной функционал системы:</h3>
<ol>
<li><strong>Автоматический сбор данных</strong> с множественных веб-источников</li>
<li><strong>Интеллектуальный анализ</strong> изменений и аномалий</li>
<li><strong>Долгосрочное хранение</strong> исторических данных</li>
<li><strong>Система уведомлений</strong> о критических изменениях</li>
<li><strong>Аналитическая отчетность</strong> и экспорт данных</li>
</ol>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f527.png" alt="🔧" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Архитектура парсинг-модулей:</h3>
<p>Система поддерживает подключение различных источников данных через универсальную архитектуру парсеров:</p>
<ul>
<li> <strong>Базовый абстрактный класс</strong> для всех парсеров</li>
<li> <strong>Специализированные модули</strong> для каждого источника</li>
<li><strong>Автоматическая обработка ошибок</strong> и повторные попытки</li>
<li><strong>Валидация данных</strong> на всех этапах обработки</li>
<li> <strong>Гибкая настройка</strong> параметров парсинга</li>
</ul>
<h2>Технологический стек</h2>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3d7.png" alt="🏗" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Архитектура приложения</h3>
<p>Система построена на современных enterprise-технологиях с акцентом на производительность и масштабируемость:</p>
<ul>
<li><strong>Backend:</strong> FastAPI + SQLAlchemy — асинхронный REST API</li>
<li><strong>Frontend:</strong> React + TypeScript + Ant Design — SPA интерфейс</li>
<li><strong>База данных:</strong> PostgreSQL — реляционное хранение данных</li>
<li><strong>Очереди задач:</strong> Celery + Redis — асинхронная обработка задач</li>
<li><strong>Контейнеризация:</strong> Docker + Docker Compose — простое развертывание</li>
<li><strong>Веб-сервер:</strong> Nginx — reverse proxy и статические файлы</li>
</ul>
<h3> Умный алгоритм парсинга</h3>
<p>Каждый парсер работает по единому алгоритму:</p>
<ol>
<li><strong>Получение страницы</strong> с товаром (с повторными попытками при ошибках)</li>
<li><strong>Извлечение цены</strong> из HTML-кода страницы</li>
<li><strong>Валидация данных</strong> (цена должна быть разумной)</li>
<li><strong>Сравнение с предыдущими значениями</strong> для выявления изменений</li>
<li><strong>Сохранение в базу данных</strong> с временной меткой</li>
</ol>
<h2>Результаты проекта</h2>
<h3> Ключевые показатели эффективности:</h3>
<table style="width: 100%; border-collapse: collapse;" border="1">
<tbody>
<tr>
<th>Метрика</th>
<th>Было</th>
<th>Стало</th>
<th>Улучшение</th>
</tr>
<tr>
<td>Время на мониторинг</td>
<td>4-6 часов в день</td>
<td>15 минут в день</td>
<td><strong>95% автоматизация</strong></td>
</tr>
<tr>
<td>Покрытие товарных позиций</td>
<td>200-300 единиц</td>
<td>2000+ единиц</td>
<td><strong>×7 масштабирование</strong></td>
</tr>
<tr>
<td>Частота обновления данных</td>
<td>1-2 раза в неделю</td>
<td>24/7 мониторинг</td>
<td><strong>Real-time данные</strong></td>
</tr>
<tr>
<td>Точность прогнозов</td>
<td>Интуитивные оценки</td>
<td>Data-driven решения</td>
<td><strong>Аналитический подход</strong></td>
</tr>
</tbody>
</table>
<h3> Техническая эффективность:</h3>
<ul>
<li><strong>Производительность:</strong> обработка 10,000+ запросов в день</li>
<li><strong>Надежность:</strong> 99.9% uptime системы</li>
<li><strong>Масштабируемость:</strong> горизонтальное расширение парсеров</li>
<li><strong>Мониторинг:</strong> детальное логирование и метрики производительности</li>
</ul>
<h2>Работа системы</h2>
<h3> Жизненный цикл обработки данных</h3>
<p>Система работает по следующему алгоритму:</p>
<ul>
<li><strong>02:00</strong> — Автоматический запуск процедур сбора данных</li>
<li><strong>02:00-04:00</strong> — Параллельная обработка всех источников</li>
<li><strong>04:00-04:30</strong> — Анализ изменений и генерация уведомлений</li>
<li><strong>04:30-05:00</strong> — Обновление аналитических отчетов</li>
<li><strong>05:00+</strong> — Данные доступны пользователям через веб-интерфейс</li>
</ul>
<h3> Интеллектуальная система алертов</h3>
<p>Система анализирует данные и автоматически определяет важные события:</p>
<ul>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f534.png" alt="🔴" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Критические изменения (&gt;20%):</strong> Мгновенное уведомление</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f7e1.png" alt="🟡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Значительные изменения (10-20%):</strong> Уведомление в интерфейсе</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f7e0.png" alt="🟠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Недоступность источника 3+ дня:</strong> Техническое предупреждение</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f7e2.png" alt="🟢" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Новые экстремумы:</strong> Статистические аномалии</li>
</ul>
<h2>Интерфейсы и возможности</h2>
<p><img decoding="async" class="aligncenter size-large wp-image-404" src="https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.59-1024x846.png" alt="" width="1024" height="846" srcset="https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.59-1024x846.png 1024w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.59-300x248.png 300w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.59-768x634.png 768w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.59-1536x1269.png 1536w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.50.59.png 1886w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<h3> Аналитический дашборд</h3>
<p>Веб-интерфейс предоставляет комплексную аналитику:</p>
<ul>
<li><strong>Real-time дашборд:</strong> текущее состояние мониторинга</li>
<li><strong>Исторические тренды:</strong> графики изменений во времени</li>
<li><strong>Статистика обработки:</strong> метрики работы парсеров</li>
<li><strong>Интерактивные фильтры:</strong> настраиваемые представления данных</li>
</ul>
<h3> Административная панель</h3>
<p>Система предоставляет полный контроль над процессом мониторинга:</p>
<ul>
<li> <strong>Управление номенклатурой</strong> через веб-интерфейс</li>
<li> <strong>Настройка источников</strong> для каждой позиции</li>
<li> <strong>Категоризация и теги</strong> для группировки данных</li>
<li> <strong>Экспорт отчетов</strong> в различных форматах</li>
</ul>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-402" src="https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.51.23-1024x494.png" alt="" width="1024" height="494" srcset="https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.51.23-1024x494.png 1024w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.51.23-300x145.png 300w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.51.23-768x371.png 768w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.51.23-1536x742.png 1536w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.51.23.png 1800w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<h3> Гибкая настройка парсинга</h3>
<ul>
<li><strong>Расписание:</strong> ежедневно в 2:00 (настраивается)</li>
<li><strong>Повторные попытки:</strong> до 3 попыток при ошибках</li>
<li><strong>Таймауты:</strong> 30 секунд на запрос (настраивается)</li>
<li><strong>User-Agent:</strong> ротация для избежания блокировок</li>
</ul>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-400" src="https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.52.05-822x1024.png" alt="" width="822" height="1024" srcset="https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.52.05-822x1024.png 822w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.52.05-241x300.png 241w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.52.05-768x956.png 768w, https://shknv.ru/wp-content/uploads/2025/08/CleanShot-2025-08-22-at-17.52.05.png 991w" sizes="auto, (max-width: 822px) 100vw, 822px" /></p>
<h2>Развертывание за 15 минут</h2>
<p>Благодаря использованию Docker, развертывание PriceWatch занимает всего несколько команд:</p>
<pre><code>
# Клонирование проекта
git clone [repository-url]
cd pricewatch

# Настройка конфигурации
cp .env.example .env

# Запуск системы
docker compose up -d

# Применение миграций
docker compose exec backend alembic upgrade head
</code></pre>
<p><strong>Готово!</strong> Система доступна по адресу <code>http://localhost:18080</code></p>
<h2>Масштабируемость и развитие</h2>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Планы развития системы</h3>
<p><strong>Версия 2.0 (планируется):</strong></p>
<ul>
<li> <strong>Интеграция с 1С</strong> для автоматической синхронизации номенклатуры</li>
<li> <strong>Мобильное приложение</strong> для мониторинга &#171;на ходу&#187;</li>
<li> <strong>Машинное обучение</strong> для прогнозирования цен</li>
<li> <strong>Расширенная аналитика</strong> с рекомендациями по ценообразованию</li>
</ul>
<p><strong>Версия 3.0 (перспектива):</strong></p>
<ul>
<li> <strong>Мониторинг наличия товаров</strong> у конкурентов</li>
<li> <strong>Парсинг характеристик</strong> для полного сравнения</li>
<li> <strong>Интеграция с маркетплейсами</strong> (Wildberries, Ozon)</li>
<li> <strong>Конкурентный анализ ассортимента</strong></li>
</ul>
<h2>Технические преимущества архитектуры</h2>
<h3> Микросервисная архитектура</h3>
<p>PriceWatch построен по принципам современной разработки:</p>
<ul>
<li><strong>Разделение ответственности:</strong> API, парсинг, интерфейс — независимые сервисы</li>
<li><strong>Горизонтальное масштабирование:</strong> можно добавлять новые парсеры без изменения кода</li>
<li><strong>Отказоустойчивость:</strong> если один сервис недоступен, остальные работают</li>
<li><strong>Простота обслуживания:</strong> каждый компонент обновляется независимо</li>
</ul>
<h3> Безопасность и надежность</h3>
<ul>
<li><strong>JWT-аутентификация</strong> для защиты API</li>
<li><strong>Защита от блокировок</strong> при парсинге (ротация User-Agent, задержки)</li>
<li><strong>Логирование всех операций</strong> для отладки и аудита</li>
<li><strong>Автоматические backup&#8217;ы</strong> базы данных</li>
</ul>
<h2>Технические особенности реализации</h2>
<h3> Архитектурные решения</h3>
<ul>
<li><strong>Микросервисная архитектура:</strong> независимые модули для каждого типа задач</li>
<li><strong>Асинхронная обработка:</strong> Celery workers для фонового выполнения</li>
<li><strong>Кэширование:</strong> Redis для повышения производительности</li>
<li><strong>Мониторинг:</strong> Логирование и метрики работы системы</li>
</ul>
<h3> База данных и модели</h3>
<ul>
<li><strong>ORM:</strong> SQLAlchemy для работы с базой данных</li>
<li><strong>Миграции:</strong> Alembic для версионирования схемы</li>
<li><strong>Связи:</strong> Many-to-many отношения между товарами и источниками</li>
<li><strong>Индексы:</strong> Оптимизация запросов к историческим данным</li>
</ul>
<h2>Заключение</h2>
<p>Проект демонстрирует успешную реализацию полнофункциональной системы мониторинга с современным технологическим стеком. Ключевые достижения проекта:</p>
<ul>
<li> <strong>Высокая производительность:</strong> обработка тысяч запросов</li>
<li> <strong>Масштабируемость:</strong> легкое добавление новых источников</li>
<li> <strong>Автоматизация:</strong> 95% сокращение ручного труда</li>
<li> <strong>Modern tech stack:</strong> использование актуальных технологий</li>
</ul>
<h3> Возможности развития</h3>
<p>Архитектура системы позволяет легко расширять функционал:</p>
<ul>
<li> <strong>API интеграции</strong> с внешними системами</li>
<li> <strong>Machine Learning</strong> для прогнозирования трендов</li>
<li> <strong>Расширенная аналитика</strong> и бизнес-интеллект</li>
<li> <strong>Интеграция с ERP/CRM</strong> системами</li>
</ul>
<hr />
<h3> Исходный код</h3>
<p>Проект реализован как fullstack-приложение с полной контейнеризацией:</p>
<ul>
<li><strong>Backend:</strong> FastAPI + SQLAlchemy + Celery</li>
<li><strong>Frontend:</strong> React + TypeScript + Ant Design</li>
<li><strong>Infrastructure:</strong> Docker + PostgreSQL + Redis + Nginx</li>
<li><strong>Monitoring:</strong> Comprehensive logging and metrics</li>
</ul>
<p><strong>Технологии:</strong> Python, JavaScript, TypeScript, FastAPI, React, PostgreSQL, Redis, Celery, Docker, Nginx</p>
<p>&nbsp;</p><p>The post <a href="https://shknv.ru/397-2/">Кейс: Разработка системы автоматического мониторинга цен конкурентов</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PharmaChecker-помощник в мире лекарств</title>
		<link>https://shknv.ru/pharmachecker-pomoshhnik-v-mire-lekarstv/</link>
		
		<dc:creator><![CDATA[Evgeniy Shikunov]]></dc:creator>
		<pubDate>Sun, 13 Jul 2025 14:25:32 +0000</pubDate>
				<category><![CDATA[portfolio]]></category>
		<category><![CDATA[PharmaChecker]]></category>
		<category><![CDATA[аптека]]></category>
		<category><![CDATA[здоровье]]></category>
		<category><![CDATA[лекарства]]></category>
		<category><![CDATA[обзор]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=375</guid>

					<description><![CDATA[<p>PharmaChecker — ваш помощник в мире лекарств В современном мире забота о здоровье становится всё более важной. Мы создали PharmaChecker — онлайн-сервис, который помогает людям и врачам быстро находить информацию о лекарствах, проверять их совместимость и получать персональные рекомендации. Скриншот главной страницы сервиса: Для кого этот сервис? Для пациентов — чтобы узнать больше о назначенных [&#8230;]</p>
<p>The post <a href="https://shknv.ru/pharmachecker-pomoshhnik-v-mire-lekarstv/">PharmaChecker-помощник в мире лекарств</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<article>
<h1>PharmaChecker — ваш помощник в мире лекарств</h1>
<p>В современном мире забота о здоровье становится всё более важной. Мы создали<br />
<strong>PharmaChecker</strong> — онлайн-сервис, который помогает людям и врачам быстро находить информацию о лекарствах, проверять их совместимость и<br />
получать персональные рекомендации.</p>
<p><!-- Вставьте скриншот главной страницы --></p>
<p><em>Скриншот главной страницы сервиса:</em></p>
<h1><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-379" src="https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-15.26.25@2x-scaled.png" alt="" width="2560" height="1791" srcset="https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-15.26.25@2x-scaled.png 2560w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-15.26.25@2x-300x210.png 300w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-15.26.25@2x-1024x716.png 1024w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-15.26.25@2x-768x537.png 768w" sizes="auto, (max-width: 2560px) 100vw, 2560px" /></h1>
<h2>Для кого этот сервис?</h2>
<ul>
<li><strong>Для пациентов</strong> — чтобы узнать больше о назначенных<br />
препаратах, проверить их совместимость и избежать нежелательных<br />
последствий.</li>
<li><strong>Для врачей</strong> — чтобы быстро анализировать схемы лечения и<br />
подбирать безопасные комбинации лекарств.</li>
<li><strong>Для родственников</strong> — чтобы заботиться о близких, особенно<br />
если они принимают несколько препаратов одновременно.</li>
</ul>
<h2>Что умеет PharmaChecker?</h2>
<ol>
<li><strong>Поиск лекарств</strong> — просто введите название препарата и<br />
получите подробную информацию о нём.</li>
<li><strong>Проверка совместимости</strong> — сервис анализирует, можно ли<br />
принимать выбранные лекарства вместе.</li>
<li><strong>Персональные профили</strong> — можно создать профиль пациента,<br />
чтобы получать рекомендации с учётом возраста, заболеваний и других<br />
особенностей.</li>
<li><strong>История анализов</strong> — все ваши проверки сохраняются, чтобы<br />
вы могли к ним вернуться в любой момент.</li>
</ol>
<p><!-- Вставьте скриншот поиска и анализа --></p>
<p><em>Скриншот поиска и анализа лекарств:</em></p>
<h2><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-380" src="https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.17.29@2x.png" alt="" width="2016" height="1540" srcset="https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.17.29@2x.png 2016w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.17.29@2x-300x229.png 300w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.17.29@2x-1024x782.png 1024w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.17.29@2x-768x587.png 768w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.17.29@2x-1536x1173.png 1536w" sizes="auto, (max-width: 2016px) 100vw, 2016px" /></h2>
<h2>Почему это важно?</h2>
<p>Многие люди принимают несколько лекарств одновременно, не подозревая о возможных взаимодействиях между ними.<br />
<strong>PharmaChecker</strong> помогает избежать ошибок, повысить безопасность лечения и сделать заботу о здоровье проще и понятнее.</p>
<h2>Как это работает?</h2>
<p>Сервис прост в использовании: нужно зарегистрироваться, чтобы начать поиск.<br />
Достаточно ввести название лекарства или добавить препараты в анализ — и вы сразу получите результат. Для врачей и постоянных пользователей есть расширенные возможности: создание профилей, сохранение истории, персональные рекомендации.</p>
<p><!-- Вставьте скриншот профиля пациента --></p>
<p><em>Скриншот профиля пациента:</em></p>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-381" src="https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.22.15@2x-783x1024.png" alt="" width="783" height="1024" srcset="https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.22.15@2x-783x1024.png 783w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.22.15@2x-229x300.png 229w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.22.15@2x-768x1005.png 768w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.22.15@2x-1174x1536.png 1174w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.22.15@2x-1565x2048.png 1565w, https://shknv.ru/wp-content/uploads/2025/07/CleanShot-2025-07-13-at-17.22.15@2x.png 1588w" sizes="auto, (max-width: 783px) 100vw, 783px" /></p>
<h2>Безопасность и конфиденциальность</h2>
<p>Мы не сохраняем личные данные без вашего согласия. Вся информация защищена, а история анализов доступна только вам.</p>
<p>&nbsp;</p>
</article><p>The post <a href="https://shknv.ru/pharmachecker-pomoshhnik-v-mire-lekarstv/">PharmaChecker-помощник в мире лекарств</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Персональный веб сервер</title>
		<link>https://shknv.ru/personalnyj-veb-server/</link>
		
		<dc:creator><![CDATA[Evgeniy Shikunov]]></dc:creator>
		<pubDate>Wed, 25 Jun 2025 14:37:52 +0000</pubDate>
				<category><![CDATA[portfolio]]></category>
		<category><![CDATA[Автоматизация]]></category>
		<category><![CDATA[Без рубрики]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=340</guid>

					<description><![CDATA[<p>Как создать персональный сервер разработки: полный стек инструментов для современного разработчика Представьте, что у вас есть собственный сервер, доступный 24/7 из любой точки мира, с полным набором инструментов для разработки, тестирования и деплоя проектов. Звучит как мечта? На самом деле, это вполне реальная задача, которую можно решить за несколько часов. 🎯 Зачем нужен персональный dev-сервер? [&#8230;]</p>
<p>The post <a href="https://shknv.ru/personalnyj-veb-server/">Персональный веб сервер</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<h1>Как создать персональный сервер разработки: полный стек инструментов для<br />
современного разработчика</h1>
<p>Представьте, что у вас есть собственный сервер, доступный 24/7 из любой точки<br />
мира, с полным набором инструментов для разработки, тестирования и деплоя<br />
проектов. Звучит как мечта? На самом деле, это вполне реальная задача, которую<br />
можно решить за несколько часов.</p>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Зачем нужен персональный dev-сервер?</h2>
<p>В современном мире разработки мы часто сталкиваемся с ограничениями:</p>
<ul>
<li><strong>Привязка к рабочему компьютеру</strong> &#8212; код доступен только с<br />
одного устройства</li>
<li><strong>Сложности командной работы</strong> &#8212; как поделиться средой<br />
разработки с коллегами?</li>
<li><strong>Ограниченные ресурсы локальной машины</strong> &#8212; особенно актуально<br />
для ресурсоемких проектов</li>
<li><strong>Отсутствие единой среды</strong> &#8212; разные окружения на разных<br />
устройствах</li>
</ul>
<p>Персональный сервер разработки решает все эти проблемы одним махом.</p>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3d7.png" alt="🏗" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Архитектура решения</h2>
<p>Основой нашего сервера стал <strong>Docker</strong> &#8212; он обеспечивает изоляцию<br />
сервисов и упрощает развертывание. Все компоненты работают в контейнерах и<br />
управляются через единую панель.</p>
<p><!-- МЕСТО ДЛЯ СКРИНШОТА: Центральный dashboard --></p>
<figure style="margin: 30px 0; text-align: center;"><figcaption style="margin-top: 15px; color: #657786; font-style: italic; font-size: 14px;"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-345" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-13.40.06.png" alt="" width="1250" height="1555" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-13.40.06.png 1250w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-13.40.06-241x300.png 241w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-13.40.06-823x1024.png 823w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-13.40.06-768x955.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-13.40.06-1235x1536.png 1235w" sizes="auto, (max-width: 1250px) 100vw, 1250px" /><br />
Центральный dashboard объединяет все инструменты разработки в одном месте</figcaption></figure>
<h3>Основные компоненты:</h3>
<p><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f5a5.png" alt="🖥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Среда разработки</strong></p>
<ul>
<li><strong>Code Server</strong> &#8212; полноценный VS Code в браузере</li>
<li><strong>Git сервер</strong> &#8212; приватные репозитории для ваших проектов</li>
<li><strong>CI/CD система</strong> &#8212; автоматическое тестирование и деплой</li>
</ul>
<p><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f5c4.png" alt="🗄" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Управление данными</strong></p>
<ul>
<li><strong>Веб-интерфейсы для баз данных</strong> &#8212; управление PostgreSQL,<br />
MySQL и другими</li>
<li><strong>Файловый менеджер</strong> &#8212; полный доступ к файловой системе через<br />
браузер</li>
<li><strong>S3-совместимое хранилище</strong> &#8212; для статических файлов и бэкапов</li>
</ul>
<p><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4ca.png" alt="📊" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Мониторинг и управление</strong></p>
<ul>
<li><strong>Система мониторинга</strong> &#8212; отслеживание доступности всех<br />
сервисов</li>
<li><strong>Docker управление</strong> &#8212; веб-интерфейс для контейнеров</li>
<li><strong>Прокси-менеджер</strong> &#8212; автоматическое управление SSL<br />
сертификатами</li>
</ul>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Ключевые возможности</h2>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bb.png" alt="💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Разработка из любой точки мира</h3>
<p>Забудьте про &#171;работает только на моей машине&#187;. Ваша среда разработки доступна<br />
из любого браузера &#8212; с компьютера, планшета и даже смартфона. Полноценный VS<br />
Code с расширениями, терминалом и Git интеграцией.</p>
<p><!-- МЕСТО ДЛЯ СКРИНШОТА: VS Code в браузере --></p>
<figure style="margin: 30px 0; text-align: center;"><figcaption style="margin-top: 15px; color: #657786; font-style: italic; font-size: 14px;"><img loading="lazy" decoding="async" class="aligncenter wp-image-348 size-large" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.46.00-1024x715.png" alt="" width="1024" height="715" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.46.00-1024x715.png 1024w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.46.00-300x209.png 300w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.46.00-768x536.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.46.00-1536x1072.png 1536w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.46.00-2048x1430.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><br />
Полноценный VS Code работает прямо в браузере с полной поддержкой расширений</figcaption></figure>
<blockquote><p><em>Пример:</em> Вы работаете дома на MacBook, в офисе на Windows PC, а в<br />
поездке используете iPad. Везде одинаковая среда разработки с вашими<br />
настройками, расширениями и проектами.</p></blockquote>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f504.png" alt="🔄" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Автоматизация рабочих процессов</h3>
<p>Настройте автоматическое тестирование и деплой проектов. Git push →<br />
автоматические тесты → деплой на продакшн. Всё работает без вашего участия.</p>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Централизованное хранилище</h3>
<p>Все файлы проектов в одном месте. S3-совместимое хранилище для статики, база<br />
данных для проектов, автоматические бэкапы.</p>
<p><!-- МЕСТО ДЛЯ СКРИНШОТОВ: Файловый менеджер и Adminer --></p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 25px; margin: 30px 0;">
<figure style="text-align: center;"><figcaption style="margin-top: 10px; color: #657786; font-style: italic; font-size: 12px;"><img loading="lazy" decoding="async" class="aligncenter wp-image-351 size-large" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.53.07-1024x435.png" alt="" width="1024" height="435" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.53.07-1024x435.png 1024w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.53.07-300x127.png 300w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.53.07-768x326.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.53.07-1536x652.png 1536w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.53.07-2048x869.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><br />
Полный доступ к файловой системе</figcaption></figure>
<figure style="text-align: center;"><figcaption style="margin-top: 10px; color: #657786; font-style: italic; font-size: 12px;"><img loading="lazy" decoding="async" class="aligncenter wp-image-352 size-full" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.56.23.png" alt="" width="906" height="535" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.56.23.png 906w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.56.23-300x177.png 300w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.56.23-768x454.png 768w" sizes="auto, (max-width: 906px) 100vw, 906px" /><br />
Веб-интерфейс для баз данных</figcaption></figure>
</div>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f310.png" alt="🌐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Простое развертывание проектов</h3>
<p>Каждый проект может получить собственный домен и SSL сертификат в пару кликов.<br />
Прокси автоматически перенаправляет трафик и обновляет сертификаты.</p>
<p><!-- МЕСТО ДЛЯ СКРИНШОТА: MinIO Storage --></p>
<figure style="margin: 30px 0; text-align: center;"><figcaption style="margin-top: 15px; color: #657786; font-style: italic; font-size: 14px;"></figcaption></figure>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f527.png" alt="🔧" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Технические детали</h2>
<h3>Выбор железа</h3>
<p>Для такого сервера подойдет VPS от любого провайдера:</p>
<ul>
<li><strong>RAM:</strong> 4GB минимум (рекомендуется 8GB)</li>
<li><strong>Диск:</strong> 50GB SSD</li>
<li><strong>CPU:</strong> 2+ ядра</li>
<li><strong>Сеть:</strong> неограниченный трафик</li>
</ul>
<div style="background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); padding: 20px; border-left: 5px solid #007cba; margin: 25px 0; border-radius: 10px;">
<p style="margin: 0;"><strong><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Совет:</strong> Начните с минимальной конфигурации. Современные<br />
VPS легко масштабируются, и вы всегда сможете добавить ресурсов при<br />
необходимости.</p>
</div>
<h3>Операционная система</h3>
<p>Ubuntu 22.04 LTS &#8212; стабильная, с долгосрочной поддержкой и отличной<br />
совместимостью с Docker.</p>
<h3>Сетевая архитектура</h3>
<p>Все сервисы работают во внутренней Docker сети. Наружу смотрит только Nginx<br />
Proxy Manager, который:</p>
<ul>
<li>Автоматически получает SSL сертификаты от Let&#8217;s Encrypt</li>
<li>Распределяет трафик между сервисами</li>
<li>Обеспечивает единую точку входа</li>
</ul>
<p><!-- МЕСТО ДЛЯ СКРИНШОТА: Portainer --></p>
<figure style="margin: 30px 0; text-align: center;"><figcaption style="margin-top: 15px; color: #657786; font-style: italic; font-size: 14px;"><img loading="lazy" decoding="async" class="aligncenter wp-image-353 size-full" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.57.39.png" alt="" width="2145" height="844" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.57.39.png 2145w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.57.39-300x118.png 300w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.57.39-1024x403.png 1024w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.57.39-768x302.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.57.39-1536x604.png 1536w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-25-at-14.57.39-2048x806.png 2048w" sizes="auto, (max-width: 2145px) 100vw, 2145px" /><br />
Portainer обеспечивает полный контроль над Docker инфраструктурой</figcaption></figure>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e1.png" alt="🛡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Безопасность</h2>
<p>Безопасность &#8212; критически важный аспект такой системы:</p>
<h3>Изоляция сервисов</h3>
<p>Каждый компонент работает в отдельном Docker контейнере с минимальными<br />
правами.</p>
<h3>Сетевая безопасность</h3>
<ul>
<li>Файрвол открывает только необходимые порты (22, 80, 443)</li>
<li>Все сервисы доступны только через HTTPS</li>
<li>Внутренняя связь между контейнерами изолирована</li>
</ul>
<h3>Аутентификация</h3>
<ul>
<li>Многоуровневая система авторизации</li>
<li>Защищенная центральная панель управления</li>
<li>Индивидуальные пароли для каждого сервиса</li>
</ul>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4bc.png" alt="💼" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Практические сценарии использования</h2>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 25px; margin: 30px 0;">
<div style="background: linear-gradient(135deg, #fff 0%, #f8f9fa 100%); border: 2px solid #e9ecef; padding: 25px; border-radius: 15px; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);">
<h4 style="color: #2c3e50; margin-bottom: 15px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Фрилансер/Solo разработчик</h4>
<ul style="margin: 0; padding-left: 20px;">
<li>Работа из дома, офиса, кафе &#8212; везде одинаковая среда</li>
<li>Автоматические бэкапы защищают от потери кода</li>
<li>Легко показать проект заказчику &#8212; просто дать ссылку</li>
</ul>
</div>
<div style="background: linear-gradient(135deg, #fff 0%, #f8f9fa 100%); border: 2px solid #e9ecef; padding: 25px; border-radius: 15px; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);">
<h4 style="color: #2c3e50; margin-bottom: 15px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f465.png" alt="👥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Небольшая команда</h4>
<ul style="margin: 0; padding-left: 20px;">
<li>Общая среда разработки для всей команды</li>
<li>Централизованный Git сервер для приватных проектов</li>
<li>Совместное использование баз данных и файлов</li>
</ul>
</div>
<div style="background: linear-gradient(135deg, #fff 0%, #f8f9fa 100%); border: 2px solid #e9ecef; padding: 25px; border-radius: 15px; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);">
<h4 style="color: #2c3e50; margin-bottom: 15px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f393.png" alt="🎓" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Обучение и эксперименты</h4>
<ul style="margin: 0; padding-left: 20px;">
<li>Безопасная песочница для изучения новых технологий</li>
<li>Можно сломать что угодно &#8212; всё восстанавливается из контейнеров</li>
<li>История всех экспериментов в Git</li>
</ul>
</div>
<div style="background: linear-gradient(135deg, #fff 0%, #f8f9fa 100%); border: 2px solid #e9ecef; padding: 25px; border-radius: 15px; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);">
<h4 style="color: #2c3e50; margin-bottom: 15px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9ea.png" alt="🧪" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Staging окружение</h4>
<ul style="margin: 0; padding-left: 20px;">
<li>Точная копия продакшн среды для тестирования</li>
<li>Автоматический деплой из Git веток</li>
<li>Мониторинг производительности и ошибок</li>
</ul>
</div>
</div>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4b0.png" alt="💰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Экономическая выгода</h2>
<p>Сравнение с популярными облачными альтернативами:</p>
<table style="width: 100%; border-collapse: collapse; margin: 25px 0; background: #fff; border-radius: 10px; overflow: hidden; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);">
<thead>
<tr style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white;">
<th style="padding: 18px; text-align: left; font-weight: 600;">Решение</th>
<th style="padding: 18px; text-align: left; font-weight: 600;">Стоимость/месяц</th>
<th style="padding: 18px; text-align: left; font-weight: 600;">Ограничения</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom: 1px solid #e9ecef;">
<td style="padding: 15px;">GitHub Codespaces</td>
<td style="padding: 15px; color: #e74c3c; font-weight: 600;">~$130 при полной загрузке</td>
<td style="padding: 15px;">Лимит часов, нет полного контроля</td>
</tr>
<tr style="border-bottom: 1px solid #e9ecef;">
<td style="padding: 15px;">AWS Cloud9</td>
<td style="padding: 15px; color: #e74c3c; font-weight: 600;">$50-100</td>
<td style="padding: 15px;">Привязка к AWS, дорогой трафик</td>
</tr>
<tr style="background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%);">
<td style="padding: 15px; font-weight: 600;">Персональный VPS</td>
<td style="padding: 15px; color: #27ae60; font-weight: bold; font-size: 18px;">$20-40</td>
<td style="padding: 15px; font-weight: 600;">Неограниченное использование</td>
</tr>
</tbody>
</table>
<p>При этом персональный сервер дает полный контроль и неограниченное время<br />
использования.</p>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4c8.png" alt="📈" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Масштабирование и автоматизация</h2>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 25px; margin: 30px 0;">
<div>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4ca.png" alt="📊" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Вертикальное масштабирование</h3>
<ul>
<li>Увеличение RAM/CPU при росте нагрузки</li>
<li>Добавление дискового пространства</li>
<li>Оптимизация производительности</li>
</ul>
</div>
<div>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f310.png" alt="🌐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Горизонтальное масштабирование</h3>
<ul>
<li>Несколько серверов для разных проектов</li>
<li>Кластеризация Docker Swarm</li>
<li>CDN для статических файлов</li>
</ul>
</div>
</div>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4ca.png" alt="📊" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Мониторинг и поддержка</h2>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f441.png" alt="👁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Система мониторинга</h3>
<ul>
<li>24/7 отслеживание доступности всех сервисов</li>
<li>Метрики производительности</li>
<li>Автоматические уведомления о проблемах</li>
</ul>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4dd.png" alt="📝" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Логирование</h3>
<ul>
<li>Централизованный сбор логов</li>
<li>Поиск и анализ ошибок</li>
<li>Ротация логов для экономии места</li>
</ul>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f389.png" alt="🎉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Заключение</h2>
<p>Персональный сервер разработки &#8212; это не просто модная игрушка, а реальный<br />
инструмент повышения продуктивности. Он освобождает от привязки к конкретному<br />
устройству, автоматизирует рутинные задачи и создает единую среду для всех<br />
проектов.</p>
<p>Современные технологии контейнеризации делают развертывание такой системы<br />
простым и доступным. За несколько часов работы вы получаете полноценную<br />
платформу разработки, которая будет служить годами.</p>
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 20px; margin: 40px 0; text-align: center;">
<h3 style="color: white; margin-top: 0; font-size: 24px;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Ключевые преимущества</h3>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-top: 25px;">
<div><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f30d.png" alt="🌍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Доступность из любой точки мира</div>
<div><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f504.png" alt="🔄" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Автоматизация CI/CD процессов</div>
<div><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e1.png" alt="🛡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Высокий уровень безопасности</div>
<div><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4b0.png" alt="💰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Экономическая эффективность</div>
<div><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Простота масштабирования</div>
</div>
</div>
<p style="font-size: 18px; text-align: center; margin: 30px 0;">Если вы серьезно относитесь к разработке и хотите работать как настоящий<br />
профессионал &#8212; персональный сервер разработки должен стать частью вашего<br />
арсенала.</p>
<hr style="border: none; border-top: 2px solid #e9ecef; margin: 40px 0;" />
<p style="color: #657786; font-style: italic; text-align: center;"><em>Эта статья описывает общие принципы создания персонального сервера<br />
разработки. Конкретная реализация может отличаться в зависимости от ваших<br />
потребностей и предпочтений.&lt;/em &gt; </em></p><p>The post <a href="https://shknv.ru/personalnyj-veb-server/">Персональный веб сервер</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Проект: Интерактивная карта концертного тура &#171;Stigmata&#187;</title>
		<link>https://shknv.ru/proekt-interaktivnaja-karta-koncertn/</link>
		
		<dc:creator><![CDATA[Evgeniy Shikunov]]></dc:creator>
		<pubDate>Sun, 22 Jun 2025 09:27:48 +0000</pubDate>
				<category><![CDATA[portfolio]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=328</guid>

					<description><![CDATA[<p>Проект: Интерактивная карта концертного тура &#171;Stigmata&#187; 1. Краткий обзор Этот проект представляет собой полнофункциональное веб-приложение, созданное для визуализации концертного тура музыкальной группы &#171;Stigmata&#187;. Вместо стандартного списка городов и дат, приложение предлагает интерактивную карту, на которой отмечены все предстоящие концерты. Маршрут тура наглядно соединён анимированными линиями, что позволяет фанатам легко отслеживать перемещения группы. Цель проекта: Создать [&#8230;]</p>
<p>The post <a href="https://shknv.ru/proekt-interaktivnaja-karta-koncertn/">Проект: Интерактивная карта концертного тура «Stigmata»</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<h1>Проект: Интерактивная карта концертного тура &#171;Stigmata&#187;</h1>
<h2>1. Краткий обзор</h2>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-331" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.15.29@2x-1024x806.png" alt="Скриншот карты тура" width="1024" height="806" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.15.29@2x-1024x806.png 1024w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.15.29@2x-300x236.png 300w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.15.29@2x-768x604.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.15.29@2x-1536x1208.png 1536w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.15.29@2x-2048x1611.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>Этот проект представляет собой полнофункциональное веб-приложение, созданное для визуализации концертного тура музыкальной группы &#171;Stigmata&#187;. Вместо стандартного списка городов и дат, приложение предлагает интерактивную карту, на которой отмечены все предстоящие концерты. Маршрут тура наглядно соединён анимированными линиями, что позволяет фанатам легко отслеживать перемещения группы.</p>
<p><strong>Цель проекта:</strong> Создать удобный, наглядный и привлекательный инструмент для информирования поклонников о концертном графике.</p>
<h2>2. Архитектура системы</h2>
<p>Проект имеет многокомпонентную архитектуру, включающую этап подготовки данных, бэкенд-сервер для обработки логики и фронтенд для взаимодействия с пользователем.</p>
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-330" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.14.35@2x-1024x276.png" alt="Диаграмма архитектуры проекта" width="1024" height="276" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.14.35@2x-1024x276.png 1024w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.14.35@2x-300x81.png 300w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.14.35@2x-768x207.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.14.35@2x-1536x415.png 1536w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.14.35@2x.png 1926w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Диаграмма архитектуры проекта</figcaption></figure>
<ul>
<li><strong>Подготовка данных:</strong> Исходная информация о концертах обрабатывается Node.js-скриптом, который извлекает нужные поля и сохраняет их в структурированном виде в базу данных MySQL.</li>
<li><strong>Бэкенд:</strong> Сервер на Flask (Python) выступает в роли API. Он запрашивает данные о предстоящих концертах из БД, обогащает их гео-координатами (используя внешний сервис и собственный кэш) и отдает фронтенду в формате JSON.</li>
<li><strong>Фронтенд:</strong> Клиентская часть, написанная на чистом JavaScript, получает данные от бэкенда и с помощью библиотеки Leaflet.js отрисовывает интерактивную карту с маркерами, всплывающими окнами и анимированным маршрутом.</li>
</ul>
<h2>3. Стек технологий</h2>
<ul>
<li><strong>Бэкенд:</strong> Python, Flask</li>
<li><strong>Фронтенд:</strong> HTML5, CSS3, JavaScript (ES6+), Leaflet.js</li>
<li><strong>База данных:</strong> MySQL</li>
<li><strong>Геокодинг:</strong> Geopy (Nominatim/OpenStreetMap)</li>
<li><strong>Парсинг данных:</strong> Node.js</li>
<li><strong>Оркестрация:</strong> Docker (docker-compose.yaml)</li>
</ul>
<h2>4. Ключевые функции и решения</h2>
<h3>Интерактивная карта тура</h3>
<p>Основная &#171;фишка&#187; проекта. Использование Leaflet.js позволило создать быструю и функциональную карту. При клике на маркер города появляется всплывающее окно с датой, местом проведения и прямой ссылкой на покупку билета.</p>
<h3>Анимированный маршрут</h3>
<p>Чтобы визуально связать города в туре, между последовательными концертами рисуются линии. Эти линии анимированы, что создаёт эффект &#171;движения&#187; и наглядно показывает последовательность выступлений.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-332" src="https://shknv.ru/wp-content/uploads/2025/06/Area.gif" alt="Анимация маршрута" width="1372" height="720" /></p>
<h3>Эффективный геокодинг с кэшированием</h3>
<p>Для отображения городов на карте нужны их географические координаты. Чтобы не перегружать внешние API (Nominatim) и ускорить загрузку, было реализовано кэширование:</p>
<ol>
<li>Приложение сперва ищет координаты в собственной таблице <code>city_coordinates</code> в БД.</li>
<li>Если для города координат в кэше нет, отправляется запрос к Geopy.</li>
<li>Полученные координаты сохраняются в БД для будущих запросов.</li>
</ol>
<p>Это значительно сокращает время ответа сервера и снижает зависимость от сторонних сервисов.</p>
<h3>Разделение логики: от парсинга до отображения</h3>
<p>Наличие отдельного скрипта (<code>processPattern.js</code>) для парсинга данных показывает продуманный подход. Вместо того чтобы &#171;на лету&#187; обрабатывать сложные данные при каждом запросе, информация заранее подготавливается и складывается в БД. Это делает основное приложение более быстрым, надёжным и менее зависимым от формата исходных данных.</p>
<h2>5. Потенциальные улучшения (Точки роста)</h2>
<ul>
<li><strong>Автоматизация ETL:</strong> Процесс извлечения, преобразования и загрузки данных (ETL), который сейчас выполняется вручную с помощью скрипта, можно автоматизировать. Например, создать периодическую задачу (cron job), которая будет сама проверять обновления и добавлять новые концерты в БД.</li>
</ul>
<h2>6. Заключение</h2>
<p>Проект &#171;Карта концертов Stigmata&#187; является отличным примером полнофункционального веб-приложения, решающего конкретную задачу. Он демонстрирует навыки в бэкенд- и фронтенд-разработке, работе с базами данных, использовании внешних API и продумывании архитектуры. Особого внимания заслуживают решения по оптимизации (кэширование) и наглядной визуализации данных.</p><p>The post <a href="https://shknv.ru/proekt-interaktivnaja-karta-koncertn/">Проект: Интерактивная карта концертного тура «Stigmata»</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Портфолио: Система учёта визитов &#171;Visit&#187;</title>
		<link>https://shknv.ru/320-2/</link>
		
		<dc:creator><![CDATA[Evgeniy Shikunov]]></dc:creator>
		<pubDate>Sun, 22 Jun 2025 09:08:40 +0000</pubDate>
				<category><![CDATA[portfolio]]></category>
		<category><![CDATA[code]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=320</guid>

					<description><![CDATA[<p>Портфолио: West Visit — Как мы сократили время на документирование визитов с 15 минут до 2 1. Откуда взялась задача Представьте медицинского представителя фармацевтической компании. Его день выглядит так: 6-8 визитов к врачам, поездки между клиниками, переговоры, презентации препаратов. А вечером — рутина: открыть ноутбук и потратить полтора часа на то, чтобы задокументировать все встречи [&#8230;]</p>
<p>The post <a href="https://shknv.ru/320-2/">Портфолио: Система учёта визитов «Visit»</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<div style="width: 100%; max-width: 100%; padding: 0; box-sizing: border-box;">
<p><span style="font-size: 2.25em; font-weight: 800;">Портфолио: West Visit — Как мы сократили время на документирование визитов с 15 минут до 2</span></p>
</div>
<h2><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-323" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.01.07@2x-1024x638.png" alt="" width="1024" height="638" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.01.07@2x-1024x638.png 1024w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.01.07@2x-300x187.png 300w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.01.07@2x-768x478.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.01.07@2x-1536x956.png 1536w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.01.07@2x-2048x1275.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></h2>
<h2>1. Откуда взялась задача</h2>
<p>Представьте медицинского представителя фармацевтической компании. Его день выглядит так: 6-8 визитов к врачам, поездки между клиниками, переговоры, презентации препаратов. А вечером — рутина: открыть ноутбук и потратить полтора часа на то, чтобы задокументировать все встречи в корпоративной CRM.</p>
<p><strong>Проблемы, с которыми они сталкивались ежедневно:</strong></p>
<ul>
<li>10-15 минут на заполнение одного визита в Bitrix24</li>
<li>Сначала записи в блокнот, потом в Excel, потом в CRM — тройное дублирование</li>
<li>«Что мы обсуждали в прошлый раз с этим врачом?» — информация теряется</li>
<li>Руководитель не видит, что происходит в полях в реальном времени</li>
<li>Нестабильный интернет в регионах — визит не сохранился, данные потеряны</li>
</ul>
<p>Именно эти боли легли в основу <strong>West Visit</strong> — Progressive Web Application, которое работает на любом устройстве, в том числе оффлайн, и превращает документирование визита из рутины в дело пары минут.</p>
<h2>2. Что умеет West Visit</h2>
<h3>Кейс №1: Утро медпредставителя</h3>
<p>Анна, медицинский представитель, открывает West Visit на планшете за завтраком. Сегодня у неё 7 визитов. Система автоматически подгрузила все запланированные встречи из Bitrix24:</p>
<blockquote><p><strong>9:00</strong> — Клиника «Здоровье», ул. Ленина, 10<br />
Врач: Иванов П.С., кардиолог<br />
<em>История: в прошлый раз обсуждали препарат X, обещали подумать</em></p></blockquote>
<p>Ещё в машине Анна открывает карточку клиники и видит:</p>
<ul>
<li>Полную информацию о клинике (адрес, телефоны, контакты ЛПР)</li>
<li>Историю всех предыдущих визитов к этой клинике</li>
<li>Список врачей, которые там работают</li>
<li>Заметки коллег из прошлых встреч</li>
</ul>
<p><strong>Результат:</strong> Анна приходит на встречу подготовленной, помнит контекст предыдущего разговора, знает, о чём договаривались.</p>
<h3>Кейс №2: Во время визита</h3>
<p>Встреча с врачом заняла 20 минут. Анна выходит из кабинета и прямо в коридоре, пока всё свежо в памяти, открывает карточку визита на телефоне:</p>
<ol>
<li>Меняет статус с «Запланирован» на «Состоялся» — визит становится зелёным</li>
<li>Выбирает тип визита: «Презентация препарата»</li>
<li>Отмечает, какие препараты обсуждали (список подгружается из Bitrix24)</li>
<li>Добавляет комментарий: «Врач заинтересован, попросил прислать клинические исследования»</li>
<li>Система автоматически сохраняет данные</li>
</ol>
<p><strong>Время затрачено: 2 минуты.</strong></p>
<p>Все изменения мгновенно отправляются в Bitrix24. Даже если интернет пропал — не страшно, данные сохранятся локально и синхронизируются, как только связь появится. Визит помечен значком «ожидает синхронизации».</p>
<h3>Кейс №3: Руководитель следит за работой команды</h3>
<p>Олег, региональный менеджер, сидит в офисе и в реальном времени видит:</p>
<ul>
<li>Сколько визитов запланировано на сегодня у каждого медпредставителя</li>
<li>Сколько уже состоялось, сколько проваленных</li>
<li>Какие клиники посещаются регулярно, а какие «простаивают»</li>
<li>Детали каждого визита: о чём говорили, какие препараты презентовали</li>
</ul>
<p>Если видит, что у кого-то из команды все визиты показывают статус «Провалился» — может оперативно позвонить и помочь.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-324" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.02.55@2x-1024x921.png" alt="" width="1024" height="921" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.02.55@2x-1024x921.png 1024w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.02.55@2x-300x270.png 300w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.02.55@2x-768x691.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.02.55@2x-1536x1382.png 1536w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-12.02.55@2x.png 1704w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<h3>Кейс №4: Поиск клиники на ходу</h3>
<p>Сергей едет по городу и решает заехать в новую клинику, мимо которой проезжает. Он знает только название: «Медцентр Плюс». Открывает West Visit, вбивает в поиск — система мгновенно находит клинику в базе Bitrix24:</p>
<ul>
<li>Полное название, ИНН, адрес</li>
<li>Телефоны и контакты ЛПР</li>
<li>История визитов коллег (если кто-то уже был)</li>
<li>Какие врачи там работают</li>
</ul>
<p>Прямо из карточки клиники Сергей создаёт новый визит — буквально в три клика. Система автоматически подставляет данные клиники, остаётся только выбрать дату и добавить комментарий.</p>
<h2>3. Самое крутое — динамические поля</h2>
<p>Каждая фармацевтическая компания работает по-своему. У одних в Bitrix24 есть поле «Количество выданных образцов», у других — «Уровень лояльности врача», у третьих — «Конкуренты в регионе».</p>
<p><strong>Обычная проблема:</strong> чтобы добавить новое поле, нужно переделывать код приложения, тестировать, выкатывать обновление.</p>
<p><strong>Наше решение:</strong> система маппинга полей. Администратор заходит в административную панель West Visit и настраивает соответствие:</p>
<blockquote><p>Поле в Bitrix24: <code>UF_CRM_1732026990932</code> (тип: список)<br />
Название в приложении: <strong>«Тип визита»</strong><br />
Обязательное: Да<br />
Показывать в карточке: Да</p></blockquote>
<p>Всё! Теперь это поле автоматически появляется в формах создания и редактирования визитов. Если в Bitrix24 добавили новое значение списка — администратор нажимает одну кнопку «Обновить из Bitrix24», и список актуализируется.</p>
<p><strong>Результат:</strong> компания может добавлять любые поля в CRM, и West Visit адаптируется автоматически, без разработки.</p>
<h2>4. Технологии под капотом</h2>
<p>Чтобы всё это работало быстро и надёжно, мы выбрали современный стек:</p>
<h3>Backend</h3>
<ul>
<li><strong>FastAPI (Python 3.11)</strong> — быстрый и современный фреймворк для создания API. Работает асинхронно, поэтому обрабатывает множество запросов одновременно без задержек</li>
<li><strong>PostgreSQL 14</strong> — надёжная база данных с поддержкой JSONB. Это позволяет хранить динамические поля из Bitrix24 без изменения структуры базы</li>
<li><strong>SQLAlchemy 2.0</strong> — ORM для работы с базой данных. Упрощает написание запросов и защищает от SQL-инъекций</li>
</ul>
<h3>Frontend</h3>
<ul>
<li><strong>React 18 + TypeScript</strong> — интерактивный интерфейс с полной типизацией. Меньше ошибок, удобнее разработка</li>
<li><strong>Material-UI v5</strong> — готовые компоненты для интерфейса. Тёмная тема специально оптимизирована для работы на улице под солнцем</li>
<li><strong>React Query</strong> — умное кеширование данных. Приложение работает быстро, даже если интернет медленный</li>
</ul>
<h3>DevOps</h3>
<ul>
<li><strong>Docker</strong> — приложение упаковано в контейнеры. Легко развернуть на любом сервере</li>
<li><strong>Nginx</strong> — веб-сервер для раздачи статики и проксирования запросов</li>
</ul>
<h2>5. Архитектура: как всё устроено</h2>
<p>Система построена по классической схеме:</p>
<ol>
<li><strong>Пользователь</strong> открывает West Visit на телефоне/планшете/компьютере</li>
<li><strong>Frontend</strong> (React) отправляет запросы к API</li>
<li><strong>Backend</strong> (FastAPI) обрабатывает логику, общается с базой данных и Bitrix24</li>
<li><strong>PostgreSQL</strong> хранит все данные локально для быстрого доступа</li>
<li><strong>Bitrix24</strong> получает обновления через API и отправляет изменения обратно через вебхуки</li>
</ol>
<h3><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-322" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.59.49@2x-859x1024.png" alt="" width="859" height="1024" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.59.49@2x-859x1024.png 859w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.59.49@2x-252x300.png 252w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.59.49@2x-768x915.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.59.49@2x-1289x1536.png 1289w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.59.49@2x.png 1636w" sizes="auto, (max-width: 859px) 100vw, 859px" /></h3>
<h3>Двусторонняя синхронизация</h3>
<p>Это ключевая фишка системы:</p>
<ul>
<li><strong>Изменили визит в West Visit?</strong> Данные автоматически отправляются в Bitrix24</li>
<li><strong>Изменили визит в Bitrix24?</strong> Обновление приходит в West Visit через вебхук</li>
<li><strong>Создали новую компанию?</strong> Она появляется в приложении</li>
<li><strong>Добавили врача в Bitrix24?</strong> Он тут же доступен для связи с визитами</li>
</ul>
<p>Всё работает в обе стороны, данные всегда актуальные.</p>
<h2>6. Основные модели данных</h2>
<p>В основе системы — четыре ключевые сущности:</p>
<h3>User (Пользователь)</h3>
<p>Хранит данные о медпредставителях: email, пароль, роль (обычный пользователь или администратор), связь с пользователем в Bitrix24.</p>
<h3>Company (Компания/Клиника)</h3>
<p>Название, ИНН, адрес, телефоны, email, ID в Bitrix24 для синхронизации. Плюс динамические поля — всё, что настроено в CRM.</p>
<h3>Visit (Визит)</h3>
<p>Связан с пользователем и компанией. Содержит дату, статус (запланирован/состоялся/провалился), тип визита, комментарии, связь с врачами. Плюс динамические поля.</p>
<h3>Contact/Doctor (Контакты и врачи)</h3>
<p>ЛПР (лица, принимающие решения) и врачи. У каждого — имя, должность, телефоны (может быть несколько: рабочий, мобильный), email. Связь many-to-many с компаниями и визитами.</p>
<h3>FieldMapping (Маппинг полей)</h3>
<p>Самая важная таблица! Здесь хранятся настройки: какое поле из Bitrix24 (например, <code>UF_CRM_123</code>) соответствует какому полю в приложении, какой у него тип, обязательное ли оно, нужно ли показывать в карточках.</p>
<p>Благодаря этой таблице система <strong>гибко адаптируется</strong> к любым изменениям в CRM без переделки кода.</p>
<h2>7. Progressive Web App — работает везде</h2>
<p>West Visit — это PWA, что означает:</p>
<ul>
<li><strong>Установка на домашний экран</strong> — приложение выглядит и работает как нативное</li>
<li><strong>Работает оффлайн</strong> — данные кешируются, изменения сохраняются локально и синхронизируются при появлении интернета</li>
<li><strong>Адаптивный дизайн</strong> — одинаково удобно на телефоне, планшете и компьютере</li>
<li><strong>Быстрая загрузка</strong> — благодаря кешированию и оптимизации</li>
<li><strong>Тёмная тема</strong> — удобно работать на улице и не сажать зрение в тёмное время суток</li>
</ul>
<h2>8. Административная панель</h2>
<p>Администратор системы может:</p>
<ol>
<li><strong>Управлять пользователями</strong> — добавлять новых медпредставителей, блокировать учётные записи</li>
<li><strong>Настраивать маппинги полей</strong> — создавать соответствия между полями Bitrix24 и приложением</li>
<li><strong>Просматривать метаданные из Bitrix24</strong> — видеть все доступные поля и их типы</li>
<li><strong>Синхронизировать справочники</strong> — обновлять списки значений для выпадающих полей</li>
</ol>
<p>Это делает систему полностью самообслуживаемой: администратор компании может настроить всё под свои процессы без программиста.</p>
<h2>9. Что дальше: планы развития</h2>
<h3>Ближайшие улучшения (3-6 месяцев)</h3>
<h4>Календарь визитов</h4>
<p>Полноценный интерактивный календарь с разными видами: месяц, неделя, день. Drag-and-drop для быстрого переноса визитов. Цветовая индикация загруженности.</p>
<h4>Карточки компаний 2.0</h4>
<p>Вкладки для разделения информации: «Основное», «Контакты», «Врачи», «История визитов». Timeline всех взаимодействий в виде ленты. Интеграция с Яндекс.Картами — построение маршрута одной кнопкой.</p>
<h4>Push-уведомления</h4>
<p>Напоминания о предстоящих визитах за час/за день. Уведомления об изменениях в Bitrix24. Геолокационные уведомления: «Вы рядом с клиникой, у которой запланирован визит».</p>
<h3>Долгосрочные планы (6-12 месяцев)</h3>
<h4>Расширенный оффлайн-режим</h4>
<p>Service Worker для полноценной работы без интернета. Background Sync API — отправка данных в фоне, когда появится связь. Умное разрешение конфликтов: если визит изменили и в приложении, и в Bitrix24, система предложит выбрать версию.</p>
<h4>Геолокация и маршруты</h4>
<p>Построение оптимального маршрута на день с учётом пробок (Google Maps / Яндекс.Карты). Верификация визитов: система проверяет, что медпредставитель действительно был рядом с клиникой. GPS-трекинг для расчёта пробега и компенсации ГСМ.</p>
<h4>Аналитика для руководителей</h4>
<p>Дашборды с KPI: сколько визитов в день, процент успешных, конверсия в продажи. Тепловые карты активности по регионам. Прогнозирование на основе истории: когда пора снова посетить клинику.</p>
<h4>Интеграция с другими CRM</h4>
<p>Система спроектирована так, чтобы добавить адаптеры для AmoCRM, Salesforce, Microsoft Dynamics. Это откроет рынок за пределами пользователей Bitrix24.</p>
<h2>10. Результаты и достижения</h2>
<h3>Технические</h3>
<ul>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Полностью типобезопасная разработка (TypeScript + Python type hints)</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Современный async стек для высокой производительности</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Масштабируемая слоистая архитектура</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Продвинутая двусторонняя интеграция с Bitrix24</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Уникальная система динамических полей</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> PWA с offline-capable архитектурой</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Responsive UI для всех устройств</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Высокая безопасность (JWT, bcrypt, CORS, валидация)</li>
</ul>
<h3>Бизнес</h3>
<ul>
<li><strong>Сокращение времени на документирование с 10-15 до 2 минут</strong></li>
<li>Повышение прозрачности работы команды на 100%</li>
<li> Снижение ошибок синхронизации благодаря автоматизации</li>
<li>Готовность к масштабированию без изменения архитектуры</li>
<li>Ускорение адаптации новых сотрудников</li>
</ul>
<h2>11. Чем West Visit выделяется среди аналогов</h2>
<ol>
<li><strong>Гибкая система маппинга полей</strong> — не требует разработки при добавлении новых полей в CRM. Администратор всё настраивает сам через панель управления</li>
<li><strong>Offline-first подход</strong> — работает даже без интернета, данные синхронизируются автоматически при появлении связи (В планах)</li>
<li><strong>Always-editing режим</strong> — карточка визита всегда готова к редактированию, автосохранение, никаких лишних кликов</li>
<li><strong>Глубокая интеграция с Bitrix24</strong> — не просто API, а полноценная двусторонняя синхронизация с обработкой вебхуков</li>
<li><strong>Type-safe full-stack</strong> — минимум runtime ошибок благодаря TypeScript и Pydantic</li>
<li><strong>Extensible архитектура</strong> — готовность к добавлению других CRM и новых функций</li>
</ol>
<h2>12. Заключение</h2>
<p><strong>West Visit</strong> — это не просто «планировщик визитов». Это <strong>цифровая экосистема</strong> для фармацевтических компаний, которая:</p>
<ul>
<li>Объединяет поле и офис</li>
<li>Автоматизирует рутину</li>
<li>Даёт данные для аналитики</li>
<li>Масштабируется вместе с бизнесом</li>
<li>Адаптируется под любые требования</li>
</ul>
<p>Проект демонстрирует, как <strong>правильная архитектура</strong> и <strong>современные технологии</strong> могут превратить сложный бизнес-процесс в простой и понятный digital experience.</p>
<p>Медицинский представитель тратит 2 минуты вместо 15. Руководитель видит всю картину в реальном времени. Компания получает структурированные данные для принятия решений. Все довольны.</p>
<hr />
<p><strong>Технологии:</strong> Python 3.11, FastAPI, PostgreSQL, SQLAlchemy, React 18, TypeScript, Material-UI, React Query, Docker</p>
<p><strong>Интеграции:</strong> Bitrix24 REST API, Smart Processes, Webhook</p>
<p><strong>Статус:</strong> Production-ready, активная разработка новых features</p>
<p>&nbsp;</p><p>The post <a href="https://shknv.ru/320-2/">Портфолио: Система учёта визитов «Visit»</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Beton-CRM: Динамическая форма для оформления заявок.</title>
		<link>https://shknv.ru/beton-crm-dinamicheskaja-forma-dlja-oformlenija/</link>
		
		<dc:creator><![CDATA[Evgeniy Shikunov]]></dc:creator>
		<pubDate>Sun, 22 Jun 2025 08:52:29 +0000</pubDate>
				<category><![CDATA[portfolio]]></category>
		<category><![CDATA[code]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=318</guid>

					<description><![CDATA[<p>Введение Beton-CRM — это специализированная веб-система, разработанная для оптимизации и автоматизации процесса приёма и обработки заказов в компании по производству бетона. Проект был создан с нуля для решения уникальных задач бизнеса, требующих гибкости и высокой производительности, недоступных в стандартных &#171;коробочных&#187; решениях. Основная цель проекта — предоставить интуитивно понятный инструмент для клиентов и мощную административную панель для менеджеров. Система [&#8230;]</p>
<p>The post <a href="https://shknv.ru/beton-crm-dinamicheskaja-forma-dlja-oformlenija/">Beton-CRM: Динамическая форма для оформления заявок.</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-4" class="markdown-section" data-markdown-raw=" # **Beton-CRM: Комплексная CRM-система для бетонной промышленности**" data-section-index="4">
<h1><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-466" src="https://shknv.ru/wp-content/uploads/2025/06/image.png" alt="" width="1536" height="1024" srcset="https://shknv.ru/wp-content/uploads/2025/06/image.png 1536w, https://shknv.ru/wp-content/uploads/2025/06/image-300x200.png 300w, https://shknv.ru/wp-content/uploads/2025/06/image-1024x683.png 1024w, https://shknv.ru/wp-content/uploads/2025/06/image-768x512.png 768w" sizes="auto, (max-width: 1536px) 100vw, 1536px" /></h1>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-5" class="markdown-section" data-markdown-raw=" ### **Введение**" data-section-index="5">
<h3><span class="markdown-bold-text">Введение</span></h3>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-7" class="markdown-section" data-markdown-raw=" Beton-CRM — это специализированная веб-система, разработанная для оптимизации и автоматизации процесса приёма и обработки заказов в компании по производству бетона. Проект был создан с нуля для решения уникальных задач бизнеса, требующих гибкости и высокой производительности, недоступных в стандартных &quot;коробочных&quot; решениях." data-section-index="7">Beton-CRM — это специализированная веб-система, разработанная для оптимизации и автоматизации процесса приёма и обработки заказов в компании по производству бетона. Проект был создан с нуля для решения уникальных задач бизнеса, требующих гибкости и высокой производительности, недоступных в стандартных &#171;коробочных&#187; решениях.</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-9" class="markdown-section" data-markdown-raw=" Основная цель проекта — предоставить интуитивно понятный инструмент для клиентов и мощную административную панель для менеджеров. Система построена на современном технологическом стеке: **React** и **TypeScript** на фронтенде, **Node.js** и **Express** на бэкенде, с базой данных **MongoDB** и глубокой интеграцией с корпоративной CRM **Bitrix24**." data-section-index="9">Основная цель проекта — предоставить интуитивно понятный инструмент для клиентов и мощную административную панель для менеджеров. Система построена на современном технологическом стеке: <span class="markdown-bold-text">React</span> и <span class="markdown-bold-text">TypeScript</span> на фронтенде, <span class="markdown-bold-text">Node.js</span> и <span class="markdown-bold-text">Express</span> на бэкенде, с базой данных <span class="markdown-bold-text">MongoDB</span> и глубокой интеграцией с корпоративной CRM <span class="markdown-bold-text">Bitrix24</span>.</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-10" class="markdown-section" data-markdown-raw=" --- " data-section-index="10">
<hr />
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-11" class="markdown-section" data-markdown-raw=" ## **Ключевая особенность: Динамический конструктор форм**" data-section-index="11">
<h2><span class="markdown-bold-text">Ключевая особенность: Динамический конструктор форм</span></h2>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-13" class="markdown-section" data-markdown-raw=" Сердцем Beton-CRM является мощный и гибкий конструктор форм. В отличие от статичных форм, где каждое поле жестко закодировано, наша система позволяет администраторам полностью управлять структурой формы заказа без привлечения разработчиков." data-section-index="13">Сердцем Beton-CRM является мощный и гибкий конструктор форм. В отличие от статичных форм, где каждое поле жестко закодировано, наша система позволяет администраторам полностью управлять структурой формы заказа без привлечения разработчиков.</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-14" class="markdown-section" data-markdown-raw=" #### **Возможности административной панели:**" data-section-index="14">
<h4><span class="markdown-bold-text">Возможности административной панели:</span></h4>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-15" class="markdown-section" data-markdown-raw=" * **Полное управление полями:** Создание, редактирование и удаление полей различных типов: текст, число, выпадающий список, дата, чекбокс и умное поле с автозаполнением. * **Структурирование формы:** Организация полей в логические разделы (например, &quot;Информация о компании&quot;, &quot;Детали заказа&quot;, &quot;Технические параметры&quot;) с помощью специальных полей-заголовков. * **Интуитивное управление порядком:** Удобный **Drag-and-Drop интерфейс** для изменения порядка полей и целых разделов, позволяющий быстро адаптировать форму под меняющиеся бизнес-требования. Система автоматически пересчитывает порядок всех затронутых элементов, поддерживая целостность данных." data-section-index="15">
<ul>
<li data-indent="0"><span class="markdown-bold-text">Полное управление полями:</span> Создание, редактирование и удаление полей различных типов: текст, число, выпадающий список, дата, чекбокс и умное поле с автозаполнением.</li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">Структурирование формы:</span> Организация полей в логические разделы (например, &#171;Информация о компании&#187;, &#171;Детали заказа&#187;, &#171;Технические параметры&#187;) с помощью специальных полей-заголовков.</li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">Интуитивное управление порядком:</span> Удобный <span class="markdown-bold-text">Drag-and-Drop интерфейс</span> для изменения порядка полей и целых разделов, позволяющий быстро адаптировать форму под меняющиеся бизнес-требования. Система автоматически пересчитывает порядок всех затронутых элементов, поддерживая целостность данных.</li>
</ul>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-17" class="markdown-section" data-markdown-raw=" Эта гибкость гарантирует, что форма всегда будет актуальной и будет содержать только необходимые поля, что упрощает процесс заполнения для конечного пользователя." data-section-index="17">Эта гибкость гарантирует, что форма всегда будет актуальной и будет содержать только необходимые поля, что упрощает процесс заполнения для конечного пользователя.</section>
<section data-markdown-raw=" Эта гибкость гарантирует, что форма всегда будет актуальной и будет содержать только необходимые поля, что упрощает процесс заполнения для конечного пользователя." data-section-index="17"><img loading="lazy" decoding="async" class="aligncenter wp-image-312 size-large" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.36.10@2x-1024x931.png" alt="" width="1024" height="931" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.36.10@2x-1024x931.png 1024w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.36.10@2x-300x273.png 300w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.36.10@2x-768x698.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.36.10@2x-1536x1397.png 1536w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.36.10@2x-2048x1863.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-21" class="markdown-section" data-markdown-raw=" --- " data-section-index="21">
<hr />
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-22" class="markdown-section" data-markdown-raw=" ## **Глубокая интеграция с Bitrix24**" data-section-index="22">
<h2></h2>
<h2><span class="markdown-bold-text">Глубокая интеграция с Bitrix24</span></h2>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-24" class="markdown-section" data-markdown-raw=" Одной из важнейших задач была бесшовная интеграция с существующей в компании CRM-системой — Bitrix24. Beton-CRM не заменяет её, а расширяет, автоматизируя поток данных." data-section-index="24">Одной из важнейших задач была бесшовная интеграция с существующей в компании CRM-системой — Bitrix24. Beton-CRM не заменяет её, а расширяет, автоматизируя поток данных.</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-25" class="markdown-section" data-markdown-raw=" #### **Как это работает:**" data-section-index="25">
<h4><span class="markdown-bold-text">Как это работает:</span></h4>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-26" class="markdown-section" data-markdown-raw=" 1. **Синхронизация данных в реальном времени:** Поля с автозаполнением (например, &quot;Название компании&quot; или &quot;Продукт&quot;) напрямую запрашивают данные из Bitrix24. Когда пользователь начинает вводить текст, система мгновенно предлагает релевантные варианты из базы данных компании. Это устраняет ошибки и дубликаты. *Ключевой доработкой стала интеллектуальная система поиска: если пользователь вводит цифры, поиск идет по ID, если текст — по названию.* 2. **Автоматическое создание сделок:** После того как пользователь отправляет заполненную форму, система автоматически создает новую сделку в Bitrix24 в нужной воронке, прикрепляя все введенные данные и корректно указывая ответственного менеджера. Это избавляет менеджеров от необходимости вручную переносить информацию. 3. **Обновление статусов:** Система синхронизирует статусы заявок между Beton-CRM и Bitrix24 с учетом категорий сделок, обеспечивая прозрачность процесса для всех участников. Это было достигнуто благодаря правильной передаче &#96;categoryId&#96; и формированию &#96;STAGE_ID&#96; с префиксом категории." data-section-index="26">
<ol>
<li value="1" data-indent="0"><span class="markdown-bold-text">Синхронизация данных в реальном времени:</span> Поля с автозаполнением (например, &#171;Название компании&#187; или &#171;Продукт&#187;) напрямую запрашивают данные из Bitrix24. Когда пользователь начинает вводить текст, система мгновенно предлагает релевантные варианты из базы данных компании. Это устраняет ошибки и дубликаты. <span class="markdown-italics-text">Ключевой доработкой стала интеллектуальная система поиска: если пользователь вводит цифры, поиск идет по ID, если текст — по названию.</span></li>
</ol>
<ol>
<li value="2" data-indent="0"><span class="markdown-bold-text">Автоматическое создание сделок:</span> После того как пользователь отправляет заполненную форму, система автоматически создает новую сделку в Bitrix24 в нужной воронке, прикрепляя все введенные данные и корректно указывая ответственного менеджера. Это избавляет менеджеров от необходимости вручную переносить информацию.</li>
<li value="3" data-indent="0"><span class="markdown-bold-text">Обновление статусов:</span> Система синхронизирует статусы заявок между Beton-CRM и Bitrix24 с учетом категорий сделок, обеспечивая прозрачность процесса для всех участников. Это было достигнуто благодаря правильной передаче <span class="markdown-inline-code leading-[1.4]">categoryId</span> и формированию <span class="markdown-inline-code leading-[1.4]">STAGE_ID</span> с префиксом категории.</li>
</ol>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-313 size-large" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.39.02@2x-779x1024.png" alt="" width="779" height="1024" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.39.02@2x-779x1024.png 779w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.39.02@2x-228x300.png 228w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.39.02@2x-768x1009.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.39.02@2x-1169x1536.png 1169w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.39.02@2x.png 1332w" sizes="auto, (max-width: 779px) 100vw, 779px" /></p>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-30" class="markdown-section" data-markdown-raw=" --- " data-section-index="30">
<hr />
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-31" class="markdown-section" data-markdown-raw=" ## **Интеллектуальные функции и пользовательский опыт (UX)**" data-section-index="31">
<h2><span class="markdown-bold-text">Интеллектуальные функции и пользовательский опыт (UX)</span></h2>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-33" class="markdown-section" data-markdown-raw=" Мы уделили особое внимание тому, чтобы сделать работу с формой максимально удобной." data-section-index="33">Мы уделили особое внимание тому, чтобы сделать работу с формой максимально удобной.</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-34" class="markdown-section" data-markdown-raw=" * **Связанные поля (Linked Fields):** Эта функция позволяет одним кликом копировать информацию между разными разделами формы (например, данные из раздела &quot;Заказчик&quot; в раздел &quot;Получатель&quot;). Это значительно ускоряет заполнение и минимизирует вероятность ошибок. *Мы решили сложную проблему копирования значений в полях с автозаполнением, где система теперь корректно переносит как ID, так и отображаемое значение.* * **Удобная навигация:** Длинная форма разделена на сворачиваемые разделы (аккордеоны). Пользователь может сосредоточиться на текущем блоке, а не теряться в большом количестве полей. *Изначально была проблема, когда поля без раздела не отображались, но мы это исправили, сделав такие группы всегда раскрытыми по умолчанию.* * **Управление доступом на основе ролей:** * **Пользователи:** Могут создавать заявки и отслеживать статусы только своих заказов. * **Администраторы:** Имеют полный доступ к системе — управляют структурой формы, пользователями, видят все заявки и могут настраивать интеграции." data-section-index="34">
<ul>
<li data-indent="0"><span class="markdown-bold-text">Связанные поля (Linked Fields):</span> Эта функция позволяет одним кликом копировать информацию между разными разделами формы (например, данные из раздела &#171;Заказчик&#187; в раздел &#171;Получатель&#187;). Это значительно ускоряет заполнение и минимизирует вероятность ошибок. <span class="markdown-italics-text">Мы решили сложную проблему копирования значений в полях с автозаполнением, где система теперь корректно переносит как ID, так и отображаемое значение.</span></li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">Удобная навигация:</span> Длинная форма разделена на сворачиваемые разделы (аккордеоны). Пользователь может сосредоточиться на текущем блоке, а не теряться в большом количестве полей. <span class="markdown-italics-text">Изначально была проблема, когда поля без раздела не отображались, но мы это исправили, сделав такие группы всегда раскрытыми по умолчанию.</span></li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">Управление доступом на основе ролей:</span></li>
</ul>
<ul class="nested">
<li class="nested" data-indent="4"><span class="markdown-bold-text">Пользователи:</span> Могут создавать заявки и отслеживать статусы только своих заказов.</li>
</ul>
<ul class="nested">
<li class="nested" data-indent="4"><span class="markdown-bold-text">Администраторы:</span> Имеют полный доступ к системе — управляют структурой формы, пользователями, видят все заявки и могут настраивать интеграции.</li>
</ul>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-314" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.41.40@2x-941x1024.png" alt="" width="941" height="1024" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.41.40@2x-941x1024.png 941w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.41.40@2x-276x300.png 276w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.41.40@2x-768x836.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.41.40@2x.png 1244w" sizes="auto, (max-width: 941px) 100vw, 941px" /> <img loading="lazy" decoding="async" class="alignnone wp-image-315 size-large" src="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.44.38@2x-1024x781.png" alt="" width="1024" height="781" srcset="https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.44.38@2x-1024x781.png 1024w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.44.38@2x-300x229.png 300w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.44.38@2x-768x586.png 768w, https://shknv.ru/wp-content/uploads/2025/06/CleanShot-2025-06-22-at-11.44.38@2x.png 1524w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-38" class="markdown-section" data-markdown-raw=" --- " data-section-index="38">
<hr />
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-39" class="markdown-section" data-markdown-raw=" ## **Оптимизация производительности: фокус на Android и мобильных устройствах**" data-section-index="39">
<h2><span class="markdown-bold-text">Оптимизация производительности: фокус на Android и мобильных устройствах</span></h2>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-41" class="markdown-section" data-markdown-raw=" Одной из самых сложных и интересных задач была оптимизация производительности. Первоначальные тесты показали, что на мобильных устройствах (особенно на Android) форма работала медленно, с заметными задержками при вводе текста." data-section-index="41">Одной из самых сложных и интересных задач была оптимизация производительности. Первоначальные тесты показали, что на мобильных устройствах (особенно на Android) форма работала медленно, с заметными задержками при вводе текста.</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-42" class="markdown-section" data-markdown-raw=" #### **Принятые меры:**" data-section-index="42">
<h4><span class="markdown-bold-text">Принятые меры:</span></h4>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-43" class="markdown-section" data-markdown-raw=" * **Миграция с Formik на React Hook Form:** Этот стратегический шаг позволил избавиться от проблемы &quot;лишних&quot; перерисовок компонентов (re-renders) и значительно повысить отзывчивость интерфейса. Это решило критическую ошибку &#96;Maximum update depth exceeded&#96;. * **Адаптивная оптимизация ввода:** Была внедрена &quot;умная&quot; система с использованием техник &#96;debounce&#96; и &#96;throttle&#96;. Запросы на поиск в полях с автозаполнением отправляются не при каждом нажатии клавиши, а с задержкой (например, 1000 мс), что кардинально снизило нагрузку. * **Создание легковесных компонентов:** Разработан специальный компонент &#96;FastAutocompleteInput&#96;, оптимизированный для быстрой работы на медленных устройствах. Вся система оптимизации была вынесена в отдельный хук &#96;useAndroidOptimization&#96;." data-section-index="43">
<ul>
<li data-indent="0"><span class="markdown-bold-text">Миграция с Formik на React Hook Form:</span> Этот стратегический шаг позволил избавиться от проблемы &#171;лишних&#187; перерисовок компонентов (re-renders) и значительно повысить отзывчивость интерфейса. Это решило критическую ошибку <span class="markdown-inline-code leading-[1.4]">Maximum update depth exceeded</span>.</li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">Адаптивная оптимизация ввода:</span> Была внедрена &#171;умная&#187; система с использованием техник <span class="markdown-inline-code leading-[1.4]">debounce</span> и <span class="markdown-inline-code leading-[1.4]">throttle</span>. Запросы на поиск в полях с автозаполнением отправляются не при каждом нажатии клавиши, а с задержкой (например, 1000 мс), что кардинально снизило нагрузку.</li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">Создание легковесных компонентов:</span> Разработан специальный компонент <span class="markdown-inline-code leading-[1.4]">FastAutocompleteInput</span>, оптимизированный для быстрой работы на медленных устройствах. Вся система оптимизации была вынесена в отдельный хук <span class="markdown-inline-code leading-[1.4]">useAndroidOptimization</span>.</li>
</ul>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-44" class="markdown-section" data-markdown-raw=" #### **Результаты:**" data-section-index="44">
<h4><span class="markdown-bold-text">Результаты:</span></h4>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-46" class="markdown-section" data-markdown-raw=" Проведенное профилирование показало впечатляющие улучшения:" data-section-index="46">Проведенное профилирование показало впечатляющие улучшения:</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-47" class="markdown-section" data-markdown-raw=" * **INP (Interaction to Next Paint) снизился на 51%:** с 3,720 мс до 1,824 мс. * **Отклик на ввод с клавиатуры ускорился до 75%.**" data-section-index="47">
<ul>
<li data-indent="0"><span class="markdown-bold-text">INP (Interaction to Next Paint) снизился на 51%:</span> с 3,720 мс до 1,824 мс.</li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">Отклик на ввод с клавиатуры ускорился до 75%.</span></li>
</ul>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-49" class="markdown-section" style="font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; border-radius: 4px; margin: 6px 0px; position: relative; scroll-margin-bottom: 40px; scroll-margin-top: 40px; color: #bec6d0; font-family: -apple-system, system-ui, sans-serif; font-size: 13px; font-variant-ligatures: normal; orphans: 2; widows: 2; background-color: #0c0f11; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;" data-markdown-raw=" &gt; Это доказывает, что даже сложные и тяжелые формы могут быть быстрыми и отзывчивыми на любом устройстве." data-section-index="49">&gt; Это доказывает, что даже сложные и тяжелые формы могут быть быстрыми и отзывчивыми на любом устройстве.</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-50" class="markdown-section" data-markdown-raw=" --- " data-section-index="50">
<hr />
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-51" class="markdown-section" data-markdown-raw=" ## **Техническая архитектура и процесс разработки**" data-section-index="51">
<h2><span class="markdown-bold-text">Техническая архитектура и процесс разработки</span></h2>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-53" class="markdown-section" data-markdown-raw=" Проект построен на надежном и масштабируемом стеке технологий." data-section-index="53">Проект построен на надежном и масштабируемом стеке технологий.</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-54" class="markdown-section" data-markdown-raw=" * **Frontend:** React, TypeScript, React Hook Form, Axios. * **Backend:** Node.js, Express, Mongoose (для работы с MongoDB), JWT (для аутентификации). * **База данных:** MongoDB. * **Инфраструктура:** Nginx для проксирования запросов, PM2 для управления процессами Node.js." data-section-index="54">
<ul>
<li data-indent="0"><span class="markdown-bold-text">Frontend:</span> React, TypeScript, React Hook Form, Axios.</li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">Backend:</span> Node.js, Express, Mongoose (для работы с MongoDB), JWT (для аутентификации).</li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">База данных:</span> MongoDB.</li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">Инфраструктура:</span> Nginx для проксирования запросов, PM2 для управления процессами Node.js.</li>
</ul>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-55" class="markdown-section" data-markdown-raw=" #### **Ключевые моменты процесса разработки:**" data-section-index="55">
<h4><span class="markdown-bold-text">Ключевые моменты процесса разработки:</span></h4>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-56" class="markdown-section" data-markdown-raw=" * **Целостность данных:** С самого начала был сделан акцент на надежности. Была разработана система автоматической валидации базы данных при старте сервера, которая проверяет целостность связей между сущностями (например, что у каждого поля есть форма) и может автоматически исправлять некоторые проблемы. Это предотвратило множество трудноуловимых багов, таких как &quot;исчезающие&quot; поля. * **Итеративное решение проблем:** В ходе разработки было решено множество нетривиальных задач: от исправления ошибок рендеринга в React до отладки сложных сценариев взаимодействия с API Bitrix24 и проблем с позиционированием элементов при Drag-and-Drop. * **Строгая типизация:** Использование TypeScript на всех уровнях проекта позволило минимизировать количество ошибок во время выполнения и сделало кодовую базу более понятной и поддерживаемой." data-section-index="56">
<ul>
<li data-indent="0"><span class="markdown-bold-text">Целостность данных:</span> С самого начала был сделан акцент на надежности. Была разработана система автоматической валидации базы данных при старте сервера, которая проверяет целостность связей между сущностями (например, что у каждого поля есть форма) и может автоматически исправлять некоторые проблемы. Это предотвратило множество трудноуловимых багов, таких как &#171;исчезающие&#187; поля.</li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">Итеративное решение проблем:</span> В ходе разработки было решено множество нетривиальных задач: от исправления ошибок рендеринга в React до отладки сложных сценариев взаимодействия с API Bitrix24 и проблем с позиционированием элементов при Drag-and-Drop.</li>
</ul>
<ul>
<li data-indent="0"><span class="markdown-bold-text">Строгая типизация:</span> Использование TypeScript на всех уровнях проекта позволило минимизировать количество ошибок во время выполнения и сделало кодовую базу более понятной и поддерживаемой.</li>
</ul>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-57" class="markdown-section" data-markdown-raw=" --- " data-section-index="57">
<hr />
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-58" class="markdown-section" data-markdown-raw=" ## **Итоги проекта**" data-section-index="58">
<h2><span class="markdown-bold-text">Итоги проекта</span></h2>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-60" class="markdown-section" data-markdown-raw=" Beton-CRM — это успешный пример того, как индивидуальная разработка может решить специфические задачи бизнеса гораздо эффективнее универсальных инструментов. В результате была создана быстрая, надежная и гибкая CRM-система, которая:" data-section-index="60">Beton-CRM — это успешный пример того, как индивидуальная разработка может решить специфические задачи бизнеса гораздо эффективнее универсальных инструментов. В результате была создана быстрая, надежная и гибкая CRM-система, которая:</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-61" class="markdown-section" data-markdown-raw=" * Автоматизировала рутинные задачи менеджеров. * Упростила и ускорила процесс заказа для клиентов. * Обеспечила полную синхронизацию данных с основной корпоративной системой. * Продемонстрировала возможность достижения высокой производительности на сложных формах даже на мобильных устройствах." data-section-index="61">
<ul>
<li data-indent="0">Автоматизировала рутинные задачи менеджеров.</li>
</ul>
<ul>
<li data-indent="0">Упростила и ускорила процесс заказа для клиентов.</li>
</ul>
<ul>
<li data-indent="0">Обеспечила полную синхронизацию данных с основной корпоративной системой.</li>
</ul>
<ul>
<li data-indent="0">Продемонстрировала возможность достижения высокой производительности на сложных формах даже на мобильных устройствах.</li>
</ul>
</section>
<section id="markdown-section-992ec2aa-bb70-483e-9ced-3bc80ebc4285-63" class="markdown-section" data-markdown-raw=" Этот проект является отличным дополнением к портфолио, демонстрирующим навыки в full-stack разработке, решении сложных архитектурных задач, оптимизации производительности и интеграции со сторонними сервисами." data-section-index="63">Этот проект является отличным дополнением к портфолио, демонстрирующим навыки в full-stack разработке, решении сложных архитектурных задач, оптимизации производительности и интеграции со сторонними сервисами.</section><p>The post <a href="https://shknv.ru/beton-crm-dinamicheskaja-forma-dlja-oformlenija/">Beton-CRM: Динамическая форма для оформления заявок.</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
