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

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

Матеріал з K2 ERP Wiki
щоб контролювати прострочені, відхилені, непідписані та проблемні документи.; # Чи підтримує роботу EDIN потрібний тип податкової звітності?; |-
document_hash - Первинні документи - Податкові накладні EDIN-сценарій податкових накладних, якщо доступний.; Тип документа
def get_document_list(self, filters: dict) -> "DocumentListResponse":
pass

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

Податкова накладна 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, якщо підтримується Супровідна
document.edin_document_id = response.document_id
base_url: str
}

!; |- | Audit Logger | Зберігає всі дії, запити, відповіді та помилки.; |- | receipt_type | varchar | Квитанція, підтвердження, службове повідомлення.; істотно: назви методів у Python-клієнті є собою внутрішньою абстракцією.; Ризик

платформа повинна логувати: !; |- | EDIN Client | Python-клієнт для API EDIN.; Тип

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

except TemporaryEdinError as exc:
{
pass

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

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

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

2.; |- | AC-10 | EDIN повертає квитанцію.; |- | idempotency_key | Унікальний ключ конкретної версії відправки.; |}

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

я хочу бачити документи, які очікують підпису, 6.; |- | schema_version | varchar | реліз схеми.; № class EdinClient:

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

19.5. edin_receipts

|- | AC-9 | EDIN повертає новий статус.; |- | TimeoutError | Перевищено час очікування.; Очікуваний результат

19.3. edin_documents

)

EDIN_RETRY_COUNT=3

EDIN_TIMEOUT_SECONDS=30

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

- raw_payload jsonb - integration_id uuid - Невідомий статус EDIN має змогу повернути статус, якого немає в мапінгу.; Приклад hash: ; Колір
  • timeout;
  • HTTP 429;
  • HTTP 500;
  • HTTP 502;
  • HTTP 503;
  • HTTP 504;
  • тимчасової недоступності EDIN;
  • тимчасової помилки отримання статусу;
  • тимчасової помилки завантаження квитанції.; # Які формати документів використовуються: XML, JSON, PDF, XLSX?; |-
AC-20 - Dashboard API Видає статистику по документах, статусах і помилках.; Організація
Підходить для - Помилка передачі - Attachment Список документів, dashboard, картка документа.; |} },
  • акаунт EDIN;
  • доступ до EDIN API або EDIN DocFlow API;
  • тестове середовище або тестову компанію, якщо доступно;
  • логін / пароль або API token;
  • інформаційні дані компанії-відправника;
  • інформаційні дані контрагентів;
  • перелік типів документів, які потрібно передавати;
  • XML / JSON-специфікації документів;
  • правила підписання;
  • КЕП / ЕЦП або сценарій делегованого підписання;
  • вимоги до вкладень;
  • правила отримання статусів;
  • правила отримання квитанцій;
  • правила повторної відправки;
  • контакт технічної підтримки EDIN.; KPI
def sync_edin_document_status(document_id: str, db: "Session") -> None:
K2 ERP передає різні типи документів через різні API EDIN.; |-
file_size integer - status varchar - Document Queue - Підписано SIGNED Зелений - AC-12 - document_id uuid - CounterpartyError Він бачить кількість створених, підписаних, відправлених, прийнятих і відхилених документів.; |- Основні операції Підготовка документа, підписання, передача, статуси, квитанції.; v
  • реалізувати сценарій WAITING_SIGNATURE;
  • реалізувати інтеграцію з Signature Service, якщо є собою;
  • реалізувати перевірку підпису;
  • реалізувати журнал підписання.; | Зберігається EDIN document ID.; |-
Document Type style="background:#eeeeee;" | Сірий
Готовий до перевірки READY_FOR_REVIEW Документ сформований і очікує перевірки.; характеристика е-ТТН, нестандартні документи, ручні сценарії.; |- Signature Підпис КЕП / ЕЦП.; Поле
id uuid - file_id uuid - status varchar - Дублювання документів } ; from pydantic_settings import BaseSettings
document = edin_document_repository.create(
document.status = "SENDING"
EDIN не підтримує роботу потрібний тип звітності - Завантаження квитанцій Середній Не блокує первинну відправку.;== 28.; Ризики ==
document.status = "NEEDS_RETRY"
integration_mode: str = "docflow"

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

document_type_id uuid Тип документа.; * створення інтеграції EDIN;
  • перевірка підключення;
  • довідник типів документів;
  • створення документа;
  • валідація документа;
  • завантаження вкладень;
  • базовий сценарій підписання або статус «очікує підпису»;
  • передача документа в EDIN;
  • збереження EDIN document ID;
  • синхронізація статусу;
  • отримання квитанцій, якщо доступно через API;
  • дедублікація;
  • retry-механізм;
  • журнал подій;
  • dashboard API;
  • базові unit-тести;
  • mock EDIN API для інтеграційних тестів.; |-
company_id varchar ID компанії в EDIN.; EDIN повертає ID документа або технічну відповідь.; характеристика
  • реалізувати dashboard API;
  • реалізувати список проблемних документів;
  • реалізувати фільтри;
  • реалізувати експорт, якщо потрібно.; | style="background:#bbdefb;" | Блакитний
Потребує виправлення NEEDS_CORRECTION }

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

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

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

