<?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</title>
	<atom:link href="https://shknv.ru/category/razrabotka/feed/" rel="self" type="application/rss+xml" />
	<link>https://shknv.ru</link>
	<description>Евгений Шикунов</description>
	<lastBuildDate>Sat, 25 Apr 2026 15:36:20 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://shknv.ru/wp-content/uploads/2024/12/web-app-manifest-512x512-1-150x150.png</url>
	<title>Разработка - Portfolio</title>
	<link>https://shknv.ru</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Своя разработка или коробочное решение: как бизнесу не переплатить за неправильный выбор</title>
		<link>https://shknv.ru/custom-software-vs-boxed-solution/</link>
		
		<dc:creator><![CDATA[post]]></dc:creator>
		<pubDate>Mon, 20 Apr 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[Разработка]]></category>
		<category><![CDATA[CRM]]></category>
		<category><![CDATA[SaaS]]></category>
		<category><![CDATA[Гайд]]></category>
		<category><![CDATA[разработка]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=588</guid>

					<description><![CDATA[<p>Универсального ответа здесь нет. Одним компаниям действительно нужен Bitrix24 или другая коробка, другим — собственный продуктовый контур. Важно понять, где у вас типовой процесс, а где именно там рождается конкурентное преимущество.</p>
<p>The post <a href="https://shknv.ru/custom-software-vs-boxed-solution/">Своя разработка или коробочное решение: как бизнесу не переплатить за неправильный выбор</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="wp-block-group">
<p><strong>Коротко:</strong> Универсального ответа здесь нет. Одним компаниям действительно нужен Bitrix24 или другая коробка, другим — собственный продуктовый контур. Важно понять, где у вас типовой процесс, а где именно там рождается конкурентное преимущество.</p>
<ul>
<li>Время чтения: 11 минут</li>
<li>Формат: практический разбор без лишней теории</li>
</ul>
</div>
<div class="wp-block-group">
<p><strong>Что внутри:</strong></p>
<ul>
<li><a href="#custom-software-vs-boxed-solution-1">1. Насколько ваш процесс типовой</a></li>
<li><a href="#custom-software-vs-boxed-solution-2">2. Где находится ваша конкурентная ценность</a></li>
<li><a href="#custom-software-vs-boxed-solution-3">3. Как быстро нужен результат</a></li>
<li><a href="#custom-software-vs-boxed-solution-4">4. Готов ли бизнес быть владельцем продукта</a></li>
<li><a href="#custom-software-vs-boxed-solution-5">5. Насколько критичны интеграции и ограничения платформы</a></li>
<li><a href="#custom-software-vs-boxed-solution-6">6. Что происходит с экономикой владения</a></li>
<li><a href="#custom-software-vs-boxed-solution-7">Где компании ошибаются чаще всего</a></li>
<li><a href="#custom-software-vs-boxed-solution-8">Что работает лучше всего на практике</a></li>
</ul>
</div>
<p>Вопрос &#171;делать своё или брать готовое&#187; кажется техническим, но на самом деле это управленческое решение. Ошибка здесь стоит дорого в обе стороны.</p>
<p>Если компания слишком рано идёт в собственную разработку, она получает длинный, дорогой и ресурсоёмкий проект там, где можно было быстро запустить типовое решение. Если, наоборот, бизнес слишком долго держится за коробку, он начинает подгонять процесс под ограничения системы и теряет в эффективности.</p>
<p>Чтобы не спорить на уровне вкусов, полезно смотреть на несколько факторов.</p>
<h2 id="custom-software-vs-boxed-solution-1">1. Насколько ваш процесс типовой</h2>
<p>Если ваш контур продаж, заявок, согласований или сервиса в целом похож на сотни других компаний, коробочное решение часто имеет смысл. Вы получаете быстрый запуск, понятную стоимость и готовую экосистему.</p>
<p>Но если ключевой процесс компании действительно специфичен — например, связан с полевыми командами, сложными интеграциями, внутренней логикой расчётов или нестандартным пользовательским сценарием — коробка быстро начинает мешать.</p>
<p>Хороший вопрос здесь звучит так: мы пытаемся автоматизировать типовую практику рынка или свой собственный способ работать?</p>
<h2 id="custom-software-vs-boxed-solution-2">2. Где находится ваша конкурентная ценность</h2>
<p>Не все процессы одинаково важны. Иногда компании нужна уникальность не везде, а только в одном критическом звене.</p>
<p>Например:</p>
<ul>
<li>CRM для базового контура продаж может быть коробочной;</li>
<li>а мобильный инструмент для полевой команды — своим;</li>
<li>закупочный workflow может быть типовым;</li>
<li>а AI-модуль сравнения номенклатуры — кастомным.</li>
</ul>
<p>То есть выбор не всегда бинарный. Часто лучший вариант — гибридная схема, где коробка закрывает стандартную часть, а разработка усиливает то место, где у бизнеса своя логика и своё преимущество.</p>
<h2 id="custom-software-vs-boxed-solution-3">3. Как быстро нужен результат</h2>
<p>Если бизнесу важно быстро запуститься, проверить гипотезу или стабилизировать базовый процесс, коробочное решение почти всегда выигрывает. У него ниже порог входа и короче путь до рабочего состояния.</p>
<p>Собственная разработка требует:</p>
<ul>
<li>discovery;</li>
<li>проектирования;</li>
<li>поэтапной реализации;</li>
<li>тестирования;</li>
<li>поддержки после запуска.</li>
</ul>
<p>Это не плохо, просто это другой тип инвестиции.</p>
<h2 id="custom-software-vs-boxed-solution-4">4. Готов ли бизнес быть владельцем продукта</h2>
<p>Собственная система — это не только свобода, но и ответственность. Нужно принимать решения по бэклогу, приоритетам, качеству данных, развитию, интеграциям и поддержке.</p>
<p>Если внутри компании нет зрелого владельца продукта или хотя бы устойчивого процесса принятия решений, кастомная разработка легко начинает буксовать.</p>
<p>Коробка в этом смысле менее требовательна: часть сложных решений уже принята за вас.</p>
<h2 id="custom-software-vs-boxed-solution-5">5. Насколько критичны интеграции и ограничения платформы</h2>
<p>Иногда основной аргумент в пользу разработки — не &#171;мы хотим своё&#187;, а &#171;готовый продукт слишком тяжело интегрировать с нашей реальностью&#187;. Такое бывает, когда:</p>
<ul>
<li>много внутренних систем;</li>
<li>сложные правила обмена данными;</li>
<li>нетерпимы ограничения по интерфейсу и логике;</li>
<li>нужен offline-first или специфический мобильный контур;</li>
<li>важны нестандартные права, сценарии и процессы.</li>
</ul>
<p>Если вы уже на этапе предпроекта видите большое количество обходных маршрутов и костылей, это серьёзный сигнал в пользу более гибкой архитектуры.</p>
<h2 id="custom-software-vs-boxed-solution-6">6. Что происходит с экономикой владения</h2>
<p>На старте коробка обычно выглядит дешевле. И часто это правда. Но в длинной перспективе нужно учитывать не только лицензию или подписку, а всю стоимость владения:</p>
<ul>
<li>доработки;</li>
<li>интеграции;</li>
<li>обучение;</li>
<li>ограничения масштабирования;</li>
<li>зависимость от чужой roadmap;</li>
<li>стоимость обходных ручных процессов.</li>
</ul>
<p>И наоборот, у собственной разработки выше входной порог, но при правильной архитектуре она может стать выгоднее на масштабе, если критичный процесс действительно ваш и сильно влияет на экономику бизнеса.</p>
<h2 id="custom-software-vs-boxed-solution-7">Где компании ошибаются чаще всего</h2>
<h3>Ошибка 1. Идти в разработку из самолюбия</h3>
<p>&#171;Нам нужно своё, потому что мы особенные&#187; — плохой аргумент. Своё решение оправдано только тогда, когда это подтверждается процессом, интеграциями и экономикой.</p>
<h3>Ошибка 2. Держаться за коробку из страха</h3>
<p>Иногда бизнес давно вырос из типового решения, но боится признать, что количество ограничений уже стало дороже, чем нормальная пересборка контура.</p>
<h3>Ошибка 3. Видеть только первый бюджет</h3>
<p>Сравнивать только стоимость запуска — недостаточно. Нужно смотреть на 2–3 года вперёд.</p>
<h2 id="custom-software-vs-boxed-solution-8">Что работает лучше всего на практике</h2>
<p>Чаще всего зрелое решение выглядит так:</p>
<ul>
<li>коробка для типового и стандартного;</li>
<li>кастомная разработка для действительно специфичного;</li>
<li>интеграции между ними как часть архитектуры, а не как послепродажная боль.</li>
</ul>
<p>Это позволяет не переплачивать за уникальность там, где она не нужна, и не душить бизнес ограничениями там, где она критична.</p>
<h2 id="custom-software-vs-boxed-solution-9">Вывод</h2>
<p>Выбор между коробочным решением и собственной разработкой не должен строиться на эмоциях, моде или убеждении &#171;на рынке всё плохо&#187;. Он должен строиться на вопросах о типичности процесса, ценности для бизнеса, зрелости команды и стоимости владения.</p>
<p>Если ваш процесс типовой — коробка часто даёт лучший ROI. Если процесс сложный, интеграционно насыщенный и напрямую влияет на конкурентное преимущество — своя разработка может оказаться намного рациональнее.</p>
<p>Главное — не путать желание &#171;иметь своё&#187; с реальной необходимостью в своём.</p>
<p><!-- shknv-related:start --></p>
<section class="wp-block-group shknv-related-materials">
<h2>Связанные материалы</h2>
<p>Эти материалы дополняют статью и помогают перейти к соседним темам без повторения одного и того же материала.</p>
<ul>
<li><a href="https://shknv.ru/licenzionnyj-portal-ot-idei-do-production/">Лицензионный портал: от идеи до production</a> — дополняет техническую часть разработки и инфраструктуры</li>
<li><a href="https://shknv.ru/kejs-it-budget-manager-polnyj-obzor/">Кейс: IT Budget Manager: полный обзор</a> — дополняет тему управленческого учета, KPI и бюджета</li>
<li><a href="https://shknv.ru/kejs-sistema-upravlenija-it-bjudzhetom/">Кейс: Система управления IT-бюджетом</a> — дополняет тему управленческого учета, KPI и бюджета</li>
<li><a href="https://shknv.ru/it-audit-or-new-system/">Когда бизнесу нужен IT-аудит, а не ещё одна новая система</a> — связанный кейс или практический разбор из блога</li>
<li><a href="https://shknv.ru/choose-dev-automation-contractor/">Как выбрать подрядчика на разработку и автоматизацию без лишнего риска</a> — связанный кейс или практический разбор из блога</li>
</ul>
</section>
<p><!-- shknv-related:end --></p><p>The post <a href="https://shknv.ru/custom-software-vs-boxed-solution/">Своя разработка или коробочное решение: как бизнесу не переплатить за неправильный выбор</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Как выбрать подрядчика на разработку и автоматизацию без лишнего риска</title>
		<link>https://shknv.ru/choose-dev-automation-contractor/</link>
		
		<dc:creator><![CDATA[post]]></dc:creator>
		<pubDate>Mon, 20 Apr 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[Автоматизация]]></category>
		<category><![CDATA[Разработка]]></category>
		<category><![CDATA[автоматизация]]></category>
		<category><![CDATA[Гайд]]></category>
		<category><![CDATA[подрядчик]]></category>
		<category><![CDATA[разработка]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=590</guid>

					<description><![CDATA[<p>Подрядчика часто выбирают по презентации, цене и обещаниям скорости. Но самые дорогие ошибки случаются позже — когда выясняется, что у команды нет процесса, нормальной диагностики и зрелого отношения к рискам. Разбираем, на что смотреть до подписания договора.</p>
<p>The post <a href="https://shknv.ru/choose-dev-automation-contractor/">Как выбрать подрядчика на разработку и автоматизацию без лишнего риска</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="wp-block-group">
<p><strong>Коротко:</strong> Подрядчика часто выбирают по презентации, цене и обещаниям скорости. Но самые дорогие ошибки случаются позже — когда выясняется, что у команды нет процесса, нормальной диагностики и зрелого отношения к рискам. Разбираем, на что смотреть до подписания договора.</p>
<ul>
<li>Время чтения: 10 минут</li>
<li>Формат: практический разбор без лишней теории</li>
</ul>
</div>
<div class="wp-block-group">
<p><strong>Что внутри:</strong></p>
<ul>
<li><a href="#choose-dev-automation-contractor-1">Что стоит проверить в первую очередь</a></li>
<li><a href="#choose-dev-automation-contractor-2">Красные флаги, которые я бы не игнорировал</a></li>
<li><a href="#choose-dev-automation-contractor-3">Что отличает зрелого подрядчика</a></li>
<li><a href="#choose-dev-automation-contractor-4">Какие вопросы полезно задать до подписания</a></li>
<li><a href="#choose-dev-automation-contractor-5">Почему цена не может быть единственным критерием</a></li>
<li><a href="#choose-dev-automation-contractor-6">Вывод</a></li>
</ul>
</div>
<p>Услуги по разработке и автоматизации очень легко продать на уверенности. Почти любая команда может показать красивый стек, список кейсов и пообещать, что &#171;всё сделает под ключ&#187;. Проблема в том, что реальное качество подрядчика становится видно не на этапе коммерческого предложения, а позже — когда возникают первые спорные решения, ограничения и риски.</p>
<p>Поэтому выбирать подрядчика лучше не по красивым словам, а по тому, как команда думает и как ведёт проект ещё до старта.</p>
<h2 id="choose-dev-automation-contractor-1">Что стоит проверить в первую очередь</h2>
<h3>1. Как команда разбирает задачу</h3>
<p>Зрелый подрядчик не начинает с перечисления технологий. Он сначала задаёт вопросы:</p>
<ul>
<li>какую бизнес-проблему решаем;</li>
<li>где сейчас ломается процесс;</li>
<li>кто пользователи;</li>
<li>какие есть ограничения;</li>
<li>как будет измеряться результат.</li>
</ul>
<p>Если с первой встречи вам продают стек и обещают &#171;сделать всё быстро&#187;, это повод насторожиться.</p>
<h3>2. Есть ли у подрядчика понятная рамка проекта</h3>
<p>Хорошая команда умеет сказать:</p>
<ul>
<li>что входит в первый этап;</li>
<li>что сознательно не входит;</li>
<li>где есть риски;</li>
<li>какие решения нужно принять со стороны бизнеса;</li>
<li>как будут идти итерации и приёмка.</li>
</ul>
<p>Размытые формулировки почти всегда превращаются в конфликт ожиданий.</p>
<h3>3. Как подрядчик относится к неопределённости</h3>
<p>Сильная команда не делает вид, что знает всё заранее. Она умеет отделять понятное от непонятного, формулировать гипотезы и предлагать нормальный способ снизить неопределённость: аудит, discovery, прототип, пилот.</p>
<p>Слабая команда, наоборот, часто обещает слишком точно и слишком рано.</p>
<h2 id="choose-dev-automation-contractor-2">Красные флаги, которые я бы не игнорировал</h2>
<h3>&#171;Сделаем всё, как скажете&#187;</h3>
<p>На слух это звучит клиенториентированно. На деле так часто выглядит отсутствие собственной инженерной позиции. Хороший подрядчик не спорит ради спора, но умеет объяснить, почему один путь лучше другого.</p>
<h3>&#171;Сначала подпишем, потом разберём детали&#187;</h3>
<p>Если детали критичны для бюджета, сроков и результата, их нельзя откладывать до запуска.</p>
<h3>&#171;Оценка точная, хотя мы почти ничего не уточняли&#187;</h3>
<p>Это не признак силы. Это признак того, что вас либо ещё не поняли, либо намеренно обещают удобную цифру.</p>
<h3>Нет разговоров о поддержке и развитии</h3>
<p>Разработка заканчивается не в день релиза. Если подрядчик не обсуждает поддержку, ownership, документацию, передачу знаний и контур изменений, значит проект смотрят слишком коротко.</p>
<h2 id="choose-dev-automation-contractor-3">Что отличает зрелого подрядчика</h2>
<p>Есть несколько признаков, которые обычно хорошо работают.</p>
<h3>Подрядчик умеет говорить о рисках спокойно</h3>
<p>Не скрывает сложные места, не прячет ограничения под формулировкой &#171;разберёмся по ходу&#187;, а честно объясняет, что может пойти не так и как этим управлять.</p>
<h3>Подрядчик не тащит вас в лишнюю сложность</h3>
<p>Сильная команда не продаёт сложность ради чека. Если задачу можно решить проще, она так и скажет. Например:</p>
<ul>
<li>начать с коробочного контура, а не сразу с кастомной платформы;</li>
<li>провести аудит до внедрения;</li>
<li>ограничить первый релиз узким сценарием;</li>
<li>не внедрять AI там, где достаточно нормальной аналитики.</li>
</ul>
<h3>Подрядчик умеет показать логику решений</h3>
<p>Не просто &#171;мы делали похожее&#187;, а:</p>
<ul>
<li>почему предлагается именно такой подход;</li>
<li>какие есть альтернативы;</li>
<li>какие у них trade-off;</li>
<li>где бизнес сэкономит, а где наоборот должен быть готов инвестировать.</li>
</ul>
<h2 id="choose-dev-automation-contractor-4">Какие вопросы полезно задать до подписания</h2>
<p>Вот короткий список вопросов, который быстро вскрывает зрелость команды:</p>
<ol>
<li>Как вы будете разбираться в нашей текущей ситуации?</li>
<li>Какие риски вы видите уже сейчас?</li>
<li>Что мы должны подготовить со своей стороны?</li>
<li>Что будет первым измеримым результатом?</li>
<li>Как будет устроена приёмка?</li>
<li>Кто с вашей стороны отвечает за продуктовую логику, а кто за технику?</li>
<li>Что вы сделаете, если на середине проекта выяснится, что часть гипотез неверна?</li>
</ol>
<p>Ответы на эти вопросы обычно говорят о подрядчике больше, чем презентация с логотипами.</p>
<h2 id="choose-dev-automation-contractor-5">Почему цена не может быть единственным критерием</h2>
<p>Низкая стоимость на старте легко превращается в высокую стоимость владения потом. Особенно если:</p>
<ul>
<li>проект плохо спроектирован;</li>
<li>нет документации;</li>
<li>команда не держит архитектуру;</li>
<li>сроки сдвигаются из-за постоянных переделок;</li>
<li>бизнесу приходится заново пересобирать контур с другим подрядчиком.</li>
</ul>
<p>Хороший выбор подрядчика — это не &#171;самый дорогой&#187; и не &#171;самый дешёвый&#187;. Это команда, которая понимает задачу, умеет держать рамку и не создаёт лишний риск для бизнеса.</p>
<h2 id="choose-dev-automation-contractor-6">Вывод</h2>
<p>Выбор подрядчика на разработку и автоматизацию — это не закупка часов. Это выбор партнёра по изменениям в процессе, данных и архитектуре.</p>
<p>Поэтому важнее всего смотреть не на уверенность в голосе и не на красивый стек, а на то, как команда думает: умеет ли она диагностировать проблему, ставить границы, объяснять trade-off и вести проект без лишнего шума.</p>
<p>Именно это в итоге сильнее всего влияет на то, получите вы рабочий результат или ещё одну затянувшуюся историю про &#171;почти внедрили&#187;.</p>
<p><!-- shknv-related:start --></p>
<section class="wp-block-group shknv-related-materials">
<h2>Связанные материалы</h2>
<p>Эти материалы дополняют статью и помогают перейти к соседним темам без повторения одного и того же материала.</p>
<ul>
<li><a href="https://shknv.ru/licenzionnyj-portal-ot-idei-do-production/">Лицензионный портал: от идеи до production</a> — дополняет техническую часть разработки и инфраструктуры</li>
<li><a href="https://shknv.ru/sozdanie-servisa/">Создание сервиса</a> — дополняет техническую часть разработки и инфраструктуры</li>
<li><a href="https://shknv.ru/kejs-veb-prilozhenie-zdorovoe-pitanie/">Кейс: Веб-приложение &#171;Здоровое питание&#187;</a> — связанный кейс или практический разбор из блога</li>
<li><a href="https://shknv.ru/custom-software-vs-boxed-solution/">Своя разработка или коробочное решение: как бизнесу не переплатить за неправильный выбор</a> — связанный кейс или практический разбор из блога</li>
<li><a href="https://shknv.ru/signs-you-need-automation/">5 признаков того, что вашему бизнесу действительно нужна автоматизация</a> — связанный кейс или практический разбор из блога</li>
</ul>
</section>
<p><!-- shknv-related:end --></p><p>The post <a href="https://shknv.ru/choose-dev-automation-contractor/">Как выбрать подрядчика на разработку и автоматизацию без лишнего риска</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Лицензионный портал: от идеи до production</title>
		<link>https://shknv.ru/licenzionnyj-portal-ot-idei-do-production/</link>
		
		<dc:creator><![CDATA[Evgeniy Shikunov]]></dc:creator>
		<pubDate>Wed, 26 Nov 2025 13:10:40 +0000</pubDate>
				<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=537</guid>

					<description><![CDATA[<p>Кейс лицензионного портала: как продукт проходит путь от идеи и архитектуры до production-запуска и поддержки.</p>
<p>The post <a href="https://shknv.ru/licenzionnyj-portal-ot-idei-do-production/">Лицензионный портал: от идеи до production</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<h1 style="text-align: left;">Лицензионный портал: от идеи до production</h1>
<p style="text-align: left;"><strong>Как я создал полноценную систему управления лицензиями для собственного<br />
SaaS-продукта за 3 недели</strong></p>
<p style="text-align: left;">Рассказываю о разработке лицензионного портала — системы, которая контролирует<br />
выдачу ключей, мониторит активации и автоматизирует весь цикл работы с<br />
клиентами IT Budget Manager.</p>
<h2 style="text-align: left;"><img fetchpriority="high" decoding="async" class="aligncenter size-large wp-image-538" src="https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.00.23-2x-1024x406.png" alt="" width="1024" height="406" srcset="https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.00.23-2x-1024x406.png 1024w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.00.23-2x-300x119.png 300w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.00.23-2x-768x304.png 768w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.00.23-2x-1536x609.png 1536w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.00.23-2x-2048x811.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></h2>
<h2 style="text-align: left;">Ключевые цифры проекта</h2>
<ul style="text-align: left;">
<li><strong>11 таблиц</strong> в базе данных</li>
<li><strong>33 разрешения</strong> в системе RBAC</li>
<li><strong>5 ролей</strong> пользователей</li>
<li><strong>ECDSA P-256</strong> — криптографическая подпись лицензий</li>
<li><strong>FastAPI + React</strong> — современный стек</li>
<li><strong>Docker Compose</strong> — полная контейнеризация</li>
</ul>
<h2 style="text-align: left;">Предыстория: зачем понадобился отдельный портал</h2>
<p style="text-align: left;">Budget Manager — это веб-система управления бюджетом, которую я<br />
разрабатываю как самостоятельный продукт. Когда проект вырос до уровня, где<br />
его можно предлагать внешним клиентам, встал вопрос:<br />
<strong>как контролировать лицензии?</strong></p>
<p style="text-align: left;">Варианты были такие:</p>
<ol style="text-align: left;">
<li><strong>Ручной контроль в Excel</strong> — не масштабируется, легко потерять<br />
данные</li>
<li><strong>Готовые SaaS-решения</strong> — дорого, избыточно, нет контроля</li>
<li><strong>Свой портал</strong> — полный контроль, интеграция с продуктом,<br />
кастомная логика</li>
</ol>
<p style="text-align: left;">Выбрал третий путь. Да, это больше работы, но зато:</p>
<ul style="text-align: left;">
<li>Полная интеграция с основным продуктом</li>
<li>Криптографическая защита лицензий</li>
<li>Автоматический мониторинг установок</li>
<li>Гибкая система ролей под мою команду</li>
</ul>
<h2 style="text-align: left;">Архитектура решения</h2>
<p style="text-align: left;">Портал построен по классической схеме с разделением на frontend и backend:</p>
<p>&nbsp;</p>
<p><img decoding="async" class="aligncenter size-full wp-image-545" src="https://shknv.ru/wp-content/uploads/2025/11/unnamed.jpg" alt="" width="1024" height="559" srcset="https://shknv.ru/wp-content/uploads/2025/11/unnamed.jpg 1024w, https://shknv.ru/wp-content/uploads/2025/11/unnamed-300x164.jpg 300w, https://shknv.ru/wp-content/uploads/2025/11/unnamed-768x419.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p style="text-align: left;">Технологический стек</p>
<p style="text-align: left;"><strong>Backend:</strong></p>
<ul style="text-align: left;">
<li>FastAPI — асинхронный Python-фреймворк</li>
<li>SQLAlchemy + Alembic — ORM и миграции</li>
<li>PostgreSQL — основная БД</li>
<li>Redis — кэширование и rate limiting</li>
<li>cryptography — ECDSA подпись лицензий</li>
<li>Pydantic — валидация данных</li>
</ul>
<p style="text-align: left;"><strong>Frontend:</strong></p>
<ul style="text-align: left;">
<li>React 18 + TypeScript</li>
<li>Ant Design — UI-компоненты</li>
<li>Zustand — state management</li>
<li>Vite — сборка</li>
</ul>
<p style="text-align: left;"><strong>Инфраструктура:</strong></p>
<ul style="text-align: left;">
<li>Docker Compose — локальная разработка и production</li>
<li>GitHub Actions — CI/CD</li>
<li>Nginx — reverse proxy</li>
</ul>
<h2 style="text-align: left;">Модель данных: что храним в БД</h2>
<p style="text-align: left;">Проектирование схемы БД — один из самых важных этапов. Вот что получилось:</p>
<h3 style="text-align: left;">Основные сущности</h3>
<p style="text-align: left;"><strong>Клиенты (clients)</strong> — юрлица с ИНН, сегментом<br />
(SMB/Enterprise/Government) и типом внедрения (on-prem/SaaS).</p>
<p style="text-align: left;"><strong>Лицензии (licenses)</strong> — ключевая таблица:</p>
<ul style="text-align: left;">
<li>Уникальный ключ (LIC-XXXXXX)</li>
<li>План (Basic/Advanced/Enterprise)</li>
<li>Список модулей (JSON)</li>
<li>Лимиты: пользователи, отделы, интеграции, API rate</li>
<li>Сроки действия + grace period</li>
<li>Статус: draft/active/expired/revoked/suspended</li>
</ul>
<p style="text-align: left;"><img decoding="async" class="aligncenter size-large wp-image-540" src="https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.07.40-2x-1024x333.png" alt="" width="1024" height="333" srcset="https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.07.40-2x-1024x333.png 1024w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.07.40-2x-300x98.png 300w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.07.40-2x-768x250.png 768w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.07.40-2x-1536x500.png 1536w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.07.40-2x-2048x667.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<p style="text-align: left;"><strong>Активации (license_activations)</strong> — записи об установках:</p>
<ul style="text-align: left;">
<li>ID сервера клиента</li>
<li>IP-адрес</li>
<li>Версия продукта</li>
<li>Последний heartbeat</li>
<li>Метрики использования</li>
</ul>
<p style="text-align: left;"><strong>Организации (organizations)</strong> — для self-service регистрации<br />
клиентов на портале.</p>
<h3 style="text-align: left;">ENUM-типы для консистентности</h3>
<p><code>clientsegment: smb, enterprise, government<br />
deploymenttype: on_prem, saas<br />
licenseplan: basic, advanced, enterprise<br />
licensestatus: draft, active, expired, revoked, suspended<br />
paymentstatus: pending, paid, overdue, cancelled, refunded</code></p>
<h2 style="text-align: left;">Криптографическая подпись лицензий</h2>
<p style="text-align: left;">Это ядро всей системы. Каждая лицензия подписывается приватным ключом, а<br />
клиентская установка проверяет подпись публичным ключом.</p>
<h3 style="text-align: left;">Почему ECDSA P-256?</h3>
<ul style="text-align: left;">
<li><strong>Компактные ключи</strong> — в отличие от RSA</li>
<li><strong>Быстрая верификация</strong> — важно для клиентских установок</li>
<li><strong>Стандарт NIST</strong> — FIPS 186-4, проверенная криптография</li>
<li><strong>Эквивалент RSA-3072</strong> — по уровню безопасности</li>
</ul>
<h3 style="text-align: left;">Формат лицензионного токена</h3>
<p style="text-align: left;">Использую JWT-подобный формат из трёх частей:</p>
<p><code>&lt;base64(payload)&gt;.&lt;base64(metadata)&gt;.&lt;base64(signature)&gt;</code></p>
<p style="text-align: left;"><strong>Payload</strong> содержит все данные лицензии:</p>
<p><code><br />
{<br />
  "version": 1,<br />
  "license_key": "LIC-ABC123...",<br />
  "client_id": 123,<br />
  "client_name": "ООО Компания",<br />
  "plan": "enterprise",<br />
  "modules": ["basic_budgeting", "ai_forecast", "multi_department"],<br />
  "limits": {<br />
    "max_users": 100,<br />
    "max_departments": 50,<br />
    "max_integrations": 10,<br />
    "api_rate_limit": 1000<br />
  },<br />
  "validity": {<br />
    "start_date": "2025-01-01T00:00:00Z",<br />
    "end_date": "2026-01-01T00:00:00Z",<br />
    "grace_period_days": 30<br />
  },<br />
  "technical": {<br />
    "domain": "budget.company.com",<br />
    "product_version": "2.5.0"<br />
  },<br />
  "issued_at": "2024-12-15T10:30:00Z",<br />
  "issued_by": "admin@portal.com"<br />
}
</pre>
<p style="text-align: left;"><strong>Metadata</strong> — служебная информация:</p>
<p>{<br />
  "checksum": "a1b2c3d4...",  // SHA-256 от payload<br />
  "algorithm": "ECDSA-P256",<br />
  "signed_at": "2024-12-15T10:30:05Z"<br />
}<br />
</code></p>
<h3 style="text-align: left;">Защита от подделки</h3>
<table class=" alignleft">
<thead>
<tr>
<th>Атака</th>
<th>Защита</th>
</tr>
</thead>
<tbody>
<tr>
<td>Модификация данных</td>
<td><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;" /> Цифровая подпись ECDSA</td>
</tr>
<tr>
<td>Подмена payload</td>
<td><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;" /> SHA-256 checksum + подпись</td>
</tr>
<tr>
<td>Подмена клиента</td>
<td><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;" /> client_id в подписанном payload</td>
</tr>
<tr>
<td>Изменение сроков</td>
<td><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;" /> validity в подписанном payload</td>
</tr>
<tr>
<td>Replay атаки</td>
<td><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;" /> Уникальный license_key + heartbeat</td>
</tr>
</tbody>
</table>
<h2 style="text-align: left;">Система ролей и прав доступа (RBAC)</h2>
<p style="text-align: left;">Для управления доступом реализовал полноценную RBAC-систему с 5 ролями и 33<br />
разрешениями.</p>
<h3 style="text-align: left;">Роли пользователей</h3>
<table class=" alignleft">
<thead>
<tr>
<th>Роль</th>
<th>Описание</th>
<th>Ключевые права</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Admin</strong></td>
<td>Руководитель/DevOps</td>
<td>Полный доступ ко всему</td>
</tr>
<tr>
<td><strong>Sales Manager</strong></td>
<td>Менеджер по продажам</td>
<td>Клиенты, лицензии, оплаты</td>
</tr>
<tr>
<td><strong>Implementation</strong></td>
<td>Инженер внедрения</td>
<td>Активации, мониторинг, конфигурации</td>
</tr>
<tr>
<td><strong>Support</strong></td>
<td>Техподдержка</td>
<td>Только чтение + заметки</td>
</tr>
<tr>
<td><strong>Audit</strong></td>
<td>Финансы/юристы</td>
<td>Только чтение + отчёты</td>
</tr>
</tbody>
</table>
<h3 style="text-align: left;">Категории разрешений</h3>
<ul style="text-align: left;">
<li><strong>Клиенты:</strong> read, create, update, delete</li>
<li><strong>Лицензии:</strong> read, create, update, delete, activate, revoke,<br />
generate</li>
<li><strong>Активации:</strong> read, manage</li>
<li><strong>Платежи:</strong> read, create, update, delete</li>
<li><strong>Пользователи:</strong> read, create, update, delete, manage_roles</li>
<li><strong>Аудит:</strong> read</li>
<li><strong>Отчёты:</strong> view, export</li>
</ul>
<h3 style="text-align: left;">Использование в коде</h3>
<p><code># Проверка одного разрешения<br />
@router.get("/clients")<br />
async def get_clients(<br />
    user: User = Depends(require_permission(Permission.CLIENTS_READ))<br />
):<br />
    ...</p>
<p># Проверка роли<br />
@router.post("/critical")<br />
async def critical_operation(<br />
    user: User = Depends(require_role("admin"))<br />
):<br />
    ...<br />
</code></p>
<h2 style="text-align: left;">API для клиентских установок</h2>
<p style="text-align: left;">Отдельный набор endpoints для взаимодействия продукта с порталом. Защищён<br />
API-ключами (не JWT).</p>
<h3 style="text-align: left;">Основные endpoints</h3>
<p style="text-align: left;"><strong>POST /api/v1/license-verification/verify</strong> — проверка<br />
валидности ключа</p>
<p><code>Headers: X-API-Key: &lt;api_key&gt;<br />
Body: {<br />
  "license_key": "LIC-ABC123..."<br />
}<br />
Response: {<br />
  "valid": true,<br />
  "status": "active",<br />
  "organization": "ООО Компания",<br />
  "expires_at": "2026-01-01T00:00:00Z",<br />
  "modules": ["basic_budgeting", "ai_forecast"]<br />
}</code></p>
<p style="text-align: left;"><strong>POST /api/v1/product/licenses/activate</strong> — активация лицензии</p>
<p style="text-align: left;"><strong>POST /api/v1/product/licenses/heartbeat</strong> — периодический пинг<br />
от установки</p>
<h3 style="text-align: left;">Workflow активации</h3>
<ol style="text-align: left;">
<li>Пользователь регистрирует организацию на портале</li>
<li>Администратор создаёт лицензию и привязывает к организации</li>
<li>Клиент вводит ключ в своей установке IT Budget Manager</li>
<li>Установка делает запрос к API портала с API-ключом</li>
<li>Портал проверяет подпись, срок, статус</li>
<li>При успехе — возвращает конфигурацию модулей и лимитов</li>
<li>Продукт активируется с полученными параметрами</li>
</ol>
<h2 style="text-align: left;">Деплой и CI/CD</h2>
<p style="text-align: left;">Проект полностью контейнеризирован и деплоится через GitHub Actions.</p>
<h3 style="text-align: left;">Автоматический деплой</h3>
<p style="text-align: left;">При push в main:</p>
<ol style="text-align: left;">
<li>GitHub Actions подключается к серверу по SSH</li>
<li>Пуллит изменения</li>
<li>Пересобирает контейнеры</li>
<li>Применяет миграции БД</li>
<li>Перезапускает сервисы</li>
</ol>
<h2 style="text-align: left;">Что реализовано на текущий момент</h2>
<h3 style="text-align: left;"><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;" /> Полностью готово</h3>
<ul style="text-align: left;">
<li>Инфраструктура (Docker, PostgreSQL, Redis)</li>
<li>Модели данных и миграции Alembic</li>
<li>Система RBAC с 5 ролями</li>
<li>Криптографическая подпись лицензий (ECDSA P-256)</li>
<li>API аутентификации (JWT + API Keys)</li>
<li>CRUD для клиентов, лицензий, организаций</li>
<li>API проверки лицензионных ключей</li>
<li>Dashboard со статистикой</li>
<li>CI/CD через GitHub Actions</li>
<li>Документация (OpenAPI, README, инструкции)</li>
</ul>
<h3 style="text-align: left;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a7.png" alt="🚧" class="wp-smiley" style="height: 1em; max-height: 1em;" /> В процессе</h3>
<ul style="text-align: left;">
<li>Мастер создания лицензий (step-by-step wizard)</li>
<li>Дашборд мониторинга активаций</li>
<li>Система уведомлений (email, Telegram)</li>
<li>Интеграция с биллингом</li>
</ul>
<h2 style="text-align: left;">Уроки и выводы</h2>
<h3 style="text-align: left;">Что сработало хорошо</h3>
<p style="text-align: left;"><strong>1. FastAPI + Pydantic</strong> — отличная комбинация. Автоматическая<br />
валидация, генерация OpenAPI-документации, асинхронность из коробки.</p>
<p style="text-align: left;"><strong>2. Alembic для миграций</strong> — версионирование схемы БД спасает<br />
при командной разработке и откатах.</p>
<p style="text-align: left;"><strong>3. Docker Compose</strong> — одна команда для запуска всего окружения.<br />
Идентичность dev и prod.</p>
<p style="text-align: left;"><strong>4. ECDSA вместо RSA</strong> — компактные токены, быстрая верификация<br />
на клиенте.</p>
<h3 style="text-align: left;">Сложности</h3>
<p style="text-align: left;"><strong>1. Проектирование RBAC</strong> — пришлось несколько раз<br />
пересматривать список разрешений. Важно продумать заранее.</p>
<p style="text-align: left;"><strong>2. Хранение приватного ключа</strong> — в dev просто файл, в prod<br />
нужен Vault или KMS. Заложил абстракцию сразу.</p>
<p style="text-align: left;"><strong>3. Миграции с ENUM</strong> — PostgreSQL требует особого подхода при<br />
изменении ENUM-типов.</p>
<h3 style="text-align: left;">Рекомендации</h3>
<ul style="text-align: left;">
<li>Начинайте с модели данных — это фундамент</li>
<li>Закладывайте RBAC с первого дня</li>
<li>Используйте криптографию правильно — не изобретайте велосипед</li>
<li>Документируйте API сразу (OpenAPI)</li>
<li>Контейнеризируйте с самого начала</li>
</ul>
<h2 style="text-align: left;">Планы развития</h2>
<p style="text-align: left;"><strong>Ближайшие задачи:</strong></p>
<ul style="text-align: left;">
<li>Мастер создания лицензий с пошаговым wizard</li>
<li>Мониторинг активных установок в реальном времени</li>
<li>Email-уведомления об истечении лицензий</li>
<li>Telegram-бот для алертов</li>
</ul>
<p style="text-align: left;"><strong>Долгосрочные цели:</strong></p>
<ul style="text-align: left;">
<li>Интеграция с 1С для импорта платежей</li>
<li>Self-service кабинет для клиентов</li>
<li>Аналитика использования модулей</li>
<li>2FA для критических операций</li>
</ul>
<h2 style="text-align: left;">Итог</h2>
<p style="text-align: left;">Лицензионный портал — это не просто «база данных с ключами». Это полноценная<br />
система, которая:</p>
<ul style="text-align: left;">
<li><strong>Защищает</strong> продукт криптографически</li>
<li><strong>Автоматизирует</strong> выдачу и контроль лицензий</li>
<li><strong>Мониторит</strong> все установки в реальном времени</li>
<li><strong>Масштабируется</strong> вместе с бизнесом</li>
</ul>
<p style="text-align: left;">Разработка заняла около 3 недель активной работы. Основное время ушло на<br />
проектирование модели данных и криптографическую часть. UI и API —<br />
относительно быстро благодаря FastAPI и Ant Design.</p>
<p style="text-align: left;">Если вы разрабатываете SaaS-продукт и думаете о лицензировании — не<br />
откладывайте. Чем раньше заложите правильную архитектуру, тем меньше проблем<br />
будет при масштабировании.</p>
<p style="text-align: left;"><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-539" src="https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.05.21-2x-1024x762.png" alt="" width="1024" height="762" srcset="https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.05.21-2x-1024x762.png 1024w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.05.21-2x-300x223.png 300w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.05.21-2x-768x571.png 768w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.05.21-2x-1536x1143.png 1536w, https://shknv.ru/wp-content/uploads/2025/11/cleanshot-2025-11-26-at-16.05.21-2x-2048x1523.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<hr />
<p style="text-align: left;"><strong>Стек проекта:</strong> Python, FastAPI, PostgreSQL, Redis, React,<br />
TypeScript, Docker, GitHub Actions</p>
<p style="text-align: left;"><strong>Статус:</strong> В активной разработке, MVP готов</p>
<p style="text-align: left;">
<p><!-- shknv-related:start --></p>
<section class="wp-block-group shknv-related-materials">
<h2>Связанные материалы</h2>
<p>Эти материалы дополняют статью и помогают перейти к соседним темам без повторения одного и того же материала.</p>
<ul>
<li><a href="https://shknv.ru/sozdanie-servisa/">Создание сервиса</a> — дополняет техническую часть разработки и инфраструктуры</li>
<li><a href="https://shknv.ru/post-zapros-izmenenie-dokumenta/">Post запрос (изменение документа)</a> — дополняет техническую часть разработки и инфраструктуры</li>
<li><a href="https://shknv.ru/__trashed-3/">Get запрос (получение номенклатуры)</a> — связанный кейс или практический разбор из блога</li>
<li><a href="https://shknv.ru/personalnyj-veb-server/">Персональный веб сервер</a> — дополняет техническую часть разработки и инфраструктуры</li>
</ul>
</section>
<p><!-- shknv-related:end --></p><p>The post <a href="https://shknv.ru/licenzionnyj-portal-ot-idei-do-production/">Лицензионный портал: от идеи до production</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[portfolio]]></category>
		<category><![CDATA[Разработка]]></category>
		<category><![CDATA[автоматизация]]></category>
		<category><![CDATA[разработка]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=409</guid>

					<description><![CDATA[<p>Обзор новых функций Beton CRM: как доработки помогают оформлять заявки, управлять процессом и снижать ручной труд.</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>
<p><!-- shknv-related:start --></p>
<section class="wp-block-group shknv-related-materials">
<h2>Связанные материалы</h2>
<p>Эти материалы дополняют статью и помогают перейти к соседним темам без повторения одного и того же материала.</p>
<ul>
<li><a href="https://shknv.ru/beton-crm-dinamicheskaja-forma-dlja-oformlenija/">Beton-CRM: Динамическая форма для оформления заявок.</a> — дополняет кластер CRM, визитов и работы полевых команд</li>
<li><a href="https://shknv.ru/kejs-sozdanie-umnoj-crm-dlja-territorial/">(Кейс) Создание Умной CRM для Территориальных Менеджеров Полный Путь от Идеи до Реализации</a> — дополняет кластер CRM, визитов и работы полевых команд</li>
<li><a href="https://shknv.ru/bitrix24-dashboard-real-time-monitoring/">Bitrix24 Dashboard: Real-Time мониторинг</a> — дополняет тему IT-процессов и контроля</li>
<li><a href="https://shknv.ru/397-2/">Кейс: Разработка системы автоматического мониторинга цен конкурентов</a> — связанный практический материал из блога</li>
</ul>
</section>
<p><!-- shknv-related:end --><br />
</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[portfolio]]></category>
		<category><![CDATA[Автоматизация]]></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>Кейс разработки системы автоматического мониторинга цен конкурентов: сбор данных, контроль изменений и практическая аналитика.</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 loading="lazy" 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="auto, (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 loading="lazy" 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="auto, (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 loading="lazy" 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="auto, (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><!-- shknv-related:start --></p>
<section class="wp-block-group shknv-related-materials">
<h2>Связанные материалы</h2>
<p>Эти материалы дополняют статью и помогают перейти к соседним темам без повторения одного и того же материала.</p>
<ul>
<li><a href="https://shknv.ru/beton-crm-novye-fishki/">Бетон CRM: Новые фишки</a> — дополняет кластер CRM, визитов и работы полевых команд</li>
<li><a href="https://shknv.ru/kejs-sozdanie-umnoj-crm-dlja-territorial/">(Кейс) Создание Умной CRM для Территориальных Менеджеров Полный Путь от Идеи до Реализации</a> — дополняет кластер CRM, визитов и работы полевых команд</li>
<li><a href="https://shknv.ru/sistema-uchjota-vizitov-medicinskih-predstavitelej/">Система учёта визитов медицинских представителей</a> — дополняет кластер CRM, визитов и работы полевых команд</li>
<li><a href="https://shknv.ru/bitrix24-dashboard-real-time-monitoring/">Bitrix24 Dashboard: Real-Time мониторинг</a> — дополняет тему IT-процессов и контроля</li>
</ul>
</section>
<p><!-- shknv-related:end --></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>Кейс: Веб-приложение &#171;Здоровое питание&#187;</title>
		<link>https://shknv.ru/kejs-veb-prilozhenie-zdorovoe-pitanie/</link>
		
		<dc:creator><![CDATA[Evgeniy Shikunov]]></dc:creator>
		<pubDate>Fri, 01 Aug 2025 07:58:55 +0000</pubDate>
				<category><![CDATA[portfolio]]></category>
		<category><![CDATA[Разработка]]></category>
		<category><![CDATA[кейс]]></category>
		<category><![CDATA[разработка]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=392</guid>

					<description><![CDATA[<p>Кейс веб-приложения «Здоровое питание»: разработка пользовательского сервиса и практический опыт запуска проекта.</p>
<p>The post <a href="https://shknv.ru/kejs-veb-prilozhenie-zdorovoe-pitanie/">Кейс: Веб-приложение «Здоровое питание»</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<h1>Кейс: Веб-приложение &#171;Здоровое питание&#187; — персональный гид по трансформации образа жизни</h1>
<h2><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-393" src="https://shknv.ru/wp-content/uploads/2025/08/IMG_2842-592x1024.jpeg" alt="" width="592" height="1024" srcset="https://shknv.ru/wp-content/uploads/2025/08/IMG_2842-592x1024.jpeg 592w, https://shknv.ru/wp-content/uploads/2025/08/IMG_2842-173x300.jpeg 173w, https://shknv.ru/wp-content/uploads/2025/08/IMG_2842-768x1328.jpeg 768w, https://shknv.ru/wp-content/uploads/2025/08/IMG_2842-888x1536.jpeg 888w, https://shknv.ru/wp-content/uploads/2025/08/IMG_2842-1184x2048.jpeg 1184w, https://shknv.ru/wp-content/uploads/2025/08/IMG_2842.jpeg 1284w" sizes="auto, (max-width: 592px) 100vw, 592px" /><br />
Обзор проекта</h2>
<p>&#171;Здоровое питание&#187; — это прогрессивное веб-приложение (PWA), разработанное для помощи людям в улучшении здоровья, снижении веса и управлении стрессом через правильное питание. Приложение представляет собой интерактивный гид с практическими рекомендациями и системой отслеживания прогресса.</p>
<h2>Проблема</h2>
<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>Веб-приложение &#171;Здоровое питание&#187; предлагает комплексный подход к решению этих проблем через:</p>
<h3>1. <strong>Структурированная информация</strong></h3>
<ul>
<li>Четкие списки разрешенных и запрещенных продуктов</li>
<li>Конкретные рекомендации для разных ситуаций (доставка, столовая, магазин)</li>
<li>Простые правила, которые легко запомнить</li>
</ul>
<h3>2. <strong>Практические инструменты</strong></h3>
<ul>
<li>Интерактивный чек-лист ежедневных задач</li>
<li>Визуализация прогресса</li>
<li>Мотивационные сообщения</li>
</ul>
<h3>3. <strong>Экстренная помощь</strong></h3>
<ul>
<li>Алгоритмы действий в критических ситуациях</li>
<li>Стратегии борьбы с соблазнами</li>
<li>Психологическая поддержка</li>
</ul>
<h2>Ключевые функции</h2>
<h3> Адаптивный дизайн</h3>
<p>Приложение оптимизировано для мобильных устройств, что позволяет использовать его в любой момент — в магазине, ресторане или дома.</p>
<h3> Разделы по ситуациям</h3>
<ul>
<li><strong>Доставка еды</strong> — что заказывать и чего избегать</li>
<li><strong>Столовая</strong> — правило тарелки и стратегия выбора</li>
<li><strong>Перекусы</strong> — здоровые альтернативы и порции</li>
<li><strong>Чек-лист</strong> — ежедневные цели и отслеживание</li>
</ul>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4be.png" alt="💾" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Сохранение прогресса</h3>
<p>Использование localStorage для хранения данных о выполненных задачах, что позволяет отслеживать прогресс день за днем.</p>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3a8.png" alt="🎨" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Интуитивный интерфейс</h3>
<ul>
<li>Цветовая кодировка (зеленый — можно, красный — нельзя)</li>
<li>Эмодзи для быстрой навигации</li>
<li>Анимации для улучшения UX</li>
</ul>
<h2>Технические особенности</h2>
<h3>Производительность</h3>
<ul>
<li>Минималистичный подход без внешних зависимостей</li>
<li>Оптимизированный CSS с использованием современных техник</li>
<li>Vanilla JavaScript для максимальной скорости</li>
</ul>
<h3>Доступность</h3>
<ul>
<li>Семантическая разметка HTML</li>
<li>Контрастные цвета для читаемости</li>
<li>Поддержка мобильных жестов</li>
</ul>
<h3>Прогрессивность</h3>
<ul>
<li>Работает офлайн после первой загрузки</li>
<li>Можно добавить на главный экран как приложение</li>
<li>Адаптируется под любой размер экрана</li>
</ul>
<h2>Результаты и влияние</h2>
<h3>Для пользователей</h3>
<ul>
<li><strong>Упрощение выбора</strong> — больше не нужно думать, что можно есть</li>
<li><strong>Формирование привычек</strong> — ежедневный чек-лист помогает закрепить правильное поведение</li>
<li><strong>Снижение стресса</strong> — четкие инструкции убирают неопределенность</li>
<li><strong>Видимый прогресс</strong> — мотивация через визуализацию достижений</li>
</ul>
<h3>Метрики успеха</h3>
<ul>
<li>Ежедневное использование чек-листа</li>
<li>Снижение количества нарушений диеты</li>
<li>Улучшение общего самочувствия</li>
<li>Формирование устойчивых здоровых привычек</li>
</ul>
<h2>Дизайн-решения</h2>
<h3>Визуальная иерархия</h3>
<p>Использование карточек с цветовой кодировкой помогает быстро ориентироваться в информации. Зеленые карточки — рекомендации, красные — ограничения, оранжевые — важная информация.</p>
<h3>Микровзаимодействия</h3>
<p>Анимации при переключении вкладок, hover-эффекты и визуальная обратная связь при выполнении задач создают ощущение отзывчивого и живого интерфейса.</p>
<h3>Типографика</h3>
<p>Четкая иерархия заголовков и оптимальный размер шрифта обеспечивают комфортное чтение на любом устройстве.</p>
<h2>Уроки и выводы</h2>
<h3>Что сработало хорошо</h3>
<ol>
<li><strong>Простота использования</strong> — минимум действий для получения информации</li>
<li><strong>Фокус на практике</strong> — не теория, а конкретные действия</li>
<li><strong>Психологическая поддержка</strong> — учет эмоционального состояния пользователя</li>
</ol>
<h3>Возможности для развития</h3>
<ol>
<li>Интеграция с фитнес-трекерами</li>
<li>Персонализация рекомендаций</li>
<li>Социальные функции для поддержки сообщества</li>
<li>Расширенная аналитика прогресса</li>
</ol>
<h2>Заключение</h2>
<p>Проект &#171;Здоровое питание&#187; демонстрирует, как продуманный UX/UI дизайн и правильная архитектура могут создать эффективный инструмент для изменения образа жизни. Приложение не просто информирует, но активно помогает пользователям формировать здоровые привычки через простые, понятные и выполнимые шаги.</p>
<p>Ключ к успеху проекта — в балансе между функциональностью и простотой, что делает здоровый образ жизни доступным для каждого.</p>
<hr />
<p><strong>Технологии:</strong> HTML5, CSS3, JavaScript (ES6+), LocalStorage API, Progressive Web App</p>
<p><strong>Категория:</strong> Здоровье и благополучие, Продуктивность, Lifestyle</p>
<p><strong>Роль:</strong> Full-stack разработка, UX/UI дизайн, Продуктовая стратегия</p>
<p><!-- shknv-related:start --></p>
<section class="wp-block-group shknv-related-materials">
<h2>Связанные материалы</h2>
<p>Эти материалы дополняют статью и помогают перейти к соседним темам без повторения одного и того же материала.</p>
<ul>
<li><a href="https://shknv.ru/licenzionnyj-portal-ot-idei-do-production/">Лицензионный портал: от идеи до production</a> — дополняет техническую часть разработки и инфраструктуры</li>
<li><a href="https://shknv.ru/personalnyj-veb-server/">Персональный веб сервер</a> — дополняет техническую часть разработки и инфраструктуры</li>
<li><a href="https://shknv.ru/sozdanie-servisa/">Создание сервиса</a> — дополняет техническую часть разработки и инфраструктуры</li>
<li><a href="https://shknv.ru/proekt-interaktivnaja-karta-koncertn/">Проект: Интерактивная карта концертного тура &quot;Stigmata&quot;</a> — связанный кейс или практический разбор из блога</li>
</ul>
</section>
<p><!-- shknv-related:end --></p><p>The post <a href="https://shknv.ru/kejs-veb-prilozhenie-zdorovoe-pitanie/">Кейс: Веб-приложение «Здоровое питание»</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>
		<category><![CDATA[Разработка]]></category>
		<category><![CDATA[кейс]]></category>
		<category><![CDATA[разработка]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=328</guid>

					<description><![CDATA[<p>Кейс интерактивной карты концертного тура: как визуальный веб-проект проходит от идеи до удобного пользовательского сценария.</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><!-- shknv-related:start --></p>
<section class="wp-block-group shknv-related-materials">
<h2>Связанные материалы</h2>
<p>Эти материалы дополняют статью и помогают перейти к соседним темам без повторения одного и того же материала.</p>
<ul>
<li><a href="https://shknv.ru/kejs-veb-prilozhenie-zdorovoe-pitanie/">Кейс: Веб-приложение &quot;Здоровое питание&quot;</a> — связанный кейс или практический разбор из блога</li>
<li><a href="https://shknv.ru/licenzionnyj-portal-ot-idei-do-production/">Лицензионный портал: от идеи до production</a> — дополняет техническую часть разработки и инфраструктуры</li>
<li><a href="https://shknv.ru/personalnyj-veb-server/">Персональный веб сервер</a> — дополняет техническую часть разработки и инфраструктуры</li>
</ul>
</section>
<p><!-- shknv-related:end --></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[Автоматизация]]></category>
		<category><![CDATA[Разработка]]></category>
		<category><![CDATA[автоматизация]]></category>
		<category><![CDATA[кейс]]></category>
		<category><![CDATA[полевые команды]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=320</guid>

					<description><![CDATA[<p>Портфолио системы Visit для учета визитов: мобильный контур, фиксация факта работы и контроль полевой команды.</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><!-- shknv-related:start --></p>
<section class="wp-block-group shknv-related-materials">
<h2>Связанные материалы</h2>
<p>Эти материалы дополняют статью и помогают перейти к соседним темам без повторения одного и того же материала.</p>
<ul>
<li><a href="https://shknv.ru/sistema-uchjota-vizitov-medicinskih-predstavitelej/">Система учёта визитов медицинских представителей</a> — дополняет кластер CRM, визитов и работы полевых команд</li>
<li><a href="https://shknv.ru/kejs-sozdanie-umnoj-crm-dlja-territorial/">(Кейс) Создание Умной CRM для Территориальных Менеджеров Полный Путь от Идеи до Реализации</a> — дополняет кластер CRM, визитов и работы полевых команд</li>
<li><a href="https://shknv.ru/pharmachecker-chto-jeto/">Pharmachecker &#8212; что это?</a> — дополняет медицинский и фармацевтический контекст</li>
<li><a href="https://shknv.ru/pharmachecker-pomoshhnik-v-mire-lekarstv/">PharmaChecker-помощник в мире лекарств</a> — дополняет медицинский и фармацевтический контекст</li>
</ul>
</section>
<p><!-- shknv-related:end --></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[CRM]]></category>
		<category><![CDATA[portfolio]]></category>
		<category><![CDATA[Разработка]]></category>
		<category><![CDATA[telegram]]></category>
		<category><![CDATA[битрикс24]]></category>
		<category><![CDATA[разработка]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=318</guid>

					<description><![CDATA[<p>Как динамическая форма в Beton CRM упрощает оформление заявок и снижает ошибки при работе менеджеров.</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="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>
<section data-markdown-raw=" Этот проект является отличным дополнением к портфолио, демонстрирующим навыки в full-stack разработке, решении сложных архитектурных задач, оптимизации производительности и интеграции со сторонними сервисами." data-section-index="63"></section>
<section data-markdown-raw=" Этот проект является отличным дополнением к портфолио, демонстрирующим навыки в full-stack разработке, решении сложных архитектурных задач, оптимизации производительности и интеграции со сторонними сервисами." data-section-index="63">Видео, в котором обьясняется как был реализован этот кейс<br />
<a href="https://vkvideo.ru/video-232474128_456239020?list=ln-H2plhthryXQoyFQgZH">https://vkvideo.ru/video-232474128_456239020?list=ln-H2plhthryXQoyFQgZH</a></section>
<section data-markdown-raw=" Этот проект является отличным дополнением к портфолио, демонстрирующим навыки в full-stack разработке, решении сложных архитектурных задач, оптимизации производительности и интеграции со сторонними сервисами." data-section-index="63"></section>
<section data-markdown-raw=" Этот проект является отличным дополнением к портфолио, демонстрирующим навыки в full-stack разработке, решении сложных архитектурных задач, оптимизации производительности и интеграции со сторонними сервисами." data-section-index="63"></section>
<section data-markdown-raw=" Этот проект является отличным дополнением к портфолио, демонстрирующим навыки в full-stack разработке, решении сложных архитектурных задач, оптимизации производительности и интеграции со сторонними сервисами." data-section-index="63"></section>
<p><!-- shknv-related:start --></p>
<section class="wp-block-group shknv-related-materials">
<h2>Связанные материалы</h2>
<p>Эти материалы дополняют статью и помогают перейти к соседним темам без повторения одного и того же материала.</p>
<ul>
<li><a href="https://shknv.ru/beton-crm-novye-fishki/">Бетон CRM: Новые фишки</a> — дополняет кластер CRM, визитов и работы полевых команд</li>
<li><a href="https://shknv.ru/kejs-sozdanie-umnoj-crm-dlja-territorial/">(Кейс) Создание Умной CRM для Территориальных Менеджеров Полный Путь от Идеи до Реализации</a> — дополняет кластер CRM, визитов и работы полевых команд</li>
<li><a href="https://shknv.ru/bitrix24-dashboard-real-time-monitoring/">Bitrix24 Dashboard: Real-Time мониторинг</a> — дополняет тему IT-процессов и контроля</li>
</ul>
</section>
<p><!-- shknv-related:end --></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>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Создание сервиса</title>
		<link>https://shknv.ru/sozdanie-servisa/</link>
		
		<dc:creator><![CDATA[Evgeniy Shikunov]]></dc:creator>
		<pubDate>Fri, 13 Dec 2024 05:29:45 +0000</pubDate>
				<category><![CDATA[1c]]></category>
		<category><![CDATA[Разработка]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[интеграции]]></category>
		<guid isPermaLink="false">https://shknv.ru/?p=122</guid>

					<description><![CDATA[<p>Практический разбор создания сервиса и HTTP-обмена для задач интеграции 1С и внутренних систем.</p>
<p>The post <a href="https://shknv.ru/sozdanie-servisa/">Создание сервиса</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></description>
										<content:encoded><![CDATA[<h1>Создание HTTP-сервиса в 1С:Предприятие</h1>
<p>В данной статье описан процесс создания HTTP-сервиса в 1С, включая настройку сервиса, создание шаблона и обработчика запросов, а также публикацию базы данных на сервере.</p>
<hr />
<h2>1. Создание сервиса</h2>
<ol>
<li>Откройте конфигуратор вашей информационной базы.</li>
<li>В дереве конфигурации найдите раздел <strong>&#171;Общие&#187;</strong> и создайте новый объект типа <strong>&#171;HTTP-сервис&#187;</strong>.</li>
<li>Укажите имя вашего сервиса, например, <code>MyService</code>. Это имя будет частью URL, по которому будет доступен сервис.</li>
</ol>
<p>Пример структуры URL: <code>http://&lt;имя_сервера&gt;/&lt;путь_к_базе&gt;/hs/MyService</code></p>
<ol start="4">
<li>Сохраните изменения в конфигурации.</li>
</ol>
<hr />
<h2>2. Создание шаблона для обработки запросов</h2>
<p>Шаблон определяет маршруты (endpoints) и методы (GET, POST, PUT, DELETE), которые обрабатываются сервисом.</p>
<ol>
<li>В объекте &#171;HTTP-сервис&#187; перейдите на вкладку <strong>&#171;Шаблоны&#187;</strong>.</li>
<li>Добавьте новый маршрут, указав путь и методы запросов. Например, добавьте маршрут <code>/api/data</code> для обработки GET и POST запросов.</li>
<li>Укажите имя процедуры или функции, которая будет обрабатывать запросы для каждого метода.</li>
</ol>
<p>Пример настройки:</p>
<ul>
<li>Путь: <code>/api/data</code></li>
<li>Методы: GET, POST</li>
<li>Обработчик GET: <code>ПолучитьДанные</code></li>
<li>Обработчик POST: <code>ДобавитьДанные</code></li>
</ul>
<hr />
<h2>3. Создание обработчика запросов</h2>
<p>Для обработки запросов создайте процедуры в модуле HTTP-сервиса. Эти процедуры будут выполняться при получении запросов на указанные маршруты.</p>
<p>Пример обработчика для метода GET:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-plain" data-lang="Plain Text"><code>
Функция ШаблонURL1ПолучитьДанныеПоНоменклатуре(Запрос)
    Ответ = Новый HTTPСервисОтвет(200);

    // Установка заголовка через коллекцию Заголовки
    Ответ.Заголовки.Вставить("Content-Type", "application/json");

    // Получаем данные
    СтрокаJSON = АИР.ПолучитьСписокНоменклатуры();

    // Устанавливаем тело ответа
    Ответ.УстановитьТелоИзСтроки(СтрокаJSON);

    Возврат Ответ;
КонецФункции

</code></pre>
</div>
<p>Пример обработчика для метода POST:</p>
<p><span style="background-color: inherit; color: inherit; font-family: inherit; font-size: inherit; font-weight: inherit; white-space: pre;"> </span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-plain" data-lang="Plain Text"><code><span style="background-color: inherit; color: inherit; font-family: inherit; font-size: inherit; font-weight: inherit; white-space: pre;">Функция Changesumm(Запрос) // Получаем тело запроса</span>
Попытка
СтрокаJSON = Запрос.ПолучитьТелоКакСтроку();
Исключение
Возврат Новый HTTPСервисОтвет(400, "Ошибка при получении тела запроса");
КонецПопытки;

// Разбираем JSON
Попытка
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
СтруктураВходныхПараметров = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Исключение
Возврат Новый HTTPСервисОтвет(400, "Ошибка разбора JSON");
КонецПопытки;

// Передаем данные в модуль и получаем ответ
ОбъектОтвета = АИР.ОбновитьСуммуПоДокументу(СтруктураВходныхПараметров);

// Формируем HTTP-ответ
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(ОбъектОтвета);

Возврат Ответ;
КонецФункции</code></pre>
</div>
<p>&nbsp;</p>
<h2>4. Создание модуля для обработки запросов</h2>
<p>Для удобства и повторного использования создайте общий модуль, который будет содержать логику обработки запросов. Этот модуль можно вызывать из обработчиков HTTP-сервиса.</p>
<h3>Пример общего модуля:</h3>
<p>Название модуля: <code>ПолучитьСписокНоменклатуры</code></p>
<p>Код модуля:</p>
<div>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-plain" data-lang="Plain Text"><code>Функция ПолучитьСписокНоменклатуры() Экспорт
    Попытка
        Запрос = Новый Запрос;
        Запрос.Текст = "ВЫБРАТЬ Код КАК cod, Наименование КАК name, Артикул КАК articul ИЗ Справочник.Номенклатура";
        Выборка = Запрос.Выполнить().Выбрать();


        Массив = Новый Массив;
        Пока Выборка.Следующий() Цикл
            Массив.Добавить(Новый Структура("cod, name, articul", Строка(Выборка.cod), Строка(Выборка.name), Строка(Выборка.articul)));
КонецЦикла;


        Если Массив.Количество() &gt; 0 Тогда
    Возврат АИР.СтруктураВСтрокуJSON(Массив);
Иначе
    Возврат "1";
КонецЕсли;
    Исключение
        Сообщить("Ошибка выполнения запроса: " + ОписаниеОшибки());
        Возврат ОписаниеОшибки();
    КонецПопытки;
КонецФункции</code></pre>
</div>
</div>
<h2>5. Публикация базы на сервере</h2>
<p>Для того чтобы HTTP-сервис стал доступен через веб, необходимо опубликовать базу данных:</p>
<ol>
<li>В конфигураторе откройте меню <strong>&#171;Администрирование&#187;</strong> -&gt; <strong>&#171;Публикация на веб-сервере&#187;</strong>.</li>
<li>Укажите путь для публикации (например, <code>/MyBase</code>).</li>
<li>Включите поддержку HTTP-сервисов в параметрах публикации.</li>
<li>Нажмите &#171;ОК&#187; для применения настроек.</li>
</ol>
<p>После публикации сервис будет доступен по адресу:</p>
<p><code>http://&lt;имя_сервера&gt;/&lt;путь_к_базе&gt;/hs/MyService</code></p>
<hr />
<p>Теперь ваш HTTP-сервис готов к использованию! Вы можете отправлять запросы с помощью браузера, Postman или других HTTP-клиентов.</p>
<p><!-- shknv-related:start --></p>
<section class="wp-block-group shknv-related-materials">
<h2>Связанные материалы</h2>
<p>Эти материалы дополняют статью и помогают перейти к соседним темам без повторения одного и того же материала.</p>
<ul>
<li><a href="https://shknv.ru/post-zapros-izmenenie-dokumenta/">Post запрос (изменение документа)</a> — дополняет техническую часть разработки и инфраструктуры</li>
<li><a href="https://shknv.ru/__trashed-3/">Get запрос (получение номенклатуры)</a> — связанный кейс или практический разбор из блога</li>
<li><a href="https://shknv.ru/personalnyj-veb-server/">Персональный веб сервер</a> — дополняет техническую часть разработки и инфраструктуры</li>
<li><a href="https://shknv.ru/licenzionnyj-portal-ot-idei-do-production/">Лицензионный портал: от идеи до production</a> — дополняет техническую часть разработки и инфраструктуры</li>
</ul>
</section>
<p><!-- shknv-related:end --></p><p>The post <a href="https://shknv.ru/sozdanie-servisa/">Создание сервиса</a> first appeared on <a href="https://shknv.ru">Portfolio</a>.</p>]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
