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

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

Матеріал з K2 ERP Wiki

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

def download_receipts(self, document_id: str) -> list [bytes]:
event_type="STATUS_SYNC_FAILED",

1.; Мета

services/

10.; Мапінг статусів ПТАХ

- xml
- Rejected Отримати офіційну документацію та тестовий доступ.; |- waiting_receipt WaitingForReceipt - КЕП Кваліфікований електронний підпис.; характеристика }

7.; # Які endpoint-и використовуються для відправки?; "taxpayer_id": "1234567890",

11.8.; Отримання журналу

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

POST /api/v1/tax-reports/{report_id}/download-receipts

Python Зафіксувати помилку, повідомити адміністратора.; |- Failed - Зміна API - AC-10 Документ підписано.;=== 8.4.; Підписання документа ===

11.7.; Отримання документа

; repositories/
event_type="SIGNED_IN_PTAH",
Draft Опційно.; Перевірити, що документ не був відправлений раніше.; |- AC-2 - AC-11 }
 integration/

* доступ до платформи ПТАХ;
* активований доступ до API.ПТАХ;
* базовий URL API;
* спосіб авторизації;
* API key / token / client credentials;
* технічну документацію endpoint-ів;
* перелік доступних типів документів;
* підтвердження функціональні можливості передачі звітності до ДПС через ПТАХ;
* формат передачі файлів;
* формат метаданих документа;
* правила створення документа в ПТАХ;
* правила підписання документа;
* правила відправки документа;
* правила отримання статусів;
* правила отримання квитанцій;
* тестове середовище, якщо доступне;
* технічний контакт з боку постачальника ПТАХ.; Оновити статус на Signed або Failed.; |-
| waiting_signature
| WaitingForSignature
| Очікується підпис.; |-
| Квитанція
| Підтвердження прийняття, відхилення або обробки звіту.; | платформа надає можливість ініціювати підписання, якщо це підтримується API.; | платформа не створює дубль без окремого підтвердження.; |-
| accepted
| Accepted
| Документ прийнято.; # Чи Python-сервіс має сам формувати XML, чи отримує готовий XML з ERP?; |-
| document_number
| varchar
| Номер документа.; Інтервал перевірки

 )

{| class="wikitable"
 "status": "Generated",
POST /api/v1/tax-reports/{report_id}/validate

=== 11.5.; Відправка документа ===

}
 verify_ssl: bool = True
ERP / Accounting System

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

ДПС або інший отримувач
{
!; |-
| Помилка API
| HTTP-код, тіло відповіді, correlation ID.; |-
| old_status
| varchar
| Попередній статус.; Викликати PtahClient.upload_tax_report().; |-
| WaitingForSignature
| Документ очікує підписання.; характеристика
платформа повинна мати background worker, який періодично оновлює статуси документів.; |-
| AC-14
| ПТАХ повертає невідомий статус.; "period": "2026-Q1",

* реалізувати авторизацію;
* реалізувати upload_tax_report;
* реалізувати create_document;
* реалізувати get_document_status;
* реалізувати download_document;
* реалізувати download_receipts;
* реалізувати обробку помилок;
* реалізувати retry.; | платформа надає можливість відправку документа.; | Виконати retry.; щоб оперативно знаходити причину помилок інтеграції.; |-
| XSD
| Схема перевірки XML-документа.; |-
| payload
| jsonb
| Технічні інформаційні дані події.; # Записати подію в журнал.; |-
| status
| varchar
| Внутрішній статус.; | Зберегти raw-статус, створити подію UnknownStatus.; |-
| file_type
| varchar
| original, signed, pdf, receipt_1, receipt_2, error_protocol.; |-
| file_format
| varchar
| XML, PDF, ZIP тощо.; |-
| Недоступність ПТАХ
| Платформа або мережа можуть бути тимчасово недоступні.; |-
| HTTP client
| httpx.; Спосіб
</pre>
 "taxpayer_name": "ФОП Іваненко Іван Іванович",
!; | Він бачить всі пов'язані файли та статуси.; |-
| Validation Layer
| Перевіряє реквізити, структуру та статус документа.; | платформа надає можливість передачу в ПТАХ.;=== 11.10.; Повторна відправка ===
 report.status = TaxReportStatus.SIGNED
; event_type="SENT_TO_PTAH",

Якщо API.ПТАХ підтримує роботу відповідний метод, Python-сервіс повинен ініціювати відправку документа отримувачу.; | Статуси документів оновлюються автономно.; Отримати результат підписання.; |-

created_at timestamp - AC-17 Отримати офіційну API-документацію та підтвердження від постачальника.; !; Метою задачі є собою створення Python-сервісу для передачі документів звітності через платформу ПТАХ.; reports = tax_report_repository.get_reports_for_sync()
)
entity_id=report.id,
allowed_formats:
- uploaded SentToPtah - Python-сервіс - source_system varchar - Підписання в Python-сервісі - ReadyToSend Документ готовий до передачі.;
"status": "Sent",
"new_status": "WaitingForSignature",