id uuid - external_receipt_id varchar Повторна відправка блокується.; |- received_at timestamp Дата отримання.; Коментар

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

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

; Компонент style="background:#e3f2fd;" | відомості
Очікують підпису Документи без підпису.; Колір

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

counterparty_id uuid Контрагент.; характеристика

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

style="background:#bbdefb;" | Блакитний
Доставлено DELIVERED Документ доставлений отримувачу або системі.; Доставка / обробка / статуси

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

- K2 ERP / ERP / CRM - AC-7 Потрібно перевірити конкретний API та тип документа.; |- EDIN Tax Invoice / Податкова накладна платформа показує AuthError і не відправляє документи.; |- name varchar Назва інтеграції.; Signature Service / KEP Module
  • додати rate limiting;
  • додати моніторинг;
  • додати alerting;
  • додати dead letter queue;
  • додати резервне копіювання;
  • додати безпечне зберігання секретів.; |}

щоб підписати їх КЕП перед відправкою.; # Чи потрібна інтеграційні функціональні можливості з хмарним КЕП?; |-

api_token_encrypted text - Organization Статус підписання змінюється на SIGNED.; "organization_id": command.organization_id,

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

- Податкові декларації Окремо підтверджується; за потреби застосовують, коли потрібно інший канал.; Показник

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

Як бухгалтер,

Як адміністратор,

document.status = "SENT_TO_EDIN"

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

}
old_status="SENDING",

EDIN_COMPANY_ID=company-001

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

Статус підсвічується зеленим.; Дія
"attachments": [ def get_document_status(self, edin_document_id: str) -> "DocumentStatusResponse": До MVP входить: Критично істотно: для кожного типу документа потрібно окремо зберігати схему, канал передачі, правила підписання, допустимі вкладення та правила отримання статусу.; |-
document_number + document_date + organization_id + counterparty_id - requires_signature boolean style="background:#ffcc80;" | Помаранчевий
Скасовано CANCELLED Документ скасовано користувачем.; Очікуваний результат

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

Документів створено Загальна кількість документів за період.; №

платформа повинна не допускати дублювання документів.; | style="background:#fff9c4;" | Жовтий

Відправляється SENDING Виконується API-запит до EDIN.; Тип Вони підсвічуються червоним.; |- Отримання статусу - created_at timestamp Дата створення.; характеристика

25. Acceptance Criteria

}
  1. Який саме програмний продукт EDIN застосовується: DocFlow, EDI Network, Tax Invoice, ETTN чи гібрид?; | style="background:#c8e6c9;" | Зелений
Очікує відправки PENDING_SEND Документ у черзі передачі.; Коментар ; характеристика

Python-сервіс створює або передає структуровані документи через DocFlow API.; K2 ERP отримує фінальний статус.; характеристика

document_validator.validate(command)
; Очікуваний результат

</syntaxhighlight>

[[Категорія:Python]]
=== 8.1.; Основні типи документів для MVP ===
== 24.; Логування та аудит ==
</pre>
<pre>
!; |-
| total_amount
| numeric
| Загальна сума.; |-
| style="background:#fff9c4;" | Жовтий
| #fff9c4
| Очікування дії: підпис, відправка, перевірка.; {| class="wikitable"

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

== 16.; Підписання КЕП ==
 "idempotency_key": "K2-TAX-INVOICE-2026-000123-v1",
!; |-
| Python Integration Service
| Інтеграційний шар між K2 ERP та EDIN.; |}

'''істотно:''' EDIN не слід автономно вважати універсальним каналом подання всіх декларацій до ДПС.; |-
| name
| varchar
| Назва типу документа.; |-
| SignatureError
| Помилка підписання.; |-
| Неправильний формат XML
| Документ має змогу бути відхилено.; | Валідація за схемою до відправки.; K2 ERP створює документ.; Тип
=== 11.2.; Основні компоненти Python-сервісу ===
 db=db,
