Files
contracts/history/architecture.md
T

5.8 KiB

Архитектура Contracts App

Обзор

Сервис Сверка договоров — автоматизированная обработка договоров и допников (docx/pdf) с извлечением структурированных данных, отслеживанием изменений и восстановлением истории договора во времени.

Принципы

  1. НЕ МОНОЛИТ — каждый слой независим, отдельный файл, своя зона ответственности
  2. Данные не покидают облако — всё в PostgreSQL внутри кластера
  3. Ничего не терять — парсер отдаёт полный слепок документа, LLM решает что важно
  4. Исключения — не фантазировать — нерешаемые подзадачи отмечать явно

Слои приложения

┌─────────────────────────────────────────────┐
│                    app.py                    │
│           ContractsApp (сборка)              │
├──────────┬──────────┬──────────┬────────────┤
│  db.py   │ parser.py│ test_     │ (будущие) │
│  (БД)    │ (парсинг)│ routes.py │  llm.py   │
│          │          │ (/test)   │  upload.py│
└──────────┴──────────┴──────────┴────────────┘
Слой Файл Что делает Статус
Ядро app.py Flask-приложение, инициализация, регистрация Blueprint
БД db.py connect(), query(), _pg_connect()
Тесты test_routes.py Blueprint /test — мост к БД извне
Парсер parser.py parse(bytes, mime) → elements для docx/pdf/doc/zip
LLM llm.py Нормализация строк через aillm.ru (120B)
Загрузка upload.py Приём файлов, сохранение в БД

Поток обработки документа

Пользователь
    │
    ▼
POST /upload (файл .docx/.pdf/.doc/.zip)
    │
    ▼
upload.py: сохранить в contract_docs (original_bytes)
    │
    ▼
parser.py: parse(bytes, mime) → elements JSON
    │
    ▼
db.py: сохранить parsed_json в contract_docs
    │
    ▼
llm.py: отправить elements → LLM → нормализованные spec_rows
    │
    ▼
db.py: сохранить в spec_rows, сравнить с предыдущими → spec_history
    │
    ▼
GET /contract/{id}/history → полная история изменений

Схема БД (план)

contract_docs               — исходные файлы + сырой парсинг
  id UUID PK
  contract_id → contracts.id
  filename TEXT
  mime_type TEXT
  original_bytes BYTEA       ← сам файл
  parsed_json JSONB          ← выдача parser.py
  created_at TIMESTAMPTZ

contracts                    — договоры
  id UUID PK
  number TEXT                ← номер договора
  client TEXT                ← клиент
  date DATE
  status TEXT

supplements                  — допники
  id UUID PK
  contract_id → contracts.id
  number TEXT
  date DATE
  type TEXT                  ← новый / изменение / расторжение
  doc_id → contract_docs.id

spec_rows                    — строки спецификаций
  id UUID PK
  supplement_id → supplements.id
  row_num INT
  name TEXT                  ← наименование услуги
  price NUMERIC
  qty NUMERIC
  sum NUMERIC
  date_start DATE
  date_end DATE

spec_history                 — история изменений
  id UUID PK
  spec_row_id → spec_rows.id
  supplement_id → supplements.id
  change_type TEXT           ← added / changed / deleted / unchanged
  old_values JSONB
  new_values JSONB

API эндпоинты

Метод Путь Слой Что
GET / app.py Главная (HTML)
GET /health app.py Health check → "OK"
GET /test test_routes Статус БД + список команд
POST /test {"action":"status"} test_routes Статус БД
POST /test {"action":"createdb"} test_routes Создать БД contracts
POST /test {"action":"tables"} test_routes Список таблиц
POST /test {"action":"sql","sql":"..."} test_routes Произвольный SQL

Технологии

Компонент Выбор
Язык Python 3.12
Фреймворк Flask
БД PostgreSQL (внутрикластерный)
Парсинг docx python-docx
Парсинг .doc LibreOffice (headless)
Парсинг PDF pdfplumber
LLM aillm.ru API (120B модель)
Деплой pythonk8s.services.ngcloud.ru
Репозиторий gitea.services.ngcloud.ru/Nail/contracts-app.git

Конфигурация (переменные окружения)

Переменная Назначение
DB_HOST Хост PostgreSQL
DB_PORT Порт (5432)
DB_NAME Имя БД (contracts)
DB_USER Пользователь
DB_PASS Пароль
DB_SSLMODE SSL mode (disable)
LLM_API_KEY Ключ aillm.ru (будет)
LLM_API_URL URL LLM API (будет)