Етап 5.; Підписання та відправка

"report_type": "single_tax_declaration",

</syntaxhighlight>

Внутрішній статус документа змінюється.; Очікуваний результат ; Внутрішній статус
"old_status": "SentToPtah",

POST /api/v1/tax-reports/{report_id}/sign

платформа повинна забезпечити:

 payload = DocumentPayload(
 "ptah_status": "waiting_signature"
 retry_backoff_seconds: int = 5

 models.py

 report = tax_report_repository.get_by_id(db, report_id)
Фінальний мапінг статусів потрібно побудувати після отримання офіційного довідника статусів API.ПТАХ.; | Основна платформа для передачі документів.; # Оновити статус на Sent.; - zip
 - xml
POST /api/v1/tax-reports/{report_id}/send-to-ptah

 details={

 "status": "ReadyToSend",
Сервіс повинен забезпечити:
{| class="wikitable"

!; # Записати подію в журнал.; | Raw-статус зберігається, створюється подія UnknownStatus.; |-
| Невідомі статуси
| ПТАХ має змогу повертати статуси, яких немає в системі.; Перевірити, що документ підписано.; характеристика
 entity_id=report.id,
 file_repository.py
== 14.; Підписання та відправка через ПТАХ ==
<pre>
 main.py
Очікувана відповідь:
 "message": "Document sent via Ptah"
=== 14.1.; Логічний бізнес-процес підписання ===
 event_repository.py
!; Окремо варто відзначити який формує, перевіряє, передає і контролює документи звітності через інтеграцію з платформою ПТАХ / API.ПТАХ.; # Перевірити, що документ підписано або готовий до підписання.; TaxReportStatus.SENT_TO_PTAH,
=== 11.2.; Перевірка документа ===
 def create_document(self, document: "DocumentPayload") -> "PtahDocumentResponse":

4.; }

tax_report_service.py

GET /api/v1/tax-reports/{report_id}/events

requires_receipt: true

PTAH_RETRY_BACKOFF_SECONDS=5

title: "Об'єднана формування звітів"

</syntaxhighlight>

 pass
 storage/


<pre>
[[Категорія:K2 ERP]]

=== 11.9.; Завантаження квитанцій ===
 report_id=report.id,
 unified_report:
 README.md

 requires_signature: true

from pydantic_settings import BaseSettings
</pre>
Мінімальний набір вхідних даних:
{| class="wikitable"
 try:
 return report
 "errors": []
 )
PTAH_TIMEOUT_SECONDS=30
Повторна відправка дозволена тільки для документів у статусах:
 tests/
4.; Передача документа через API.ПТАХ
!; Очікувана відповідь:
POST /api/v1/tax-reports/{report_id}/send-to-ptah
 ptah/

{{DISPLAYTITLE:Технічне завдання: Передача документів для звітності в податкову через ПТАХ для Python}}
== 12. Ptah Integration Client ==
!; |}

 db/

 report.ptah_document_id = response.id

* timeout;
* тимчасової недоступності API.ПТАХ;
* HTTP 429;
* HTTP 500;
* HTTP 502;
* HTTP 503;
* HTTP 504;
* тимчасових мережевих помилок.; !; | Статус документа змінюється на Signed.; {| class="wikitable"

!; date=report.document_date,

== 6.; технічна архітектура рішення для бізнесу ==
class PtahClient:
=== 12.3.; Конфігурація клієнта ===
 "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",

!; | Резервний режим.; |-
| event_type
| varchar
| Тип події.; Рекомендація
|-
| AC-8
| Документ створено в ПТАХ.; Оновити статус на SentToPtah.; 

</pre>

PTAH_TIMEOUT_SECONDS=30

* прийом даних звітності з ERP / облікової системи;
* формування або прийом готового XML-документа;
* перевірку документа перед передачею;
* передачу документа в ПТАХ;
* запуск підписання документа, якщо це підтримується API;
* запуск відправки документа, якщо це підтримується API;
* отримання зовнішнього ID документа;
* синхронізацію статусів;
* отримання квитанцій або результатів обробки;
* збереження історії передачі;
* обробку помилок;
* повторну відправку;
* журналювання всіх технічних і бізнес-подій.; |-
| Помилки КЕП
| Можливі проблеми з ключами, паролями або сертифікатами.; # Які endpoint-и використовуються для створення документа?; # Чи підтримуються webhook-и?; |-
| PtahUnavailableError
| Платформа ПТАХ недоступна.; |}

 exceptions.py

=== 14.3.; Приклад Python-логіки ===

* квитанцію про отримання;
* квитанцію про прийняття;
* квитанцію про відхилення;
* підписаний документ;
* PDF-візуалізацію, якщо доступна;
* технічний протокол обробки, якщо доступний;
* raw-відповідь ПТАХ.; Очікуваний результат
!; | Заборонити повтор без підтвердження.; |-
| Validation
| Pydantic.; Валідація та збереження документа
 title: "Декларація платника єдиного податку"
 )
 |
 | 3.; щоб мати підтвердження результату передачі документа.; | Не відправляти документ, показати список помилок.; Критерій

