/rlebe[dev].dev
Приложение маркетплейса МойСклад

Платёж появился в МойСкладе — и уже привязан к нужному документу

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

ВХОДЯЩИЙ ПЛАТЁЖ · СОЗДАН ТОЛЬКО ЧТО14.03.2026
Контрагент
ООО «Ромашка»
Сумма
30 000,00 ₽
Назначение
Оплата по счёту №СЧ-00001234 от 12.03.2026, в том числе НДС
СЧЁТ ПОКУПАТЕЛЮ СЧ-00001234НАЙДЕН
Сумма счёта
100 000,00 ₽
Было оплачено
0,00 ₽
Привязано
30 000,00 ₽ — частичная оплата, остаток 70 000,00 ₽
18
комбинаций привязки
4
типа платёжных документов
до 10
шаблонов назначения
0
ручных сверок
Задача

Выписка пришла утром. Разносить её будут до вечера

Платежи в МойСклад попадают, а к документам не привязываются: кто-то должен открыть каждый, найти нужный заказ или счёт, сверить сумму и связать вручную. Пока это не сделано, отчёт по дебиторке врёт, а «оплачено / не оплачено» в заказах не отражает реальность.

Цена ручной сверки

Ошибка находится через месяц

Платёж привязали не к тому счёту — и клиенту уходит напоминание о долге, которого нет. Или наоборот: реальный долг не виден, потому что деньги «закрыли» чужой заказ.

Частичные оплаты

Одна сумма на несколько документов

Клиент прислал 70 000 ₽ за три заказа. Руками это разносится дольше всего и ошибается чаще всего.

Расходы

Статья расходов не проставлена

Исходящие платежи уходят без статьи, и любой управленческий отчёт по расходам приходится собирать заново вручную.

Правила привязки

Девять способов найти нужный документ. И ещё девять — на закупках

Три типа документа × три стратегии поиска — на каждую сторону денег. Настройка выбирается один раз под то, как работает ваш бизнес: строгая привязка по сумме, распределение по очереди или разбор назначения платежа.

Документ По сумме и контрагенту По контрагенту По назначению платежа
Заказ покупателя Точное совпадение суммы. Минимум ложных срабатываний — рабочий вариант по умолчанию. FIFO: сумма распределяется по неоплаченным заказам, начиная со старых. Номер заказа берётся из текста платежа. Сумма может быть любой.
Счёт покупателю Для тех, кто работает счетами, а не заказами. Закрытие накопленных долгов постоянного клиента одним переводом. Самый точный вариант в B2B — если клиент указывает номер счёта.
Отгрузка Постоплата: деньги привязываются к факту отгрузки. Отсрочка платежа, контроль дебиторки по контрагенту. Оплата по номеру накладной.
Шаблоны, а не регулярки

«счёту №$name от $moment»

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

Приоритет

До десяти шаблонов по порядку

Порядок и есть приоритет: выигрывает первый совпавший. Fallback-эвристик нет намеренно — не совпал ни один шаблон, значит данные не извлечены. Лучше не привязать, чем привязать не туда.

Устойчивость к тексту

Пробелы, регистр и «ё» не мешают

Поиск идёт подстрокой без учёта регистра, последовательности пробелов приравниваются. Дата обязана присутствовать, если она есть в шаблоне, — иначе совпадение не засчитывается.

Порядок разбора

Старые документы или новые — на выбор

Для стратегий с распределением задаётся направление: сначала закрывать давние долги или сначала свежие отгрузки.

Вторая половина работы

Статья расходов проставляется сама — по контрагенту

МойСклад не даёт связать контрагента со статьёй расходов напрямую: у контрагента нет такого поля. Обходной путь пришлось построить целиком — и он работает без участия пользователя после первичной настройки.

1

Создаётся справочник-зеркало

Пользовательский справочник «Статьи расходов для привязки» — точная копия ваших статей расходов. Создаётся приложением, не руками.

2

Зеркало держится в синхроне в обе стороны

Вебхуки на создание, изменение и удаление висят и на статьях расходов, и на справочнике-зеркале. Переименовали статью — переименовалась копия, и наоборот. Отдельная ручка показывает расхождение, если оно возникло.

3

У контрагента появляется поле со списком

Дополнительное поле «Статья расходов для привязки», ссылающееся на зеркало. Менеджер выбирает значение из выпадающего списка прямо в карточке контрагента — в привычном интерфейсе МойСклада.

4

Исходящий платёж получает статью автоматически

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

Что под капотом

Вебхуки приходят дважды, аккаунтов много, а API отвечает 429

Приложение живёт в чужой инфраструктуре и не управляет ни доставкой событий, ни лимитами. Поэтому большая часть работы — не «найти документ», а не сломаться, когда всё идёт не по плану.

Повторы

Уже привязанный платёж пропускается

МойСклад доставляет вебхук повторно при любой неопределённости. Обработчик проверяет состояние документа до того, как что-то менять, — двойной привязки не происходит.

Мультиаккаунтность

Один инстанс, много установок

Приложение обслуживает несколько аккаунтов МойСклад одновременно. Контекст аккаунта разрешается явно на каждом запросе: настройки, токены и вебхуки одной компании не пересекаются с чужими.

Сеть

Ретраи с экспоненциальной задержкой

Каждое обращение к API обёрнуто повторами через tenacity с настраиваемым числом попыток и таймаутом. Временная недоступность МойСклада не превращается в потерянный платёж.

Vendor API

Установка и удаление — тоже код

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

Структура

19 доменных модулей, каждый со своим слоем

Домен, сервисы, репозитории и Unit of Work — на каждый тип документа МойСклада свой модуль с общей базой для платежей и оплачиваемых документов. Новый тип документа добавляется по образцу, а не правкой одного большого обработчика.

Наблюдаемость

Видно, что произошло с каждым событием

Результат обработки — явный объект: сработало, пропущено или ошибка, с причиной. Разбирать, почему платёж не привязался, можно по логу, а не по догадкам.

Стек

FastAPI · SQLAlchemy 2 async · вебхуки МойСклад

Ядро
Python 3.11FastAPIPydantic SettingsUvicorn
Данные
SQLAlchemy 2 asyncUnit of WorkрепозиторииSQLite / PostgreSQL
Интеграция
JSON API 1.2Vendor APIhttpxtenacityJWT
Интерфейс и запуск
Jinja2MoySklad UI KitDocker Compose
Дальше

Что у вас делают руками только потому, что «система так не умеет»?

Разнесение выписки, проставление статей, сверка остатков, перенос данных между системами — это ровно тот класс задач, где автоматизация окупается за месяцы, а не за годы. Ограничение учётной системы почти всегда обходится через её же API.

Разбор процессаЧто именно делается руками, сколько это стоит в часах и что из этого автоматизируется.
Интеграция или приложениеОтдельный сервис на вебхуках или полноценное приложение маркетплейса — по ситуации.
Работа с чужим APIЛимиты, повторные доставки, идемпотентность, мультиаккаунтность — то, на чём такие проекты обычно и ломаются.
Обсудить проект →