|-
| id
| uuid
| ID вкладення.; EDIN застосовується для ЕДО та первинних документів, а податкова формування звітів подається через інший канал виступає ключовою рисою '''істотно:''' якщо бізнес-процес передбачає саме подання декларацій до ДПС, потрібно окремо підтвердити, що EDIN API підтримує роботу цей тип звітності.; |}

<pre>

 "filename": "tax_invoice_123.pdf",

'''Заборонено:''' зберігати логін, пароль, API token, КЕП, пароль до КЕП або інші секрети у коді, Git-репозиторії, відкритих логах або frontend-змінних.; |-
| AC-16
| Документ уже прийнятий.; характеристика

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

=== 19.4. edin_attachments ===
</pre>
 |
 | 1.; Реальні EDIN API endpoint-и потрібно підставити з офіційної документації EDIN для конкретного продукту: DocFlow, EDI Network, ETTN або податкові накладні.; 

!; Тип

!; |-
| style="background:#ef9a9a;" | Червоний
| #ef9a9a
| Відхилено або критична помилка.; | style="background:#ef9a9a;" | Критично
|-
| Потребують повтору
| Технічні помилки, які можна повторити.; Формування документа
!; |}

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

!; |-
| edin_attachment_id
| varchar
| ID вкладення в EDIN.; |-
| Signature Adapter
| Підписує документ або передає його на підписання.; document_id=document.id,

=== Етап 3.; EDIN Client ===
=== 22.3.; Проблемні документи ===

щоб документ із K2 ERP був сформований, перевірений, підписаний і переданий в EDIN.; # Які типи документів потрібно передавати в MVP?; | Документ переходить у NEEDS_RETRY.; return existing
 old_status=old_status,

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

 new_status=new_status,
7.; Стан
!; характеристика

!; |-
| SendError
| API EDIN повернув помилку.; # Чи потрібен dashboard у K2 ERP?; pass

 "status": "DRAFT",
}
 "vat_amount": 2000.00,

!; |-
| Валідація
| Результат, список помилок.; |-
| Document
| Внутрішній документ K2 ERP.; Пріоритет

