Перейти до вмісту

Технічне завдання: передача документів для звітності в податкову через Edin для Python

Матеріал з K2 ERP Wiki Ukraine — База знань з автоматизації та санкцій в Україні


SEO title: Технічне завдання: Передача документів для звітності в податкову через EDIN для Python SEO description: Технічне завдання на реалізацію Python-сервісу для передачі документів, податкових накладних, первинних документів та супровідних документів через EDIN / EDIN DocFlow / EDI Network з контролем статусів, підписанням, квитанціями, журналюванням та інтеграцією з K2 ERP. SEO keywords: Python, EDIN, EDIN API, EDIN DocFlow, EDI Network, електронний документообіг, податкова накладна, КЕП, електронні документи, K2 ERP, податкова звітність, технічне завдання Alternative to:



Головна ідея: розробити Python-сервіс, який інтегрує K2 ERP або іншу облікову систему з платформою EDIN для передачі електронних документів, податкових накладних, первинних документів, супровідних файлів та документів, пов'язаних із податковою звітністю.

Критично важливо: перед початком розробки потрібно підтвердити у EDIN, які саме типи документів можуть передаватись через API у конкретному акаунті: податкові накладні, первинні документи, структуровані документи DocFlow, EDI-документи, е-ТТН або саме податкова звітність до ДПС.

Важливо: EDIN не слід автоматично вважати універсальним каналом подання всіх декларацій до ДПС. Для класичної податкової звітності потрібно окремо перевіряти, чи підтримує EDIN потрібний сценарій передачі, підписання, отримання квитанцій та статусів.

Технічний стек: Python 3.11+, FastAPI, PostgreSQL, SQLAlchemy, Alembic, httpx, Pydantic, Celery/RQ/APScheduler, Redis, Docker.

Управлінський результат: керівник або бухгалтер повинен бачити, які документи сформовано, які підписано, які передано в EDIN, які прийнято, які відхилено, які очікують підпису або дії користувача.

1. Мета

Метою задачі є створення Python-сервісу для інтеграції з EDIN з метою передачі електронних документів, які використовуються у процесах податкового, бухгалтерського та юридично значущого документообігу.

Сервіс повинен забезпечити:

  • формування електронного документа у внутрішній системі;
  • валідацію документа перед передачею;
  • підготовку XML / JSON / PDF / XLSX / вкладень;
  • підписання КЕП або передачу документа на підписання;
  • відправку документа в EDIN;
  • отримання статусу документа;
  • отримання підтверджень, квитанцій або службових повідомлень, якщо доступні;
  • збереження ID документа EDIN;
  • збереження історії зміни статусів;
  • повторну передачу документа після технічної помилки;
  • захист від дублювання;
  • передачу статусу назад у K2 ERP;
  • формування dashboard для контролю.

2. Область застосування

Інтеграція може використовуватись для:

  • передачі податкових накладних;
  • передачі розрахунків коригування;
  • передачі первинних документів;
  • передачі актів, рахунків, видаткових накладних;
  • передачі структурованих документів через EDIN DocFlow;
  • передачі EDI-документів;
  • передачі е-ТТН, якщо використовується відповідний API EDIN;
  • передачі документів між контрагентами;
  • підготовки пакета документів, які потрібні бухгалтеру для податкової звітності;
  • контролю статусів підписання та доставки документів.

Важливо: якщо бізнес-процес передбачає саме подання декларацій до ДПС, потрібно окремо підтвердити, що EDIN API підтримує цей тип звітності. Якщо не підтримує — EDIN використовується для ЕДО та первинних документів, а податкова звітність подається через інший канал.

3. Джерела інтеграції

Компонент Призначення Коментар
EDIN Платформа електронного документообігу. Основний зовнішній сервіс.
EDIN DocFlow API API для роботи зі структурованими документами, компаніями, статусами та списками документів. Використовується, якщо підключено DocFlow.
EDIN EDI Network Платформа для EDI-документообігу з контрагентами. Використовується для ORDER, DESADV, INVOICE та інших EDI-документів.
EDIN Tax Invoice / Податкова накладна Сценарій роботи з електронною податковою накладною на платформі EDIN. Потрібно перевірити конкретний API та тип документа.
Python Integration Service Інтеграційний шар між K2 ERP та EDIN. Реалізується в межах цього ТЗ.
K2 ERP / ERP / CRM Джерело документів, контрагентів, статусів і задач. Внутрішня система замовника.

4. Передумови

Для реалізації задачі необхідно отримати:

  • акаунт EDIN;
  • доступ до EDIN API або EDIN DocFlow API;
  • тестове середовище або тестову компанію, якщо доступно;
  • логін / пароль або API token;
  • дані компанії-відправника;
  • дані контрагентів;
  • перелік типів документів, які потрібно передавати;
  • XML / JSON-специфікації документів;
  • правила підписання;
  • КЕП / ЕЦП або сценарій делегованого підписання;
  • вимоги до вкладень;
  • правила отримання статусів;
  • правила отримання квитанцій;
  • правила повторної відправки;
  • контакт технічної підтримки EDIN.