FILE_STORAGE_PATH=/data/tax-reports

 sync_statuses.py

1.; def sync_pending_reports() -> None:
!; status_mapper.py
!; |-
| Завантаження квитанції
| Тип файлу, назва, дата.; # Які типи звітів підтримуються першими?; |-
| Polling
| Періодичне опитування зовнішнього API.; |-
| ДПС
| Державна податкова служба України.; |-
| Webhook
| Механізм отримання подій від зовнішньої системи.; Ризик
== 22. MVP ==
 },
=== 16.2. tax_report_events ===
=== 21.5.; Квитанції та файли ===
}
Python Tax Reporting Service
 logging.py

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

{| class="wikitable"
PTAH_CLIENT_SECRET=********
POST /api/v1/tax-reports
 "ptah_status": ptah_status.raw_status,
 pass
=== 12.2.; Основні методи ===
 db.commit()

<pre>

!;<pre>

* Accepted;
* Sent;
* WaitingForReceipt;
* SentToPtah;
* WaitingForSignature.; |}

Очікувана відповідь:

<pre>

 if report.status not in {
!; # Оновити статус документа.; |}

 details={"error": str(exc)},

# Який саме програмний продукт застосовується: ПТАХ, API.ПТАХ або інтеграційні функціональні можливості через інший програмний продукт Linkos Group?; |-
| created_at
| timestamp
| Дата створення.; # Який SLA по оновленню статусів?; 
функціональні можливості застосовують, коли потрібно для автоматизації передачі документів звітності з ERP або облікової системи до ПТАХ.; | Відображати зрозумілу помилку та дозволяти повторне підписання.; |-
| AC-3
| Передано некоректні інформаційні дані.; |-
| ptah_raw_status
| varchar
| Останній raw-статус ПТАХ.; | Зберігати raw-статус та мати UnknownStatus.; |-
| last_sync_at
| timestamp
| Дата останньої синхронізації.; |-
| Generated
| Файл документа сформовано.; Записати подію в журнал.; new_status=new_status,
!; |-
| rejected
| Rejected
| Документ відхилено.; |}

