От ручного заполнения документов к автоматизации: как собрать генератор шаблонных договоров в Telegram на Python

от автора

Коммерческие отделы ежедневно тратят много времени на ручное создание однотипных документов: копирование реквизитов из переписки, подстановка ФИО в нужном падеже, расчет графиков платежей, НДС и сумм прописью. Одна пропущенная цифра в ИНН или ошибка в склонении должности, и договор возвращается на доработку, а это задержка сделки.

В этой статье я покажу как собрал на Python Telegram-бота, который превращает 15-30 минут работы в ворде (борьбой с выравниваниями, шрифтами, отступами и пр.) в 5-минутный диалог. Никаких сложных CRM, никаких конструкторов с долгим обучением. Только async, последовательное управление состояниями, регулярные выражения и генерация готовых Word-файлов.

Архитектура решения

  • Интерфейс: Telegram Bot (python-telegram-bot v20+, асинхронный режим)

  • Управление состояниями: явное хранение шагов диалога в оперативной памяти с поддержкой возврата на предыдущий вопрос

  • Парсер реквизитов: регулярные выражения + правила для автоматического определения типа субъекта (ИП или ООО)

  • Генератор документа: docxtpl + шаблон .docx с динамическими блоками и вставкой внешних приложений

  • Запуск: облачный хостинг, секреты передаются через переменные окружения, корректное завершение работы при перезапуске

Ключевые технические решения

Telegram, очевидно, не сохраняет контекст переписки. А мне было необходимо собрать все ответы пользователя за итерацию, чтобы их аккуратно перенести в шаблон документа (предварительно размеченный). Для первой рабочей версии я реализовал явную машину состояний в оперативной памяти: каждый шаг фиксируется в словаре user_data[chat_id], а также реализовал команду возврата (/back), которая откатывает индексы и ответы пользователя. Это нужно для исправления ошибок ввода, которые часто видно сразу. То есть можно откатиться на шаг назад и исправить ответ.

# bot.py (фрагмент)async def handle_back(update: Update, context: ContextTypes.DEFAULT_TYPE):    chat_id = update.effective_chat.id    state = user_data.get(chat_id)    if not state: return        step = state.get("step")    if step == "main_flow":        f_idx = state.get("flow_idx", 0)        if f_idx > 0:            # Удаляем текущий ответ, откатываем индекс            curr_key = FLOW_STEPS[f_idx]            state.pop(curr_key, None)            state["flow_idx"] = f_idx - 1            # Пропускаем лишние шаги, если они были скрыты логикой            prev_key = FLOW_STEPS[state["flow_idx"]]            if prev_key == "pay_date_3" and state.get("payment_type") == "50/50":                state["flow_idx"] -= 1                prev_key = FLOW_STEPS[state["flow_idx"]]            await update.message.reply_text(QUESTIONS[prev_key])

Парсинг реквизитов

Менеджеры присылают реквизиты в произвольном виде: кто-то копирует из 1С, кто-то из мессенджера, кто-то копирует со скриншота с распознаванием текста. Парсер вытаскивает ИНН, ОГРН/ОГРНИП, КПП, расчётный и корреспондентский счета, БИК, email и адрес, автоматически определяя статус субъекта.

# requisites_parser.py (фрагмент)def parse_requisites(text: str) -> dict:    text = clean(text)    data = {"company_name": text.split("\n")[0].strip() if text else ""}    full_text = text        # ИНН (10 или 12 цифр)    m = re.search(r"(?i)ИНН\s*[:\-]?\s*(\d{10,12})", full_text)    data["inn"] = m.group(1) if m else ""        # ОГРН / ОГРНИП: определяем тип субъекта по длине числа    m_ogrn = re.search(r"(?i)ОГРН(?:ИП)?\s*[:\-]?\s*(\d{13,15})", full_text)    if m_ogrn:        ogrn_val = m_ogrn.group(1)        data["ogrn"] = ogrn_val        data["is_ip"] = len(ogrn_val) == 15  # 15 цифр = ИП, 13 = ООО    else:        # Резервный вариант: ищем "ИП" в названии компании        data["is_ip"] = "ИП " in data["company_name"].upper()    # ... дальнейший парсинг КПП, счетов, БИК, Email, Адреса    return data

Сейчас пользователю не нужно заполнять отдельные поля. Достаточно отправить текст с реквизитами в чат. Регулярные выражения покрывают ~95% случаев копипасты из различных источников.

Динамический расчёт платежей и НДС

В договорах часто меняются схемы оплаты и порядок оплат, ставки НДС и суммы. Логика полностью вынесена в Python, что исключает ошибки при ручном пересчёте в таблицах. Суммы прописью генерируются через num2words, НДС считается корректно в общей сумме контракта в зависимости от выбранной системы налогообложения.

Русская грамматика в преамбуле

Юридически корректная формулировка требует родительного падежа: в лице Генерального директора Иванова И.И.. Полноценная языковая модель здесь избыточна, поэтому я применил ручной подход: правила склонения + словари несклоняемых исключений.

def decline_fio(fio: str) -> str:    parts = fio.strip().split()    if len(parts) != 3: return fio    surname, name, patronymic = parts    is_female = patronymic.endswith(('вна', 'шна')) # надёжный маркер пола        # Склонение фамилии по правилам + исключения    if surname.endswith(("ова", "ева", "ина")): surname = surname[:-1] + "ой"    elif not is_female and surname[-1] not in "аеёиоуыэюя": surname += "а"    # ... аналогично для имени и отчества    return f"{surname} {name} {patronymic}"

Это покрывает ~90% кейсов. Для нестандартных имен оставлены резервные варианты, да и ручная правка текста в готовом файле остается рабочим вариантом.

Результаты

  • Время создания документа: ~5 мин диалога vs 15–30 минут ручного заполнения

  • Ошибки в реквизитах и расчетах сведены к минимуму благодаря автоматической проверке и формулам

  • Бот размещен в облаке, потребление памяти <128MB, холодный старт <3 сек

  • Бот работает в привычном мессенджере, не требует установки дополнительного ПО, доступен с телефона

Планы на развитие

  1. Переход на вебхук + базу данных для хранения истории сессий и аудита изменений.

  2. Проверка ИНН/ОГРН через открытые интерфейсы ФНС для мгновенной верификации контрагентов.

  3. Поддержка экспорта в форматы электронного документооборота.

  4. Поддержка разных валют и многоязычных шаблонов для внешних контрактов.

  5. Публикация исходного кода после финальной чистки конфигураций.

Заключение

Автоматизация юридических и коммерческих процессов не обязательно требует сложных корпоративных конструкторов. Связка Telegram + асинхронный Python + регулярные выражения + docxtpl дала мне быстрый, надежный и недорогой инструмент, которым менеджеры начинают пользоваться в первый же день. Код легко адаптируется под любой шаблонный договор: достаточно обновить .docx и скорректировать маппинг полей в логике диалога.

ссылка на оригинал статьи https://habr.com/ru/articles/1036960/