Критично важливо: без офіційної API-документації EDIN для конкретного продукту не можна фіксувати production endpoint-и, назви методів і формати payload як остаточні. У цьому ТЗ endpoint-и Python-сервісу є внутрішніми, а EDIN endpoint-и мають уточнюватись за документацією EDIN.

5. Варіанти інтеграції

5.1. Варіант 1. EDIN DocFlow API

Python-сервіс створює або передає структуровані документи через DocFlow API.

Параметр Опис
Підходить для Юридично значущих документів, актів, рахунків, договорів, первинних документів.
Переваги Робота зі статусами, компаніями, документами, структурованими даними.
Обмеження Потрібно перевірити доступність конкретних типів документів.
Основні операції Створення документа, редагування, зміна статусу, отримання списку документів.

5.2. Варіант 2. EDI Network API

Python-сервіс передає EDI-документи між компаніями та торговельними мережами.

Параметр Опис
Підходить для ORDER, ORDRSP, DESADV, INVOICE, COMDOC, e-ТТН та інших EDI-сценаріїв.
Переваги Стандартизований обмін документами з контрагентами.
Обмеження Документ залежить від схеми конкретної мережі або контрагента.
Основні операції Формування XML, передача, отримання статусу, отримання відповіді контрагента.

5.3. Варіант 3. Податкові накладні через EDIN

Python-сервіс формує або передає документи, пов'язані з електронною податковою накладною.

Параметр Опис
Підходить для Податкових накладних, розрахунків коригування, пов'язаних документів.
Переваги Можливість працювати з податковими документами в одному ЕДО-середовищі.
Обмеження Потрібно підтвердити формат API, підписання, статуси та квитанції.
Основні операції Підготовка документа, підписання, передача, статуси, квитанції.

5.4. Варіант 4. Гібридна схема

K2 ERP передає різні типи документів через різні API EDIN.

Тип документа Канал
Первинні документи EDIN DocFlow.
EDI-документи EDI Network.
Податкові накладні EDIN-сценарій податкових накладних, якщо доступний.
е-ТТН EDIN ETTN API, якщо підключено.
Податкові декларації Окремо підтверджується; за потреби використовується інший канал.

6. Основні сутності

Сутність Опис
Integration Account Обліковий запис інтеграції EDIN.
Organization Компанія-відправник або отримувач.
Counterparty Контрагент.
Document Type Тип документа: податкова накладна, акт, рахунок, EDI-документ тощо.
Document Внутрішній документ K2 ERP.
EDIN Document Документ, створений або переданий в EDIN.
Attachment Вкладення: PDF, XML, XLSX, скан, архів.
Signature Підпис КЕП / ЕЦП.
Status Статус документа в K2 ERP та EDIN.
Receipt / Confirmation Квитанція, підтвердження або службове повідомлення.
API Event Подія інтеграції.

7. User Story

7.1. Передача документа

Як бухгалтер, я хочу натиснути кнопку «Передати через EDIN», щоб документ із K2 ERP був сформований, перевірений, підписаний і переданий в EDIN.

7.2. Підписання

Як відповідальна особа, я хочу бачити документи, які очікують підпису, щоб підписати їх КЕП перед відправкою.

7.3. Контроль статусів

Як бухгалтер, я хочу бачити статус документа після відправки, щоб знати, чи документ прийнятий, відхилений, доставлений або очікує дії.

7.4. Повторна передача

Як адміністратор, я хочу повторити передачу після технічної помилки, щоб не створювати документ вручну повторно.

7.5. Dashboard керівника

Як керівник бухгалтерської компанії, я хочу бачити загальну картину по документах EDIN, щоб контролювати прострочені, відхилені, непідписані та проблемні документи.

8. Типи документів

8.1. Основні типи документів для MVP

Тип документа Код Формат Канал Важливість
Податкова накладна TAX_INVOICE XML / структурований документ EDIN Tax Invoice / DocFlow, якщо доступно Критична
Розрахунок коригування TAX_ADJUSTMENT XML / структурований документ EDIN Tax Invoice / DocFlow, якщо доступно Критична
Акт виконаних робіт ACT XML / PDF / структурований EDIN DocFlow Важлива
Рахунок INVOICE XML / PDF / структурований EDIN DocFlow / EDI Network Додаткова
Видаткова накладна EXPENSE_INVOICE XML / PDF / структурований EDIN DocFlow / EDI Network Важлива
ТТН / е-ТТН ETTN XML / структурований EDIN ETTN API, якщо підключено Важлива
Договір CONTRACT PDF / структурований EDIN DocFlow Додаткова
Довільний файл FILE PDF / XLSX / DOCX / ZIP EDIN DocFlow, якщо підтримується Супровідна