POST /api/v1/tax-reports/{report_id}/sync-status
 details={
 "ptah_document_id": "external-document-id",

{| class="wikitable"

{

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

 ptah_status = ptah_client.get_document_status(

 "source_system": "K2 ERP",
 return report
6.; Пріоритет
!; # Чи підтримує роботу ПТАХ сценарій подання податкової звітності до ДПС?; Перевірити, що документ має статус ReadyToSend.; # Які endpoint-и використовуються для підписання?; |-
| Sending
| Документ передається в ПТАХ.; |-
| SentToPtah
| Документ успішно передано в ПТАХ.; |-
| file_name
| varchar
| Назва файлу.; Призначення

1.; POST /api/v1/tax-reports/{report_id}/send

 v

* створення Python API для прийому документів;
* створення клієнта інтеграції з API.ПТАХ;
* формування XML або прийом готового XML;
* збереження документа;
* перевірка обов'язкових реквізитів;
* передача документа в ПТАХ;
* запуск підписання / відправки через ПТАХ, якщо підтримується API;
* отримання статусів;
* отримання квитанцій або результатів обробки;
* журнал подій;
* retry-механізм;
* захист API-ключів і службових доступів;
* інтеграційні функціональні можливості з ERP.; | Перевіряти ptah_document_id перед відправкою.; requires_signature: true

== 13.; Передача документа в ПТАХ ==
{| class="wikitable"
from uuid import UUID
{| class="wikitable"
 unit/
 )
я хочу ініціювати підписання та відправку документа через ПТАХ, 
 download_receipts.py
<syntaxhighlight lang="python">
 audit_logger.log(
GET /api/v1/tax-reports/{report_id}
 "old_status": old_status,
</div>
=== 12.1.; Призначення ===
!; |-
| Передача в ПТАХ
| Endpoint, час, статус відповіді, зовнішній ID.; Запустити очікування квитанцій.; |-
| ptah_document_id
| varchar
| ID документа у ПТАХ.; Зберегти ID у локальній БД.; |-
| file_path
| varchar
| Шлях до файлу у сховищі.; # Який формат документа підтримується: XML, PDF, ZIP, JSON?; | Додати healthcheck інтеграції та повідомлення адміністратору.; |-
| error_message
| text
| Остання помилка.; |-
| StatusMappingError
| Невідомий статус від ПТАХ.; характеристика
 raise InvalidStatusError(

</pre>

 )
</pre>
<pre>

 allowed_formats:

 client.py
PTAH_CLIENT_ID=********
5.; document_types:

 routes/

* ValidationError;
* Failed;
* Rejected;
* DeliveryError;
* NeedResend.; |-
| Дублювання документів
| Повторна відправка має змогу створити дубль.;<pre>

* додати Dockerfile;
* додати docker-compose;
* додати structured logging;
* додати metrics;
* додати alerting;
* додати rate limiting;
* додати security review.; |-
| sent_at
| timestamp
| Дата передачі в ПТАХ.; Тип

PTAH_COMPANY_CODE=12345678 платформа повинна підтримувати два способи актуалізація статусів:

pass
"created_by": "user@example.com"
"source_system": report.source_system,
timeout_seconds: int = 30
f"Report {report_id} cannot be signed from status {report.status}"
old_status = report.status
; "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
client_id: str | None = None
- accepted_at timestamp Дата прийняття.; validation_service.py
id uuid ID події.; характеристика

STATUS_SYNC_INTERVAL_SECONDS=300

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

session.py
event_type="STATUS_CHANGED",
raw_status=ptah_status.raw_status,
"file_content_base64": "BASE64_XML_CONTENT",
)

STATUS_SYNC_ENABLED=true

allowed_formats:
entity_id=report.id,
file_storage.py

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

report = tax_report_repository.get_by_id(db, report_id)
7.; Тип

PTAH_RETRY_BACKOFF_SECONDS=5

29.; Джерела

for report in reports:
def cancel_document(self, document_id: str, reason: str) -> "PtahDocumentResponse":
Непідтверджений сценарій подання звітності до ДПС }

tax_reporting_ptah_service/

Ptah Integration Adapter

security.py
requires_receipt: true
Потрібна офіційна API-документація та доступ.; |}

11.6.; актуалізація статусу

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

def download_signed_document(self, document_id: str) -> bytes:
"report_type": report.report_type,
id uuid ID файлу.; Статус ПТАХ

8.; Функціональні вимоги

7.2.; Підписання та відправка

=== 8.3.; Передача документа в ПТАХ ===
=== Етап 3.; Ptah Integration Client ===

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

=== Етап 1.; Базова структура Python-сервісу ===
платформа повинна логувати:
 file_name=report.file_name,

 status_sync_service.py

<pre>

 pass

=== 21.2.; Передача в ПТАХ ===

!; |}

 TaxReportStatus.CREATED_IN_PTAH,

<pre>
PTAH_CLIENT_ID=********
<div style="border-left: 6px solid #1565c0; background: #e3f2fd; padding: 12px 16px; margin: 16px 0;">
 requires_receipt: true
|-
| AC-4
| Документ має статус ReadyToSend.; Як зменшити
== 19.; конфігурація ==
 new_status = status_mapper.map_ptah_status(ptah_status)

{| class="wikitable"

# Отримати документ із локальної БД.; | платформа зберігає причину відхилення.; |-
| DB
| PostgreSQL.; |-
| content_type
| varchar
| MIME-тип.; # Отримати файл зі сховища.; |}

[[Категорія:ПТАХ]]

'''Головна ідея:''' розробити Python-сервіс.; |-
| sent_to_tax_at
| timestamp
| Дата відправки до ДПС, якщо підтримується.; |-
| document_number
| string
| Так
| Номер документа.; |-
| updated_at
| timestamp
| Дата актуалізація.; v

{| class="wikitable"

<syntaxhighlight lang="json">
<syntaxhighlight lang="json">
=== Етап 4.; Передача документів ===
 def download_original(self, document_id: str) -> bytes:
|-
| Підписання в ПТАХ
| Документ передається в ПТАХ, а підписання виконується засобами платформи.; Режим
це Python-клас або пакет, який інкапсулює роботу з API виступає ключовою рисою Ptah Integration Client.ПТАХ.; характеристика

<pre>
 "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
5.; |-
| Background jobs
| Celery, RQ або APScheduler.; |-
| AC-6
| API.ПТАХ повертає помилку.; характеристика

 audit_logger.log(

* створити FastAPI-проєкт;
* налаштувати PostgreSQL;
* створити моделі tax_reports, tax_report_events, tax_report_files;
* реалізувати конфігурацію через environment variables;
* реалізувати healthcheck endpoint.; |}

},
  • наявність обов'язкових полів;
  • коректність РНОКПП або ЄДРПОУ;
  • коректність звітного періоду;
  • наявність файлу;
  • допустимий формат файлу;
  • розмір файлу;
  • коректність імені файлу;
  • відповідність XML-структурі;
  • відповідність XSD, якщо схема доступна;
  • відсутність дубля документа;
  • наявність налаштувань інтеграції з ПТАХ.; | Маскувати логи та обмежити доступ.; # Викликати Ptah Integration Adapter.; |-
PtahTimeoutError - PtahAuthError Помилка авторизації в API.ПТАХ.; # Зберегти зовнішній ID у БД.; Тип

def sign_and_send_report(report_id: UUID, db: "Session") -> "TaxReport":

"id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",

9.; Отримати результат відправки.; |-

Відправка Результат, дата, raw-відповідь ПТАХ.; Очікуваний результат

}


 - xml

</div>

 def upload_tax_report(self, document: "DocumentPayload") -> "PtahDocumentResponse":
 signing_service.py
== 27.; Технічні вимоги до Python ==
|-
| Створення документа
| ID, користувач системи, дата, тип документа.; |-
| SignatureError
| Помилка підписання документа.; |-
| Валідація
| Результат, список помилок.; |}

Python-сервіс повинен мати метод для передачі документа в ПТАХ.; Очікуваний результат

details={"raw_status": send_response.status},
docker-compose.yml
pass

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

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

Заборонено: зберігати API key, client secret, токени або паролі КЕП у коді, Git-репозиторії чи відкритих логах.; |-

Ptah Client - PtahApiError Зберегти помилку, дозволити повторне підписання.; report.sent_at = datetime.now(timezone.utc)

def send_report_to_ptah(report_id: UUID, db: "Session") -> "TaxReport":

  • зберігання API key тільки у змінних середовища або secret storage;
  • заборону логування API key;
  • заборону зберігання паролів КЕП у відкритому вигляді;
  • маскування персональних даних у технічних логах;
  • контроль доступу до документів;
  • контроль доступу до квитанцій;
  • журналювання всіх операцій;
  • HTTPS для API-запитів;
  • перевірку SSL-сертифіката;
  • обмеження доступу до адміністративних endpoint-ів;
  • резервне копіювання документів і квитанцій.; |-
Python-сервіс - XML Формат електронного документа звітності.; №
migrations/
details={"raw_status": sign_response.status},

POST /api/v1/tax-reports/{report_id}/send

"id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",

}