{| class="wikitable"
 "send_after_signing": true
 try:
 api_password: str | None = None
 pass
 pass

=== Етап 5.; Підписання ===
 v
 db=db,

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

 "document_date": "2026-05-07",
!; |-
| storage_path
| varchar
| Шлях у сховищі.; |-
| new_status
| varchar
| Новий статус.; Статус
 {

== 1.; Мета ==

 if old_status != new_status:
 if existing:
!; |-
| Підписання
| Хто підписав, коли, результат.;=== 13.1.; Створення інтеграції ===
 "total_amount": command.total_amount,
 "currency": "UAH",
!; | Повернути існуючий документ.; Значення
 )
=== 22.2.; Приклад dashboard ===
|-
| Створення документа
| Тип, номер, дата, організація, контрагент.; | style="background:#ef9a9a;" | Червоний
|-
| Потребує повтору
| NEEDS_RETRY
| Документ можна передати повторно.; |-
| code
| varchar
| TAX_INVOICE, ACT, INVOICE, ETTN тощо.; | style="background:#ef9a9a;" | Червоний
|-
| Помилка передачі
| SEND_ERROR
| Технічна помилка передачі.; Критерій
!; | Вони підсвічуються помаранчевим.; | style="background:#c8e6c9;" | Зелений
|-
| Прийнято
| ACCEPTED
| Документ прийнятий.; |-
| raw_request
| jsonb
| Запит до EDIN.; |-
| AC-3
| Облікові інформаційні дані неправильні.; | платформа повертає успішний або помилковий статус.; |-
| EDI-документи
| EDI Network.; | Не відправляти документ, показати список помилок.; |-
| ReceiptError
| Помилка отримання квитанції.; |-
| sent_at
| timestamp
| Дата передачі.; |-
| Receipt Collector
| Завантажує квитанції, підтвердження, службові повідомлення.; |-
| AC-5
| Документ проходить валідацію.; Тип задачі

 verify_ssl: bool = True
== 7. User Story ==

'''Критично істотно:''' без офіційної API-документації EDIN для конкретного продукту не можна фіксувати production endpoint-и, назви методів і формати payload як остаточні.; Статус

!; Окремо варто відзначити який інтегрує K2 ERP або іншу облікову систему з платформою EDIN; додатково реалізовано податкових накладних, первинних документів, супровідних файлів і документів, пов'язаних із податковою звітністю.; Валідація, мапінг, підготовка файлів
!; |-
| Document Validator
| Перевіряє обов'язкові поля, суми, контрагентів, формати.; Python-сервіс зберігає EDIN ID.; Дія системи

Python EDIN Integration Service

=== 21.2.; Retry-логіка ===

 payload_hash = document_hash_service.calculate(command.payload)

EDIN_BASE_URL=https://api.example.edin
== 22.; Dashboard керівника ==
 event_type="DOCUMENT_STATUS_SYNCED",
|-
| Підходить для
| Юридично значущих документів, актів, рахунків, договорів, первинних документів.; Помилка

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

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

* формування електронного документа у внутрішній системі;
* валідацію документа перед передачею;
* підготовку XML / JSON / PDF / XLSX / вкладень;
* підписання КЕП або передачу документа на підписання;
* відправку документа в EDIN;
* отримання статусу документа;
* отримання підтверджень, квитанцій або службових повідомлень, якщо доступні;
* збереження ID документа EDIN;
* збереження історії зміни статусів;
* повторну передачу документа після технічної помилки;
* захист від дублювання;
* передачу статусу назад у K2 ERP;
* формування dashboard для контролю.; !; |-
| provider
| varchar
| edin.; | платформа повторює передачу без дублювання.;<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
!; 

{| class="wikitable"
!; |-
| document_id
| uuid
| ID документа.; |-
| Status
| Статус документа в K2 ERP та EDIN.; |-
| created_at
| timestamp
| Дата створення.; |-
| AC-6
| Документ потребує підпису.; |-
| AC-18
| є собою відхилені документи.; Тип помилки

 document.raw_response = response.raw_payload
Python EDIN Client
щоб знати, чи документ прийнятий, відхилений, доставлений або очікує дії.; |-
| filename
| varchar
| Назва файлу.; | Другий документ не створюється.; |-
| Делеговане підписання
| Підписує відповідальна особа після отримання задачі.; |-
| base_url
| varchar
| URL API.;=== 13.10. Dashboard ===
!; |-
| Підписання в EDIN
| Документ передається в EDIN і підписується користувачем на платформі.; Поле

 idempotency_key=command.idempotency_key,

</pre>
POST /api/v1/edin/documents
'''Управлінський результат:''' керівник або бухгалтер повинен бачити, які документи сформовано, які підписано, які передано в EDIN, які прийнято, які відхилено, які очікують підпису або дії користувача.; !; |-
| accepted_at
| timestamp
| Дата прийняття.; Призначення
 "payload": {

=== 13.7.; Синхронізація статусу ===
=== 7.3.; Контроль статусів ===

EDIN
{| class="wikitable"

 event_type="DOCUMENT_SENT_TO_EDIN",
{| class="wikitable"

 def refresh_token(self) -> "AuthResult":
=== 7.4.; Повторна передача ===
EDIN_RETRY_BACKOFF_SECONDS=5

 retry_count: int = 3
 db.commit()
!; Якщо не підтримує роботу.; |-
| Повторна відправка
| Хто запустив, причина, результат.; | Не змінювати фінальний статус без перевірки.; | Реалізується в межах цього ТЗ.; |-
| event_type
| varchar
| Тип події.; | Dashboard, проблемні документи.; Значення
 return
!; |-
| Counterparty
| Контрагент.; Контрагент
 document = edin_document_repository.get_by_id(db, document_id)
|-
| Документів за місяць
| 1840
| style="background:#e3f2fd;" | відомості
|-
| Очікують підпису
| 43
| style="background:#fff9c4;" | Увага
|-
| Передано в EDIN
| 1290
| style="background:#bbdefb;" | В роботі
|-
| Прийнято
| 1218
| style="background:#c8e6c9;" | Норма
|-
| Відхилено
| 12
| style="background:#ef9a9a;" | Критично
|-
| Потребують повтору
| 18
| style="background:#ffcc80;" | Потрібна дія
|}

</pre>

я хочу повторити передачу після технічної помилки, 
=== 13.9.; Отримання квитанцій ===
[[Категорія:K2 ERP]]
== 15.; Валідація документа ==
!; Компонент
 api_token: str | None = None

 new_status = status_mapper.from_edin(status_response.status)
=== Етап 8.; Production hardening ===

!; | Потрібен workflow задач.; Статус
|-
| AC-13
| Повторний запит має той самий idempotency_key.; !; |-
| Відправка в EDIN
| Час, endpoint, request_id, EDIN document ID.; |}

!; Очікуваний результат
я хочу натиснути кнопку «Передати через EDIN», 
 new_status=document.status,

{| class="wikitable"
<pre>

 return

 "raw_request": command.model_dump(),
[[Категорія:Податкова звітність]]

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

 def cancel_document(self, edin_document_id: str, reason: str) -> "CancelDocumentResponse":
Як відповідальна особа, 

 "document_number": "123",
 pass
Приклад `.env`:
!; |-
| Розрахунок коригування
| Критичний
| Впливає на ПДВ та реєстрацію.; '''Критично істотно:''' документ зі статусом ACCEPTED або DELIVERED не можна автономно відправляти повторно.; |-
| AC-19
| є собою документи без підпису.; |-
| payload
| jsonb
| Технічні інформаційні дані.; | Зупинити інтеграцію, повідомити адміністратора.; |-
| е-ТТН
| EDIN ETTN API, якщо підключено.; |-
| Document Mapper
| Перетворює документ K2 ERP у формат EDIN.; API EDIN / DocFlow / EDI Network
== Див.; 31.; додатково ==
<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">
 |
 | 5.; def create_edin_document(command: "CreateEdinDocumentCommand", db: "Session") -> "EdinDocument":

 return document

* передачі податкових накладних;
* передачі розрахунків коригування;
* передачі первинних документів;
* передачі актів, рахунків, видаткових накладних;
* передачі структурованих документів через EDIN DocFlow;
* передачі EDI-документів;
* передачі е-ТТН, якщо застосовується відповідний API EDIN;
* передачі документів між контрагентами;
* підготовки пакета документів, які потрібні бухгалтеру для податкової звітності;
* контролю статусів підписання та доставки документів.; | Перевести в NEEDS_CORRECTION.; |-
| API Event
| Подія інтеграції.; |-
| переважні аспекти
| Можливість працювати з податковими документами в одному ЕДО-середовищі.; |-
| integration_mode
| varchar
| Через який канал передається.; | style="background:#fff9c4;" | Жовтий
|-
| Підписано
| SIGNED
| Документ підписано КЕП.; | Перевести в SIGN_ERROR.; {| class="wikitable"
 "file_id": "file-001"
{| class="wikitable"
 "vat_amount": command.vat_amount,
 audit_logger.log(
 payload={"external_document_id": command.external_document_id},
class EdinSettings(BaseSettings):
 old_status = document.status
 document.accepted_at = datetime.now(timezone.utc)
=== 19.1. edin_integrations ===

 pass

 "document_type_id": command.document_type_id,
<pre>
EDIN Client  це Python-клас або пакет, який інкапсулює роботу з EDIN API.; # Чи потрібно підтримувати декілька акаунтів EDIN?; |}

 new_status="SENT_TO_EDIN",

 existing = edin_document_repository.get_by_idempotency_key(
=== 21.1.; Типи помилок ===
{| class="wikitable"
 db.commit()
|-
| id
| uuid
| Внутрішній ID документа.; |-
| EDIN Document
| Документ, створений або переданий в EDIN.; Канал
 pass
</pre>
!; Після підпису документ переходить у PENDING_SEND.; K2 ERP / ERP / CRM
|-
| style="background:#c8e6c9;" | Зелений
| #c8e6c9
| Успішно: підписано, доставлено, прийнято.; | Внутрішня платформа замовника.; |}

!; | Перевести в NEEDS_RETRY.; |-
| переважні аспекти
| Стандартизований обмін документами з контрагентами.; Канал
<pre>
!; |-
| vat_amount
| numeric
| Сума ПДВ.; характеристика

 def check_connection(self) -> "ConnectionStatus":
інтеграційні функціональні можливості має змогу використовуватись для:
 document.status = new_status
!; | Окремий статус SIGN_ERROR і журнал підписання.; Поле

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

<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">

</pre>
<pre>
</pre>
!; # Як часто синхронізувати статуси?; |-
| content_type
| varchar
| MIME type.; Параметр
{| class="wikitable"
|-
| EDIN
| Платформа електронного документообігу.; |-
| Довільний файл
| Середній
| Супровідний документ.; | Статус підсвічується червоним.; |-
| AC-14
| EDIN API тимчасово недоступний.; |-
| е-ТТН
| Високий
| Важливий для логістики.; | Помилки валідації, retry.; | інтеграційні функціональні можливості зберігається в системі.; |-
| AC-15
| користувач системи запускає retry.; |-
| payload_format
| varchar
| XML, JSON, PDF.; {| class="wikitable"

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

<syntaxhighlight lang="python">

</pre>

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

event_type="DOCUMENT_CREATED",
def create_document(self, payload: "EdinDocumentPayload") -> "EdinDocumentResponse":
"idempotency_key": command.idempotency_key,

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

API Layer - Помилка КЕП Документ не буде підписано.; status_response = edin_client.get_document_status(document.edin_document_id)
audit_logger.log(

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

Первинний документ Високий Важливий для бухгалтерії.; except Exception as exc:
Податкова накладна Критичний - idempotency_key varchar - EDIN EDI Network }
if new_status == "ACCEPTED":

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

"counterparty_id": command.counterparty_id,
def download_receipt(self, edin_document_id: str, receipt_id: str) -> bytes:

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

id uuid - Receipt / Confirmation - Отримання квитанції Тип квитанції, час, файл.;</syntaxhighlight>
!; |-
| Обмеження
| Потрібно підтвердити формат API, підписання, статуси та квитанції.; {| class="wikitable"
K2 ERP / Dashboard / Задачі відповідальних

!; |-
| is_active
| boolean
| Активність.; характеристика
9.; |-
| payload_format
| varchar
| XML, JSON, PDF, mixed.;== 20.; Приклад Python-логіки ==

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

=== Варіант 2.; 5.2.; EDI Network API ===
=== Етап 2.; Базовий Python-сервіс ===
3.; Критерій
</div>
!; # Чи потрібно зберігати КЕП у системі?; Очікуваний результат
- AC-11 - SchemaError Документ не відповідає XML/JSON-схемі.; "content_type": "application/pdf",
},
def get_document(self, edin_document_id: str) -> "EdinDocumentResponse":
- Блакитний #bbdefb - raw_response jsonb Відповідь EDIN.; Поле

19.2. edin_document_types

<syntaxhighlight lang="python">
 "content_type": "application/xml",

{| class="wikitable"
8.; У цьому ТЗ endpoint-и Python-сервісу є собою внутрішніми, а EDIN endpoint-и мають уточнюватись за документацією EDIN.; Тип документа

 "signing_status": "WAITING_SIGNATURE" if command.signing_required else "SIGN_NOT_REQUIRED",

!; |}

EDIN_API_TOKEN=********

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

!; характеристика
"document_type": "TAX_INVOICE",
Не потребує підпису SIGN_NOT_REQUIRED Сірий }
data={

 raise BusinessError("Document must be signed before sending")
 def authenticate(self) -> "AuthResult":
<syntaxhighlight lang="python">
 company_id: str
|-
| AC-1
| Адміністратор створює інтеграцію EDIN.; |-
| is_active
| boolean
| Активність.; Сервіс повинен забезпечити:
</div>
!; |-
| Немає квитанції
| Документ передано, але підтвердження не отримано.; Для реалізації задачі необхідно отримати:
{| class="wikitable"
!; |-
| Помилка підпису
| SIGN_ERROR
| style="background:#ef9a9a;" | Червоний
| Підписання не виконано.; |-
| updated_at
| timestamp
| Дата актуалізація.; | ключовий зовнішній сервіс.; | style="background:#c8e6c9;" | Норма
|-
| Відхилено
| Документи з негативним статусом.; | Квитанція зберігається в картці документа.; Що зберігати
|-
| Чернетка
| DRAFT
| Документ створено в K2 ERP, але ще не готовий до передачі.; Для класичної податкової звітності потрібно окремо перевіряти, чи підтримує роботу EDIN потрібний сценарій передачі, підписання, отримання квитанцій та статусів.; |-
| document_date
| date
| Дата документа.; |}

[[Категорія:API]]

!; |-
| api_password_encrypted
| text
| Зашифрований пароль.; |-
| payload_hash
| varchar
| Hash документа.; |-
| переважні аспекти
| Робота зі статусами, компаніями, документами, структурованими даними.; |-
| style="background:#f3e5f5;" | Фіолетовий
| #f3e5f5
| Спеціальний або індивідуальний документ.; |}

!; |-
| style="background:#ffcc80;" | Помаранчевий
| #ffcc80
| Потрібна дія користувача або повтор.; |-
| Синхронізація статусів
| Середній
| Фоновий бізнес-процес.; | застосовується, якщо підключено DocFlow.; |-
| Status Sync Worker
| Періодично синхронізує статуси з EDIN.; |-
| DuplicateDocumentError
| Документ уже існує.; | Потрібно безпечно зберігати ключі або використовувати HSM/хмарний КЕП.; Worker відправляє документ у EDIN.; |-
| file_hash
| varchar
| Hash файлу.; |-
| AC-2
| Адміністратор перевіряє підключення.; | Потрібен компонент КЕП у K2 ERP.; retry_backoff_seconds: int = 5
 document_id=document.id,
|-
| AC-4
| K2 ERP створює документ.; Сутність
|-
| Integration Account
| Обліковий запис інтеграції EDIN.; document.status = "SEND_ERROR"

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

 v
 "external_document_id": command.external_document_id,
 payload = edin_mapper.to_edin_payload(document)
EDIN_API_PASSWORD=********
!; |-
| external_document_id
| varchar
| ID документа в K2 ERP.; |-
| integration_mode
| varchar
| docflow, edi_network, tax_invoice, ettn, hybrid.; |-
| organization_id
| uuid
| Організація-відправник.; # Чи потрібна валідація XML за XSD?; характеристика
 document.sent_at = datetime.now(timezone.utc)
GET /api/v1/edin/documents/{document_id}/receipts
|-
| ValidationError
| Некоректні інформаційні дані документа.; |-
| created_at
| timestamp
| Дата події.; характеристика

== 23.; Безпека ==

!; # Чи потрібне підписання в K2 ERP, Python-сервісі або на стороні EDIN?; auth_url: str | None = None

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

 )
 pass
<pre>
|-
| Підходить для
| Податкових накладних, розрахунків коригування, пов'язаних документів.; Повторна відправка дозволена тільки для технічних помилок або спеціальних статусів, визначених бізнес-правилами.; |}

 db.commit()

</div>

=== 20.2.; Відправка документа ===
POST /api/v1/edin/documents/{document_id}/sign


 document.error_message = str(exc)
=== 22.1.; Основні KPI ===
=== 25.4.; Дедублікація та повтор ===
!; | Підтвердити API та типи документів до розробки.; # Чи потрібно експортувати журнал передачі в Excel?; Критерій
<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">
!; |}

 )

 payload=status_response.raw_payload,
!; | Idempotency key і document_hash.; Параметр
 audit_logger.log(
 document_id=document.id,
|-
| external_document_id
| ID документа у K2 ERP.; характеристика

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

=== 13.2.; Перевірка підключення ===
== 14.; Приклад запиту на створення документа ==
5.; |-
| Основні операції
| Формування XML, передача, отримання статусу, отримання відповіді контрагента.; характеристика
 "payload_hash": payload_hash,
!; |-
| Очікує підпису
| WAITING_SIGNATURE
| style="background:#fff9c4;" | Жовтий
| Документ очікує підписання.; Код
<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
 def update_document(self, edin_document_id: str, payload: "EdinDocumentPayload") -> "EdinDocumentResponse":
платформа повинна забезпечити:
 if document.status in ["ACCEPTED", "DELIVERED"]:
=== 25.5. Dashboard ===
 v
== 2.; Область сфера застосування ==
 },
 "document_number": command.document_number,
<pre>
{| class="wikitable"
 document.error_message = str(exc)
 v
EDIN_AUTH_URL=https://api.example.edin/auth
</syntaxhighlight>
== 11.; технічна архітектура рішення для бізнесу ==
Для надійності передача документів повинна виконуватись через чергу.; Поле

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

 document = edin_document_repository.get_by_id(db, document_id)
== 3.; Джерела інтеграції ==
!; |-
| api_login_encrypted
| text
| Зашифрований логін.; Параметр
=== 25.1.; інтеграційні функціональні можливості ===
|-
| 07.05.2026
| Податкова накладна №123
| ТОВ «Альфа»
| ТОВ «Бета»
| style="background:#ef9a9a;" | Відхилено
| Помилка схеми XML
| Виправити
|-
| 07.05.2026
| Акт №45
| ТОВ «Альфа»
| ТОВ «Гамма»
| style="background:#fff9c4;" | Очікує підпису
| Немає КЕП відповідального
| Підписати
|-
| 07.05.2026
| е-ТТН №77
| ТОВ «Логістика»
| ТОВ «Покупець»
| style="background:#ffcc80;" | Потребує повтору
| Timeout EDIN API
| Повторити
|}

<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">

{| class="wikitable"

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

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

=== 5.1.; Варіант 1.; EDIN DocFlow API ===
<syntaxhighlight lang="python">
EDIN_INTEGRATION_MODE=docflow
 )
|-
| id
| uuid
| ID квитанції.; |-
| signing_status
| varchar
| Статус підписання.; # Чи потрібно підтримувати декілька юридичних осіб?; |}

</syntaxhighlight>

4.; | Python-сервіс створює запис зі статусом DRAFT.; |}

 v

!; Код
 timeout_seconds: int = 30
== 26. MVP ==

; Колір
finally:

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

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

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

;

Як бухгалтер,

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

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

],
 "signing_required": true,

!; Status Sync Worker періодично оновлює статус.; |}

== 30.; Джерела ==

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

{| class="wikitable"
!; Квитанції та підтвердження зберігаються в картці документа.; | style="background:#ffcc80;" | Помаранчевий
|-
| Очікує підпису
| WAITING_SIGNATURE
| Документ готовий, але ще не підписаний.; | Версіонування клієнта і contract-тести.; # Чи потрібно отримувати квитанції автономно?; Де застосовується
=== 7.1.; Передача документа ===
|-
| Підписання в K2 ERP
| Документ підписується до передачі в EDIN.; |-
| document_id
| uuid
| ID документа.; | style="background:#eeeeee;" | Сірий
|}

from datetime import datetime, timezone

=== 16.2.; Статуси підписання ===
передачі електронних документів забезпечується через '''Головна ідея:''' розробити Python-сервіс.; | Списки, архів.; Підписання або передача на підпис
 "external_document_id": "K2-TAX-INVOICE-2026-000123",
4.; "payload_format": command.payload_format,
  • реалізувати створення документа;
  • реалізувати мапінг K2 ERP → EDIN;
  • реалізувати валідацію;
  • реалізувати hash документа;
  • реалізувати дедублікацію.; | style="background:#bbdefb;" | В роботі
Прийнято - requires_attachments boolean None = None
  • реалізувати авторизацію;
  • реалізувати check_connection;
  • реалізувати create_document;
  • реалізувати upload_attachment;
  • реалізувати send_document;
  • реалізувати get_document_status;
  • реалізувати get_document_list;
  • реалізувати download_receipt;
  • реалізувати обробку помилок.; | style="background:#ffcc80;" | Потрібна дія
Без квитанції - Підписання в Python-сервісі - Обмеження Потрібно перевірити доступність конкретних типів документів.;=== Етап 1.; Аналіз EDIN API ===

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

"filename": "tax_invoice_123.xml",
; !; Тип
Черга, статус API.; |- AuthError }
response = edin_client.create_document(payload)

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

pass
Без підпису він не відправляється.; |- Обмеження Статус змінюється на READY_FOR_REVIEW або WAITING_SIGNATURE.; | Вони підсвічуються жовтим.; №
AC-17 - Основні операції Створення документа, редагування, зміна статусу, отримання списку документів.; характеристика

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

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

"document_date": command.document_date,


"payload_format": "xml",

19.6. edin_events

style="background:#fff9c4;" | Контроль
- Зміна API Перевести в NEEDS_CORRECTION.; Retry дозволений для:

10.; |-

EDIN DocFlow API API для роботи зі структурованими документами, компаніями, статусами та списками документів.; Тип
"counterparty_id": "counterparty-001",
db.commit()
"organization_id": "org-001",
; Критерій ; Важливість
if not document.edin_document_id:
pass
def send_document(self, edin_document_id: str) -> "SendDocumentResponse":

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

Потрібно підтвердити підтримку цього сценарію для типу документа.; | Таблиця status_mapping і статус UNKNOWN.; |- AC-8 Документ відправлено в EDIN.; Як зменшити Зберегти raw-відповідь.; !; Дата

щоб не створювати документ вручну повторно.; |-

error_message text Остання помилка.;

Черга підпису, календар задач.; |- document_number varchar - Підписується SIGNING Блакитний Виконується підписання.; Подія EDIN_API_LOGIN=******** - created_at timestamp style="background:#fff9c4;" | Увага
Передано в EDIN style="background:#c8e6c9;" | Зелений
Відхилено REJECTED Документ відхилено.; HTML

12. EDIN Client

Як керівник бухгалтерської компанії,
style="background:#bbdefb;" | Блакитний
Передано в EDIN SENT_TO_EDIN - old_status varchar - Скасування Хто скасував, причина.; Код def send_edin_document(document_id: str, db: "Session") -> None: ; payload={"edin_document_id": response.document_id},
До MVP не входить:




; Критерій ; Ключ

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

- source varchar - Сірий #eeeeee застосовується для ORDER, DESADV, INVOICE та інших EDI-документів.;=== 12.3.; Конфігурація клієнта === * https://edin.ua/ * https://edin.ua/edi-network/ * https://edin.ua/integraciya/ * https://edin.ua/integracijni-rishennya-edin/ * https://wiki.edin.ua/ * https://wiki-df.edin.ua/ * https://wiki.edin.ua/uk/latest/retail_2.0/Formuvannya_Podatkovoyi_Nakladnyy_na_pidstavi_Prybutkovoyi_nakladnoyi.html * https://wiki.edin.ua/uk/latest/API_ETTNv3_1/API_ETTNv3_1_list.html "xml_file_id": "file-001" * Python * FastAPI * K2 ERP * EDIN * EDIN DocFlow * EDI Network * Електронний документообіг * КЕП * Податкова накладна * Розрахунок коригування * Первинні документи * е-ТТН * API інтеграція {

25.2.; Документи

pass if document.signing_status == "WAITING_SIGNATURE": "total_amount": 12000.00, "file_id": "file-002"