Критично важливо: для кожного типу документа потрібно окремо зберігати схему, канал передачі, правила підписання, допустимі вкладення та правила отримання статусу.

9. Статуси документів

Статус Код Опис Колір
Чернетка DRAFT Документ створено в K2 ERP, але ще не готовий до передачі. Сірий
Готовий до перевірки READY_FOR_REVIEW Документ сформований і очікує перевірки. Блакитний
Потребує виправлення NEEDS_CORRECTION Виявлено помилки у документі. Помаранчевий
Очікує підпису WAITING_SIGNATURE Документ готовий, але ще не підписаний. Жовтий
Підписано SIGNED Документ підписано КЕП. Зелений
Очікує відправки PENDING_SEND Документ у черзі передачі. Жовтий
Відправляється SENDING Виконується API-запит до EDIN. Блакитний
Передано в EDIN SENT_TO_EDIN Документ переданий у EDIN, очікується фінальний статус. Блакитний
Доставлено DELIVERED Документ доставлений отримувачу або системі. Зелений
Прийнято ACCEPTED Документ прийнятий. Зелений
Відхилено REJECTED Документ відхилено. Червоний
Помилка передачі SEND_ERROR Технічна помилка передачі. Червоний
Потребує повтору NEEDS_RETRY Документ можна передати повторно. Помаранчевий
Скасовано CANCELLED Документ скасовано користувачем. Сірий

10. Єдина логіка кольорів

Колір HTML Значення Де використовується
Зелений #c8e6c9 Успішно: підписано, доставлено, прийнято. Список документів, dashboard, картка документа.
Блакитний #bbdefb Документ у роботі або передається. Черга, статус API.
Жовтий #fff9c4 Очікування дії: підпис, відправка, перевірка. Черга підпису, календар задач.
Помаранчевий #ffcc80 Потрібна дія користувача або повтор. Помилки валідації, retry.
Червоний #ef9a9a Відхилено або критична помилка. Dashboard, проблемні документи.
Фіолетовий #f3e5f5 Спеціальний або індивідуальний документ. е-ТТН, нестандартні документи, ручні сценарії.
Сірий #eeeeee Чернетка, скасовано або не застосовується. Списки, архів.

11. Архітектура рішення

11.1. Загальна схема

K2 ERP / ERP / CRM
        |
        | 1. Формування документа
        v
Python EDIN Integration Service
        |
        | 2. Валідація, мапінг, підготовка файлів
        v
Signature Service / KEP Module
        |
        | 3. Підписання або передача на підпис
        v
Python EDIN Client
        |
        | 4. API EDIN / DocFlow / EDI Network
        v
EDIN
        |
        | 5. Доставка / обробка / статуси
        v
Python Status Sync Worker
        |
        | 6. Оновлення статусів
        v
K2 ERP / Dashboard / Задачі відповідальних

11.2. Основні компоненти Python-сервісу

Компонент Опис
API Layer REST API для прийому документів із K2 ERP.
Document Validator Перевіряє обов'язкові поля, суми, контрагентів, формати.
Document Mapper Перетворює документ K2 ERP у формат EDIN.
Signature Adapter Підписує документ або передає його на підписання.
EDIN Client Python-клієнт для API EDIN.
Document Queue Черга відправки документів.
Status Sync Worker Періодично синхронізує статуси з EDIN.
Receipt Collector Завантажує квитанції, підтвердження, службові повідомлення.
Audit Logger Зберігає всі дії, запити, відповіді та помилки.
Dashboard API Видає статистику по документах, статусах і помилках.

12. EDIN Client

12.1. Призначення

EDIN Client — це Python-клас або пакет, який інкапсулює роботу з EDIN API.

12.2. Основні методи

class EdinClient:
    def check_connection(self) -> "ConnectionStatus":
        pass

    def authenticate(self) -> "AuthResult":
        pass

    def refresh_token(self) -> "AuthResult":
        pass

    def create_document(self, payload: "EdinDocumentPayload") -> "EdinDocumentResponse":
        pass

    def update_document(self, edin_document_id: str, payload: "EdinDocumentPayload") -> "EdinDocumentResponse":
        pass

    def upload_attachment(self, edin_document_id: str, file: bytes, filename: str) -> "AttachmentResponse":
        pass

    def send_document(self, edin_document_id: str) -> "SendDocumentResponse":
        pass

    def get_document_status(self, edin_document_id: str) -> "DocumentStatusResponse":
        pass

    def get_document(self, edin_document_id: str) -> "EdinDocumentResponse":
        pass

    def get_document_list(self, filters: dict) -> "DocumentListResponse":
        pass

    def download_receipt(self, edin_document_id: str, receipt_id: str) -> bytes:
        pass

    def cancel_document(self, edin_document_id: str, reason: str) -> "CancelDocumentResponse":
        pass