- new_status varchar Новий статус.; def get_document_status(self, document_id: str) -> "PtahStatusResponse":

7.3.; Отримання статусу

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

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

16.1. tax_reports

TaxReportStatus.WAITING_FOR_SIGNATURE,
Retry не застосовується для:
id uuid - Неповна або закрита API-документація - sent_to_tax SentToTax }
api/

ПТАХ

24.; Ризики

PTAH_CLIENT_SECRET=********

; Критерій

21. Acceptance Criteria

- created_by varchar користувач системи або system.; Поле - document_date date - file_path varchar Шлях до файлу.; Компонент

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

workers/
- xml

Як користувач системи ERP,

5.; Терміни та скорочення

ERP / Accounting System

7.1.; Передача документа в ПТАХ

if not report.ptah_document_id:
- Audit Logger - Containers Docker.; # Перевірити статус документа.;=== 14.2.; Логічний бізнес-процес відправки ===

PTAH_RETRY_COUNT=3

- pdf
=== 7.4.; Отримання квитанцій ===
|-
| ПТАХ
| Платформа електронного документообігу та обміну юридично значущими документами.; | ключовий режим, якщо підтримується API.; Попередній логічний мапінг:
== 28. Definition of Done ==
=== 16.3. tax_report_files ===
я хочу бачити статус документа в ERP, 
 file_bytes = file_storage.read(report.file_path)

<pre>

 core/
 pass

Retry застосовується для:
щоб не виконувати ці дії вручну, якщо це підтримується API.; # Де зберігати файли: локально, S3, MinIO, DMS?; Підписання / відправка / обробка
 "status": "Signed",
</syntaxhighlight>
 |
 | 5.; | Записати відповідь API, дозволити повтор.; |-
| Webhook
| Отримання подій від ПТАХ, якщо підтримується.; |-
| ДПС
| Кінцевий отримувач податкової звітності.; v

* реалізувати background worker;
* реалізувати періодичне актуалізація статусів;
* реалізувати мапінг статусів;
* реалізувати обробку невідомих статусів.; f"Report {report_id} cannot be sent from status {report.status}"

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

 tax_request:
PTAH_BASE_URL=https://api.ptah.example
Приклад тіла запиту:
 report.status = TaxReportStatus.SENT
|-
| Polling
| Періодичне опитування API.ПТАХ.; !; # Хто має доступ до API key?; v

<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
<pre>
6.; | як ілюстрація K2 ERP або інша платформа.; Реальні коди статусів потрібно взяти з API-документації ПТАХ.; |-
| API.ПТАХ
| Інтеграційний API для роботи з документами.; |-
| Web framework
| FastAPI.; |}

=== 8.7.; Отримання квитанцій ===

 "document_number": "DECL-2026-0001",

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

 schemas.py
RECEIPT_DOWNLOAD_ENABLED=true
 def send_document(self, document_id: str) -> "PtahDocumentResponse":

=== 15.2.; Приклад worker-а ===

# Перевірити, що документ створено в ПТАХ.; |-
| API.ПТАХ
| API для інтеграції облікових систем із платформою ПТАХ.; Поле
!; |-
| document_date
| date
| Так
| Дата документа.; |-
| AC-16
| Документ відхилено.; Коментар
 title: "Декларація з ПДВ"
{
 }
