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

Страницы:  1

Ответить
 

Professor Seleznov


Коммерческие отделы ежедневно тратят много времени на ручное создание однотипных документов: копирование реквизитов из переписки, подстановка ФИО в нужном падеже, расчет графиков платежей, НДС и сумм прописью. Одна пропущенная цифра в ИНН или ошибка в склонении должности, и договор возвращается на доработку, а это задержка сделки.
В этой статье я покажу как собрал на 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 сек
  • Бот работает в привычном мессенджере, не требует установки дополнительного ПО, доступен с телефона
Планы на развитие
  • Переход на вебхук + базу данных для хранения истории сессий и аудита изменений.
  • Проверка ИНН/ОГРН через открытые интерфейсы ФНС для мгновенной верификации контрагентов.
  • Поддержка экспорта в форматы электронного документооборота.
  • Поддержка разных валют и многоязычных шаблонов для внешних контрактов.
  • Публикация исходного кода после финальной чистки конфигураций.
Заключение
Автоматизация юридических и коммерческих процессов не обязательно требует сложных корпоративных конструкторов. Связка Telegram + асинхронный Python + регулярные выражения + docxtpl дала мне быстрый, надежный и недорогой инструмент, которым менеджеры начинают пользоваться в первый же день. Код легко адаптируется под любой шаблонный договор: достаточно обновить .docx и скорректировать маппинг полей в логике диалога.-Источник
 
Loading...
Error