Важливо: назви методів у Python-клієнті є внутрішньою абстракцією. Реальні EDIN API endpoint-и потрібно підставити з офіційної документації EDIN для конкретного продукту: DocFlow, EDI Network, ETTN або податкові накладні.

12.3. Конфігурація клієнта

from pydantic_settings import BaseSettings


class EdinSettings(BaseSettings):
    base_url: str
    auth_url: str | None = None
    api_login: str | None = None
    api_password: str | None = None
    api_token: str | None = None
    company_id: str
    integration_mode: str = "docflow"
    timeout_seconds: int = 30
    retry_count: int = 3
    retry_backoff_seconds: int = 5
    verify_ssl: bool = True

Приклад `.env`:

EDIN_BASE_URL=https://api.example.edin
EDIN_AUTH_URL=https://api.example.edin/auth
EDIN_API_LOGIN=********
EDIN_API_PASSWORD=********
EDIN_API_TOKEN=********
EDIN_COMPANY_ID=company-001
EDIN_INTEGRATION_MODE=docflow
EDIN_TIMEOUT_SECONDS=30
EDIN_RETRY_COUNT=3
EDIN_RETRY_BACKOFF_SECONDS=5

Заборонено: зберігати логін, пароль, API token, КЕП, пароль до КЕП або інші секрети у коді, Git-репозиторії, відкритих логах або frontend-змінних.

13. API Python-сервісу

13.1. Створення інтеграції

POST /api/v1/edin/integrations

13.2. Перевірка підключення

POST /api/v1/edin/integrations/{integration_id}/check-connection

13.3. Створення документа

POST /api/v1/edin/documents

13.4. Передача документа в EDIN

POST /api/v1/edin/documents/{document_id}/send

13.5. Підписання документа

POST /api/v1/edin/documents/{document_id}/sign

13.6. Завантаження вкладення

POST /api/v1/edin/documents/{document_id}/attachments

13.7. Синхронізація статусу

POST /api/v1/edin/documents/{document_id}/sync-status

13.8. Повторна відправка

POST /api/v1/edin/documents/{document_id}/retry

13.9. Отримання квитанцій

GET /api/v1/edin/documents/{document_id}/receipts

13.10. Dashboard

GET /api/v1/edin/dashboard?date_from=2026-05-01&date_to=2026-05-31

14. Приклад запиту на створення документа

{
  "external_document_id": "K2-TAX-INVOICE-2026-000123",
  "idempotency_key": "K2-TAX-INVOICE-2026-000123-v1",
  "document_type": "TAX_INVOICE",
  "organization_id": "org-001",
  "counterparty_id": "counterparty-001",
  "document_number": "123",
  "document_date": "2026-05-07",
  "currency": "UAH",
  "total_amount": 12000.00,
  "vat_amount": 2000.00,
  "payload_format": "xml",
  "payload": {
    "xml_file_id": "file-001"
  },
  "attachments": [
    {
      "filename": "tax_invoice_123.xml",
      "content_type": "application/xml",
      "file_id": "file-001"
    },
    {
      "filename": "tax_invoice_123.pdf",
      "content_type": "application/pdf",
      "file_id": "file-002"
    }
  ],
  "signing_required": true,
  "send_after_signing": true
}

15. Валідація документа

Перед відправкою система повинна перевірити:

  • наявність external_document_id;
  • наявність idempotency_key;
  • тип документа;
  • організацію-відправника;
  • контрагента;
  • ЄДРПОУ / ІПН / податковий номер сторін;
  • дату документа;
  • номер документа;
  • валюту;
  • суму;
  • ПДВ, якщо застосовується;
  • формат XML / JSON / PDF;
  • відповідність схемі документа;
  • наявність обов'язкових вкладень;
  • наявність КЕП або сценарію підписання;
  • чи не був документ уже відправлений;
  • чи дозволений повтор для поточного статусу.

Критично важливо: документ зі статусом ACCEPTED або DELIVERED не можна автоматично відправляти повторно. Повторна відправка дозволена тільки для технічних помилок або спеціальних статусів, визначених бізнес-правилами.

16. Підписання КЕП

16.1. Сценарії підписання

Сценарій Опис Коментар
Підписання в K2 ERP Документ підписується до передачі в EDIN. Потрібен модуль КЕП у K2 ERP.
Підписання в Python-сервісі Python-сервіс викликає внутрішній Signature Service. Потрібно безпечно зберігати ключі або використовувати HSM/хмарний КЕП.
Підписання в EDIN Документ передається в EDIN і підписується користувачем на платформі. Потрібно підтвердити підтримку цього сценарію для типу документа.
Делеговане підписання Підписує відповідальна особа після отримання задачі. Потрібен workflow задач.

16.2. Статуси підписання