Очікувана дія:
!; | У документі зберігається ptah_document_id.; |-
| Receipt Loader
| Завантажує квитанції та результати обробки.; 1.; audit_logger.log(
До першої версії не входить:
 number=report.document_number,
До MVP входить:
 - zip
 requires_receipt: true
APP_ENV=production
 client_secret: str | None = None

 "ptah_document_id": response.id,

щоб не створювати документ заново.; |}

 single_tax_declaration:

2.; №
|-
| AC-15
| Документ прийнято.; |-
| Підписання
| Результат, дата, raw-відповідь ПТАХ.; |-
| sent_to_receiver_at
| timestamp
| Дата відправки отримувачу.; | Використовувати retry та чергу задач.; # Які endpoint-и використовуються для отримання квитанцій?; |-
| report_id
| uuid
| ID документа.; Поле
 if new_status != report.status:
=== 21.3.; Підписання та відправка ===
!; | Повторити пізніше, повідомити адміністратора.; характеристика
!; |-
| DeliveryError
| Помилка доставки.;=== 21.4.; Статуси ===
|-
| AC-12
| Worker запускає синхронізацію.; |}

integrations/

Етап 8.; Production hardening

receipt_service.py

DATABASE_URL=postgresql+psycopg://user:password@db:5432/reports

17.1.; Типи помилок

AC-1 ERP передає інформаційні дані документа у Python-сервіс.; title: "Запит до податкової"
def sign_document(self, document_id: str) -> "PtahDocumentResponse":
)
; характеристика

from datetime import datetime, timezone

 audit_logger.log(
!; |-
| error
| Failed
| Помилка обробки.; | Сценарій передачі через ПТАХ потрібно підтвердити окремо.; | Файл зберігається у файловому сховищі.; report.sent_to_receiver_at = datetime.now(timezone.utc)

* реалізувати sign endpoint;
* реалізувати send endpoint;
* обробити помилки КЕП;
* обробити помилки відправки;
* фіксувати всі етапи в журналі.; |-
| sent
| Sent
| Документ відправлено.; # Який базовий URL API?; |-
| rejected_at
| timestamp
| Дата відхилення.; |-
| title
| varchar
| Назва документа.; |-
| period
| string
| Так
| Звітний період.; | Опційно.; Компонент
 event_type="SENT_VIA_PTAH",
5.; Подія


!; !; |-
| Повторна відправка
| Причина, користувач системи, дата.; "message": "Document sent to Ptah"
{{SEO
|title=Технічне завдання: Передача документів для звітності в податкову через ПТАХ для Python
|description=Технічне завдання на реалізацію Python-сервісу для передачі документів податкової звітності через інтеграцію з платформою ПТАХ.
|keywords=Python, ПТАХ, API.ПТАХ, електронна звітність, податкова звітність, ДПС, API, XML, КЕП, електронний документообіг, технічне завдання
}}
=== 15.1.; Фонове актуалізація ===
=== 8.2.; Валідація документа ===
 entity_id=report.id,
!; # Чи є собою тестове середовище?; |-
| WaitingForReceipt
| Очікується квитанція або результат обробки.; |-
| ERP / облікова платформа
| Джерело даних для звітності.; |-
| DuplicateDocumentError
| Документ вже був переданий.; |-
| API
| Програмний інтерфейс інтеграції.; Як адміністратор, 

* реалізувати створення документа;
* реалізувати збереження файлу;
* реалізувати валідацію;
* реалізувати статуси;
* реалізувати журнал подій.;</syntaxhighlight>

* webhook-інтеграція;
* інтеграційні функціональні можливості напряму з ДПС;
* власний компонент КЕП;
* складний UI;
* автоматичне актуалізація XSD;
* супровід всіх типів звітності;
* автоматичне створення декларацій з бухгалтерських даних.; |-
| AC-9
| Підписання виконано успішно.; характеристика
Як бухгалтер, 
Очікувана дія:
|-
| SentToPtah
| кожні 5 хвилин
|-
| CreatedInPtah
| кожні 5 хвилин
|-
| WaitingForSignature
| кожні 15 хвилин
|-
| Sent
| кожні 10 хвилин
|-
| SentToTax
| кожні 10 хвилин
|-
| WaitingForReceipt
| кожні 10 хвилин
|-
| ReceiptReceived
| кожні 30 хвилин або не перевіряти
|-
| Accepted / Rejected
| не перевіряти
|}