Статус Код Колір Опис
Не потребує підпису SIGN_NOT_REQUIRED Сірий Документ не потребує КЕП.
Очікує підпису WAITING_SIGNATURE Жовтий Документ очікує підписання.
Підписується SIGNING Блакитний Виконується підписання.
Підписано SIGNED Зелений КЕП накладено.
Помилка підпису SIGN_ERROR Червоний Підписання не виконано.

17. Дедублікація

Система повинна не допускати дублювання документів.

Ключі дедублікації:

Ключ Призначення
external_document_id ID документа у K2 ERP.
idempotency_key Унікальний ключ конкретної версії відправки.
document_hash Hash XML/JSON/PDF документа.
document_number + document_date + organization_id + counterparty_id Бізнес-ключ документа.

Приклад hash:

sha256(document_type + document_number + document_date + total_amount + organization_tax_id + counterparty_tax_id)

18. Черга передачі

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

18.1. Логіка черги

1. K2 ERP створює документ.
2. Python-сервіс виконує валідацію.
3. Документ отримує статус READY_FOR_REVIEW або WAITING_SIGNATURE.
4. Після підпису документ переходить у PENDING_SEND.
5. Worker відправляє документ у EDIN.
6. EDIN повертає ID документа або технічну відповідь.
7. Python-сервіс зберігає EDIN ID.
8. Status Sync Worker періодично оновлює статус.
9. Квитанції та підтвердження зберігаються в картці документа.
10. K2 ERP отримує фінальний статус.

18.2. Пріоритети задач

Тип задачі Пріоритет Коментар
Податкова накладна Критичний Впливає на податковий облік.
Розрахунок коригування Критичний Впливає на ПДВ та реєстрацію.
Первинний документ Високий Важливий для бухгалтерії.
е-ТТН Високий Важливий для логістики.
Довільний файл Середній Супровідний документ.
Синхронізація статусів Середній Фоновий процес.
Завантаження квитанцій Середній Не блокує первинну відправку.

19. Модель даних

19.1. edin_integrations

Поле Тип Опис
id uuid ID інтеграції.
provider varchar edin.
integration_mode varchar docflow, edi_network, tax_invoice, ettn, hybrid.
name varchar Назва інтеграції.
base_url varchar URL API.
api_login_encrypted text Зашифрований логін.
api_password_encrypted text Зашифрований пароль.
api_token_encrypted text Зашифрований token.
company_id varchar ID компанії в EDIN.
is_active boolean Активність.
created_at timestamp Дата створення.
updated_at timestamp Дата оновлення.

19.2. edin_document_types

Поле Тип Опис
id uuid ID типу документа.
code varchar TAX_INVOICE, ACT, INVOICE, ETTN тощо.
name varchar Назва типу документа.
integration_mode varchar Через який канал передається.
payload_format varchar XML, JSON, PDF, mixed.
schema_version varchar Версія схеми.
requires_signature boolean Чи потрібен КЕП.
requires_attachments boolean Чи потрібні вкладення.
is_active boolean Активність.

19.3. edin_documents

Поле Тип Опис
id uuid Внутрішній ID документа.
integration_id uuid ID інтеграції.
document_type_id uuid Тип документа.
external_document_id varchar ID документа в K2 ERP.
edin_document_id varchar ID документа в EDIN.
idempotency_key varchar Ключ дедублікації.
document_number varchar Номер документа.
document_date date Дата документа.
organization_id uuid Організація-відправник.
counterparty_id uuid Контрагент.
status varchar Поточний статус.
signing_status varchar Статус підписання.
total_amount numeric Загальна сума.
vat_amount numeric Сума ПДВ.
payload_format varchar XML, JSON, PDF.
payload_hash varchar Hash документа.
raw_request jsonb Запит до EDIN.
raw_response jsonb Відповідь EDIN.
error_message text Остання помилка.
sent_at timestamp Дата передачі.
accepted_at timestamp Дата прийняття.
created_at timestamp Дата створення.

19.4. edin_attachments

Поле Тип Опис
id uuid ID вкладення.
document_id uuid ID документа.
filename varchar Назва файлу.
content_type varchar MIME type.
file_size integer Розмір файлу.
file_hash varchar Hash файлу.
storage_path varchar Шлях у сховищі.
edin_attachment_id varchar ID вкладення в EDIN.
created_at timestamp Дата створення.

19.5. edin_receipts

Поле Тип Опис
id uuid ID квитанції.
document_id uuid ID документа.
receipt_type varchar Квитанція, підтвердження, службове повідомлення.
external_receipt_id varchar ID квитанції в EDIN.
status varchar Статус квитанції.
received_at timestamp Дата отримання.
file_id uuid Файл квитанції.
raw_payload jsonb Дані квитанції.

19.6. edin_events

Поле Тип Опис
id uuid ID події.
document_id uuid ID документа.
event_type varchar Тип події.
old_status varchar Попередній статус.
new_status varchar Новий статус.
source varchar K2_ERP, PYTHON_SERVICE, EDIN, USER.
payload jsonb Технічні дані.
created_at timestamp Дата події.

20. Приклад Python-логіки

20.1. Створення документа

from datetime import datetime, timezone


def create_edin_document(command: "CreateEdinDocumentCommand", db: "Session") -> "EdinDocument":
    existing = edin_document_repository.get_by_idempotency_key(
        db=db,
        idempotency_key=command.idempotency_key,
    )

    if existing:
        return existing

    document_validator.validate(command)

    payload_hash = document_hash_service.calculate(command.payload)

    document = edin_document_repository.create(
        db=db,
        data={
            "external_document_id": command.external_document_id,
            "idempotency_key": command.idempotency_key,
            "document_number": command.document_number,
            "document_date": command.document_date,
            "document_type_id": command.document_type_id,
            "organization_id": command.organization_id,
            "counterparty_id": command.counterparty_id,
            "status": "DRAFT",
            "signing_status": "WAITING_SIGNATURE" if command.signing_required else "SIGN_NOT_REQUIRED",
            "total_amount": command.total_amount,
            "vat_amount": command.vat_amount,
            "payload_format": command.payload_format,
            "payload_hash": payload_hash,
            "raw_request": command.model_dump(),
        },
    )

    audit_logger.log(
        document_id=document.id,
        event_type="DOCUMENT_CREATED",
        new_status=document.status,
        payload={"external_document_id": command.external_document_id},
    )

    db.commit()
    return document

20.2. Відправка документа

def send_edin_document(document_id: str, db: "Session") -> None:
    document = edin_document_repository.get_by_id(db, document_id)

    if document.status in ["ACCEPTED", "DELIVERED"]:
        return

    if document.signing_status == "WAITING_SIGNATURE":
        raise BusinessError("Document must be signed before sending")

    try:
        document.status = "SENDING"
        db.commit()

        payload = edin_mapper.to_edin_payload(document)

        response = edin_client.create_document(payload)

        document.edin_document_id = response.document_id
        document.raw_response = response.raw_payload
        document.status = "SENT_TO_EDIN"
        document.sent_at = datetime.now(timezone.utc)

        audit_logger.log(
            document_id=document.id,
            event_type="DOCUMENT_SENT_TO_EDIN",
            old_status="SENDING",
            new_status="SENT_TO_EDIN",
            payload={"edin_document_id": response.document_id},
        )

    except TemporaryEdinError as exc:
        document.status = "NEEDS_RETRY"
        document.error_message = str(exc)

    except Exception as exc:
        document.status = "SEND_ERROR"
        document.error_message = str(exc)

    finally:
        db.commit()

20.3. Синхронізація статусів

def sync_edin_document_status(document_id: str, db: "Session") -> None:
    document = edin_document_repository.get_by_id(db, document_id)

    if not document.edin_document_id:
        return

    status_response = edin_client.get_document_status(document.edin_document_id)

    old_status = document.status
    new_status = status_mapper.from_edin(status_response.status)

    if old_status != new_status:
        document.status = new_status

        if new_status == "ACCEPTED":
            document.accepted_at = datetime.now(timezone.utc)

        audit_logger.log(
            document_id=document.id,
            event_type="DOCUMENT_STATUS_SYNCED",
            old_status=old_status,
            new_status=new_status,
            payload=status_response.raw_payload,
        )

    db.commit()

21. Обробка помилок

21.1. Типи помилок

Тип помилки Опис Дія системи
ValidationError Некоректні дані документа. Не відправляти документ, показати список помилок.
AuthError Невірні облікові дані EDIN. Зупинити інтеграцію, повідомити адміністратора.
SignatureError Помилка підписання. Перевести в SIGN_ERROR.
SchemaError Документ не відповідає XML/JSON-схемі. Перевести в NEEDS_CORRECTION.
CounterpartyError Контрагент не знайдений або не має потрібного ідентифікатора. Перевести в NEEDS_CORRECTION.
SendError API EDIN повернув помилку. Зберегти raw-відповідь.
TimeoutError Перевищено час очікування. Перевести в NEEDS_RETRY.
DuplicateDocumentError Документ уже існує. Повернути існуючий документ.
ReceiptError Помилка отримання квитанції. Не змінювати фінальний статус без перевірки.

21.2. Retry-логіка

Retry дозволений для:

  • timeout;
  • HTTP 429;
  • HTTP 500;
  • HTTP 502;
  • HTTP 503;
  • HTTP 504;
  • тимчасової недоступності EDIN;
  • тимчасової помилки отримання статусу;
  • тимчасової помилки завантаження квитанції.

Retry заборонений для:

  • помилок валідації;
  • неправильного логіна / пароля / token;
  • помилки КЕП;
  • невідповідності схемі документа;
  • документа, який уже прийнято;
  • документа, який явно відхилено через бізнес-помилки.