!; |-
| Скасування документа
| Причина, користувач системи, дата.; # Викликати метод ПТАХ для відправки.; # Отримати зовнішній ID документа в ПТАХ.; |-
| актуалізація статусу
| Старий статус, новий статус, raw-статус ПТАХ.; |-
| Status Sync Worker
| Фоновий бізнес-процес для актуалізація статусів.; | Інкапсулювати API в окремому PtahClient.;
- taxpayer_id varchar - AC-13 - Cancelled - taxpayer_name varchar - ValidationError Реалізується в межах цього ТЗ.; Тип помилки
tax_report_repository.update_status(

8.6.; Отримання статусів

POST /api/v1/tax-reports/{report_id}/resend

PTAH_API_KEY=********

Етап 7.; Квитанції та результати обробки

"new_status": new_status,

PTAH_COMPANY_CODE=12345678

 health.py

Перед передачею платформа повинна перевірити:
Задача вважається завершеною, якщо:

<syntaxhighlight lang="json">
=== 11.3.; Передача в ПТАХ ===
Очікувана відповідь:
<syntaxhighlight lang="json">
 v

!; # Чи потрібна супровід ФОП, юридичних осіб або обох варіантів?; Отримати ID документа в ПТАХ.; Дія системи
=== Етап 6.; Синхронізація статусів ===
 "metadata": {
|-
| created
| CreatedInPtah
| Документ створено в ПТАХ.; характеристика
 - pdf
</div>
 "raw_status": response.status,
PTAH_BASE_URL=https://api.ptah.example
!; Внутрішній статус
{
=== 8.8.; Повторна відправка ===

 tax_report_repository.py
{| class="wikitable"
== 2.; Область сфера застосування ==

<pre>

Як користувач системи, 

!; |-
| ПТАХ
| Платформа електронного документообігу.; |-
| Logging
| structlog або стандартний logging у JSON-форматі.; Очікуваний результат
платформа зберігає помилку та не втрачає документ.; Можливість саме подання податкової звітності до ДПС через ПТАХ потрібно підтвердити в офіційній API-документації або договорі з постачальником.; |- Accepted платформа завантажує квитанцію або результат обробки.; Компонент

13.1.; Логічний бізнес-процес

У системі створюється запис tax_reports.; file_format=report.file_format,
company_code: str | None = None

Рекомендована періодичність:

17.2.; Retry-логіка


</pre>
6.; Перевірити, що документ створено в ПТАХ.; Отримати документ з БД.;== 18.; Безпека ==

 send_response = ptah_client.send_document(report.ptah_document_id)

 v
!; Що зберігати
 pass
 except Exception as exc:

!; # Які endpoint-и використовуються для отримання статусів?; |-
| file_content_base64
| string
| Так
| Вміст документа у Base64.; актуалізація статусу в ERP
== 16.; Модель даних ==
== 26.; Приклад структури Python-проєкту ==
{

{

=== Етап 2.; Робота з документами ===
{| class="wikitable"
ПТАХ
|-
| API Layer
| REST API для прийому документів від ERP.; |-
| SentToTax
| Документ передано до ДПС, якщо такий сценарій підтримується.; * REST API для створення документа;
* збереження документа;
* базова валідація;
* Ptah Integration Client;
* передача документа в ПТАХ;
* збереження зовнішнього ID;
* ручний запуск синхронізації статусу;
* журнал подій;
* базова обробка помилок.; | Обов'язково для MVP.; | Зупинити відправку, повідомити адміністратора.; |-
| Tests
| pytest.; Оновити статус на Sent або Failed.; |-
| report_type
| varchar
| Тип звіту.; |}

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

 allowed_formats:
 sign_response = ptah_client.sign_document(report.ptah_document_id)
щоб скоротити час підготовки та подання документів.; Обов'язковість
!; щоб розуміти, чи документ створено, передано, підписано, відправлено, прийнято або відхилено.; Викликати метод підписання ПТАХ, якщо він доступний.; Підготувати метадані.; Критерій

}

!; |-
| created_at
| timestamp
| Дата створення.; платформа повинна завантажувати та зберігати:

* реалізувати завантаження квитанцій;
* реалізувати збереження PDF/XML/receipt-файлів;
* реалізувати прив'язку файлів до документа;
* реалізувати перегляд історії.; Критерій
 file_content=file_bytes,
 def get_document(self, document_id: str) -> "PtahDocumentResponse":
vat_declaration:
api_key: str | None = None
entity_id=report.id,
3.;

3.; |-

report_type string Так Тип звіту або документа.; Записати подію в журнал.; # Де виконується КЕП: у Python-сервісі, у ПТАХ або користувачем у веб-інтерфейсі?; характеристика

Python Tax Reporting Service

30.; Див.; додатково

- file_format string Так - receipt_received ReceiptReceived - size_bytes integer - Storage Layer - file_name varchar Назва файлу.; # Чи потрібно робити UI, чи тільки backend API?; Статус документа
"status": "SentToPtah",
retry_count: int = 3
}:

Очікувана відповідь:

- metadata object Ні Додаткові реквізити для ПТАХ.; Викликати метод відправки ПТАХ.; if report.status != TaxReportStatus.READY_TO_SEND:
  • помилок валідації;
  • неправильного API key;
  • відсутності прав доступу;
  • відхилення документа отримувачем;
  • дублювання документа;
  • некоректного формату файлу;
  • помилки КЕП через неправильний пароль.; |-
ORM SQLAlchemy.; audit_logger.log(
raise InvalidStatusError(
exceptions.py
raise InvalidStatusError("Report is not created in Ptah")
db.commit()

платформа повинна підтримувати один із режимів: електронного документообігу: створення забезпечується через істотно: API.ПТАХ публічно описується як API; додатково реалізовано підписання, відправка та отримання документів.; Термін

"taxpayer_name": report.taxpayer_name,
taxpayer_id string Так - ReceiptReceived - signed Signed Документ підписано.;=== 8.5.; Відправка документа ===

class PtahSettings(BaseSettings):

config.py

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

title=report.title,

Логічний endpoint Python-сервісу:

До області задачі входить:

; Пріоритет
pass

Логічний endpoint Python-сервісу:

</syntaxhighlight> Приклад змінних середовища:

== 7. User Story ==

 "taxpayer_id": report.taxpayer_id,
}
PTAH_API_KEY=********
'''Уточнення:''' значення статусів є собою попередніми.; | Статус документа змінюється на Sent.; 
 app/

 Dockerfile

Як бухгалтер, 
=== 11.1.; Створення документа ===
</pre>

 report.status = TaxReportStatus.SENT_TO_PTAH

{| class="wikitable"
=== 6.2.; Основні компоненти Python-сервісу ===
Очікувана відповідь:
!; * повна заміна інтерфейсу ПТАХ;
* власна реалізація подання напряму до API ДПС;
* власна реалізація КЕП, якщо підписання виконується на стороні ПТАХ;
* автоматичне актуалізація всіх XSD-схем;
* повноцінний UI для бухгалтера;
* автоматична бухгалтерська перевірка сум;
* супровід всіх типів податкової, статистичної та фінансової звітності.; |-
| taxpayer_name
| string
| Так
| Назва компанії або ПІБ ФОП.; Отримати файл зі сховища.; |-
| Signed
| Документ підписано.; |}

 pass

я хочу бачити журнал API-запитів і відповідей, 

[[Категорія:API]]
</div>
 metadata={
Повторна відправка не дозволена для статусів:
|-
| ValidationError
| Некоректні інформаційні дані документа.; Тип
=== 19.2.; Конфігурація типів документів ===
8.; Поле
 "message": "Document signed via Ptah"
 tax_reports.py
=== 13.2.; Приклад Python-логіки ===
v

</syntaxhighlight>

 requires_signature: true

{| class="wikitable"
PTAH_RETRY_COUNT=3
== 15.; Робота зі статусами ==
 pyproject.toml
я хочу передати документ звітності в ПТАХ без ручного імпорту, 
</pre>
=== 7.6.; Технічний аудит ===
<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">

 base_url: str

я хочу отримати квитанції або результати обробки в ERP, 
[[Категорія:Технічні завдання]]
 report.ptah_document_id

 "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
2.; |-
| Ручне підписання
| користувач системи підписує документ у веб-інтерфейсі або клієнті ПТАХ.; Критерій
[[Категорія:Інтеграції]]
=== 19.1.; Змінні середовища ===
!; | платформа повертає список помилок валідації.; "message": "Document created"

* реалізувати endpoint send-to-ptah;
* зберігати ptah_document_id;
* оновлювати статуси;
* логувати API-взаємодію.; |-
| period
| varchar
| Звітний період.; requires_signature: true
'''Технічний стек:''' Python 3.11+, FastAPI, PostgreSQL, SQLAlchemy, Alembic, httpx, Pydantic, Celery/RQ/APScheduler, Docker.; |-
| Sent
| Документ відправлено отримувачу.; "file_format": "xml",
!; |-
| AC-5
| API.ПТАХ повертає успішну відповідь.; |-
| report_id
| uuid
| ID документа.; Квитанції / статуси
3.; |-
| Помилки авторизації
| Доступ до API має змогу бути неправильним або простроченим.; |-
| CreatedInPtah
| Документ створено в ПТАХ.; інформаційні дані для звітності або готовий XML
!; |-
| Migrations
| Alembic.; |-
| FileStorageError
| Неможливо прочитати або записати файл.; |-
| AC-7
| Документ вже був переданий.; "period": report.period,
 "document_date": "2026-04-15",
 response = ptah_client.upload_tax_report(payload)
)

<syntaxhighlight lang="python"> 2.; |-

Document Builder - Персональні інформаційні дані }
pass

* Python-сервіс розгортається через Docker;
* API створення документа функціонує;
* документ зберігається у БД та файловому сховищі;
* документ проходить валідацію;
* документ передається в ПТАХ;
* зовнішній ID документа зберігається;
* статус документа оновлюється;
* помилки API обробляються;
* retry-механізм функціонує;
* журнал подій заповнюється;
* написані unit-тести для ключових сервісів;
* написані інтеграційні тести для PtahClient з mock API;
* документація для запуску додана в README;
* фінальні endpoint-и ПТАХ винесені в конфігурацію;
* отримано підтвердження сценарію подання звітності до ДПС через ПТАХ або зафіксовано альтернативний сценарій.; {