22. Dashboard керівника

22.1. Основні KPI

KPI Опис Колір
Документів створено Загальна кількість документів за період. Інформація
Очікують підпису Документи без підпису. Увага
Передано в EDIN Документи, які вже відправлені. В роботі
Прийнято Успішно прийняті документи. Норма
Відхилено Документи з негативним статусом. Критично
Потребують повтору Технічні помилки, які можна повторити. Потрібна дія
Без квитанції Документи без підтвердження. Контроль

22.2. Приклад dashboard

Показник Значення Стан
Документів за місяць 1840 Інформація
Очікують підпису 43 Увага
Передано в EDIN 1290 В роботі
Прийнято 1218 Норма
Відхилено 12 Критично
Потребують повтору 18 Потрібна дія

22.3. Проблемні документи

Дата Документ Організація Контрагент Статус Помилка Дія
07.05.2026 Податкова накладна №123 ТОВ «Альфа» ТОВ «Бета» Відхилено Помилка схеми XML Виправити
07.05.2026 Акт №45 ТОВ «Альфа» ТОВ «Гамма» Очікує підпису Немає КЕП відповідального Підписати
07.05.2026 е-ТТН №77 ТОВ «Логістика» ТОВ «Покупець» Потребує повтору Timeout EDIN API Повторити

23. Безпека

Система повинна забезпечити:

  • зберігання EDIN credentials тільки у secret storage або в зашифрованому вигляді;
  • заборону логування паролів, token, ключів КЕП;
  • маскування персональних даних;
  • HTTPS для всіх API-запитів;
  • перевірку SSL;
  • рольову модель доступу;
  • окремі права на підписання;
  • окремі права на повторну відправку;
  • окремі права на скасування документа;
  • журнал усіх дій;
  • захист від дублювання документів;
  • контроль доступу до вкладень;
  • обмеження розміру файлів;
  • антивірусну перевірку вкладень, якщо потрібно.

24. Логування та аудит

Система повинна логувати:

Подія Що зберігати
Створення документа Тип, номер, дата, організація, контрагент.
Валідація Результат, список помилок.
Підписання Хто підписав, коли, результат.
Відправка в EDIN Час, endpoint, request_id, EDIN document ID.
Отримання статусу Старий статус, новий статус, джерело.
Отримання квитанції Тип квитанції, час, файл.
Помилка передачі Код, повідомлення, raw-відповідь.
Повторна відправка Хто запустив, причина, результат.
Скасування Хто скасував, причина.

25. Acceptance Criteria

25.1. Інтеграція

Критерій Очікуваний результат
AC-1 Адміністратор створює інтеграцію EDIN. Інтеграція зберігається в системі.
AC-2 Адміністратор перевіряє підключення. Система повертає успішний або помилковий статус.
AC-3 Облікові дані неправильні. Система показує AuthError і не відправляє документи.

25.2. Документи

Критерій Очікуваний результат
AC-4 K2 ERP створює документ. Python-сервіс створює запис зі статусом DRAFT.
AC-5 Документ проходить валідацію. Статус змінюється на READY_FOR_REVIEW або WAITING_SIGNATURE.
AC-6 Документ потребує підпису. Без підпису він не відправляється.
AC-7 Документ підписано. Статус підписання змінюється на SIGNED.
AC-8 Документ відправлено в EDIN. Зберігається EDIN document ID.

25.3. Статуси та квитанції

Критерій Очікуваний результат
AC-9 EDIN повертає новий статус. Python-сервіс оновлює статус у K2 ERP.
AC-10 EDIN повертає квитанцію. Квитанція зберігається в картці документа.
AC-11 Документ відхилено. Статус підсвічується червоним.
AC-12 Документ прийнято. Статус підсвічується зеленим.

25.4. Дедублікація та повтор

Критерій Очікуваний результат
AC-13 Повторний запит має той самий idempotency_key. Другий документ не створюється.
AC-14 EDIN API тимчасово недоступний. Документ переходить у NEEDS_RETRY.
AC-15 Користувач запускає retry. Система повторює передачу без дублювання.
AC-16 Документ уже прийнятий. Повторна відправка блокується.

25.5. Dashboard

Критерій Очікуваний результат
AC-17 Керівник відкриває dashboard. Він бачить кількість створених, підписаних, відправлених, прийнятих і відхилених документів.
AC-18 Є відхилені документи. Вони підсвічуються червоним.
AC-19 Є документи без підпису. Вони підсвічуються жовтим.
AC-20 Є документи, що потребують повтору. Вони підсвічуються помаранчевим.

26. MVP

До MVP входить:

  • створення інтеграції EDIN;
  • перевірка підключення;
  • довідник типів документів;
  • створення документа;
  • валідація документа;
  • завантаження вкладень;
  • базовий сценарій підписання або статус «очікує підпису»;
  • передача документа в EDIN;
  • збереження EDIN document ID;
  • синхронізація статусу;
  • отримання квитанцій, якщо доступно через API;
  • дедублікація;
  • retry-механізм;
  • журнал подій;
  • dashboard API;
  • базові unit-тести;
  • mock EDIN API для інтеграційних тестів.

До MVP не входить:

  • автоматичне подання всіх декларацій до ДПС без підтвердження EDIN API;
  • повна підтримка всіх документів EDIN;
  • повна підтримка всіх EDI-мереж;
  • повна підтримка е-ТТН, якщо не підключено ETTN API;
  • власний модуль КЕП без окремого ТЗ;
  • складний UI підписання;
  • автоматичне виправлення XML-помилок;
  • юридична перевірка змісту документа.

27. Етапи реалізації

Етап 1. Аналіз EDIN API

  • отримати офіційну документацію EDIN;
  • визначити продукт: DocFlow, EDI Network, Tax Invoice, ETTN або гібрид;
  • визначити авторизацію;
  • визначити формати документів;
  • визначити статуси;
  • визначити правила підписання;
  • визначити квитанції та підтвердження.

Етап 2. Базовий Python-сервіс

  • створити FastAPI-проєкт;
  • налаштувати PostgreSQL;
  • створити моделі інтеграції, документів, вкладень, подій;
  • налаштувати Alembic;
  • реалізувати healthcheck.

Етап 3. EDIN Client

  • реалізувати авторизацію;
  • реалізувати check_connection;
  • реалізувати create_document;
  • реалізувати upload_attachment;
  • реалізувати send_document;
  • реалізувати get_document_status;
  • реалізувати get_document_list;
  • реалізувати download_receipt;
  • реалізувати обробку помилок.

Етап 4. Документи та валідація

  • реалізувати створення документа;
  • реалізувати мапінг K2 ERP → EDIN;
  • реалізувати валідацію;
  • реалізувати hash документа;
  • реалізувати дедублікацію.

Етап 5. Підписання

  • реалізувати сценарій WAITING_SIGNATURE;
  • реалізувати інтеграцію з Signature Service, якщо є;
  • реалізувати перевірку підпису;
  • реалізувати журнал підписання.

Етап 6. Черга та статуси

  • реалізувати чергу передачі;
  • реалізувати worker відправки;
  • реалізувати worker синхронізації статусів;
  • реалізувати retry;
  • реалізувати збереження квитанцій.

Етап 7. Dashboard та аудит

  • реалізувати dashboard API;
  • реалізувати список проблемних документів;
  • реалізувати фільтри;
  • реалізувати експорт, якщо потрібно.

Етап 8. Production hardening

  • додати rate limiting;
  • додати моніторинг;
  • додати alerting;
  • додати dead letter queue;
  • додати резервне копіювання;
  • додати безпечне зберігання секретів.

28. Ризики

Ризик Опис Як зменшити
EDIN не підтримує потрібний тип звітності Не всі податкові декларації можуть бути доступні через EDIN. Підтвердити API та типи документів до розробки.
Неправильний формат XML Документ може бути відхилено. Валідація за схемою до відправки.
Помилка КЕП Документ не буде підписано. Окремий статус SIGN_ERROR і журнал підписання.
Дублювання документів Повторний запит може створити дубль. Idempotency key і document_hash.
Невідомий статус EDIN може повернути статус, якого немає в мапінгу. Таблиця status_mapping і статус UNKNOWN.
Немає квитанції Документ передано, але підтвердження не отримано. Фоновий retry отримання квитанцій.
Зміна API EDIN може змінити API або схему. Версіонування клієнта і contract-тести.

29. Відкриті питання

  1. Який саме продукт EDIN використовується: DocFlow, EDI Network, Tax Invoice, ETTN чи гібрид?
  2. Чи підтримує EDIN потрібний тип податкової звітності?
  3. Які типи документів потрібно передавати в MVP?
  4. Чи потрібне підписання в K2 ERP, Python-сервісі або на стороні EDIN?
  5. Чи потрібно зберігати КЕП у системі?
  6. Чи потрібна інтеграція з хмарним КЕП?
  7. Які формати документів використовуються: XML, JSON, PDF, XLSX?
  8. Чи потрібна валідація XML за XSD?
  9. Чи потрібно отримувати квитанції автоматично?
  10. Як часто синхронізувати статуси?
  11. Чи потрібно надсилати документи пакетно?
  12. Чи потрібно підтримувати декілька юридичних осіб?
  13. Чи потрібно підтримувати декілька акаунтів EDIN?
  14. Чи потрібен UI для підписання?
  15. Чи потрібен dashboard у K2 ERP?
  16. Чи потрібно експортувати журнал передачі в Excel?

30. Джерела

31. Див. також