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

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

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


SEO title: Технічне завдання: Передача документів для звітності в податкову через ПТАХ для Python SEO description: Технічне завдання на реалізацію Python-сервісу для передачі документів податкової звітності через інтеграцію з платформою ПТАХ. SEO keywords: Python, ПТАХ, API.ПТАХ, електронна звітність, податкова звітність, ДПС, API, XML, КЕП, електронний документообіг, технічне завдання Alternative to:


Головна ідея: розробити Python-сервіс, який формує, перевіряє, передає та контролює документи звітності через інтеграцію з платформою ПТАХ / API.ПТАХ.

Важливо: API.ПТАХ публічно описується як API для електронного документообігу: створення, підписання, відправка та отримання документів. Можливість саме подання податкової звітності до ДПС через ПТАХ потрібно підтвердити в офіційній API-документації або договорі з постачальником.

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

1. Мета

Метою задачі є створення Python-сервісу для передачі документів звітності через платформу ПТАХ.

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

  • прийом даних звітності з ERP / облікової системи;
  • формування або прийом готового XML-документа;
  • перевірку документа перед передачею;
  • передачу документа в ПТАХ;
  • запуск підписання документа, якщо це підтримується API;
  • запуск відправки документа, якщо це підтримується API;
  • отримання зовнішнього ID документа;
  • синхронізацію статусів;
  • отримання квитанцій або результатів обробки;
  • збереження історії передачі;
  • обробку помилок;
  • повторну відправку;
  • журналювання всіх технічних і бізнес-подій.

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

Функціонал використовується для автоматизації передачі документів звітності з ERP або облікової системи до ПТАХ.

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

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

До першої версії не входить:

  • повна заміна інтерфейсу ПТАХ;
  • власна реалізація подання напряму до API ДПС;
  • власна реалізація КЕП, якщо підписання виконується на стороні ПТАХ;
  • автоматичне оновлення всіх XSD-схем;
  • повноцінний UI для бухгалтера;
  • автоматична бухгалтерська перевірка сум;
  • підтримка всіх типів податкової, статистичної та фінансової звітності.

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

Компонент Призначення Коментар
ПТАХ Платформа електронного документообігу та обміну юридично значущими документами. Основна система для передачі документів.
API.ПТАХ Інтеграційний API для роботи з документами. Потрібна офіційна API-документація та доступ.
Python-сервіс Інтеграційний шар між ERP та ПТАХ. Реалізується в межах цього ТЗ.
ERP / облікова система Джерело даних для звітності. Наприклад K2 ERP або інша система.
ДПС Кінцевий отримувач податкової звітності. Сценарій передачі через ПТАХ потрібно підтвердити окремо.

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

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

  • доступ до платформи ПТАХ;
  • активований доступ до API.ПТАХ;
  • базовий URL API;
  • спосіб авторизації;
  • API key / token / client credentials;
  • технічну документацію endpoint-ів;
  • перелік доступних типів документів;
  • підтвердження можливості передачі звітності до ДПС через ПТАХ;
  • формат передачі файлів;
  • формат метаданих документа;
  • правила створення документа в ПТАХ;
  • правила підписання документа;
  • правила відправки документа;
  • правила отримання статусів;
  • правила отримання квитанцій;
  • тестове середовище, якщо доступне;
  • технічний контакт з боку постачальника ПТАХ.

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

Термін Опис
Python-сервіс Окремий backend-сервіс або модуль, який виконує інтеграцію з ПТАХ.
ПТАХ Платформа електронного документообігу.
API.ПТАХ API для інтеграції облікових систем із платформою ПТАХ.
ДПС Державна податкова служба України.
XML Формат електронного документа звітності.
XSD Схема перевірки XML-документа.
КЕП Кваліфікований електронний підпис.
API Програмний інтерфейс інтеграції.
Webhook Механізм отримання подій від зовнішньої системи.
Polling Періодичне опитування зовнішнього API.
Квитанція Підтвердження прийняття, відхилення або обробки звіту.

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

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

ERP / Accounting System
        |
        | 1. Дані для звітності або готовий XML
        v
Python Tax Reporting Service
        |
        | 2. Валідація та збереження документа
        v
Ptah Integration Adapter
        |
        | 3. Передача документа через API.ПТАХ
        v
ПТАХ
        |
        | 4. Підписання / відправка / обробка
        v
ДПС або інший отримувач
        |
        | 5. Квитанції / статуси
        v
ПТАХ
        |
        | 6. Синхронізація статусів
        v
Python Tax Reporting Service
        |
        | 7. Оновлення статусу в ERP
        v
ERP / Accounting System

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

Компонент Опис
API Layer REST API для прийому документів від ERP.
Document Builder Формує XML або приймає готовий файл.
Validation Layer Перевіряє реквізити, структуру та статус документа.
Ptah Client Python-клієнт для роботи з API.ПТАХ.
Status Sync Worker Фоновий процес для оновлення статусів.
Receipt Loader Завантажує квитанції та результати обробки.
Storage Layer Зберігає документи, квитанції, статуси та логи.
Audit Logger Фіксує всі дії користувачів і системи.

7. User Story

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

Як користувач ERP, я хочу передати документ звітності в ПТАХ без ручного імпорту, щоб скоротити час підготовки та подання документів.

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

Як бухгалтер, я хочу ініціювати підписання та відправку документа через ПТАХ, щоб не виконувати ці дії вручну, якщо це підтримується API.

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

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

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

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

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

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

7.6. Технічний аудит

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

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

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

Python-сервіс повинен приймати документ від ERP.

Мінімальний набір вхідних даних:

Поле Тип Обов'язковість Опис
taxpayer_id string Так РНОКПП або ЄДРПОУ платника.
taxpayer_name string Так Назва компанії або ПІБ ФОП.
report_type string Так Тип звіту або документа.
period string Так Звітний період.
document_number string Так Номер документа.
document_date date Так Дата документа.
file_format string Так XML, PDF, ZIP або інший підтримуваний формат.
file_content_base64 string Так Вміст документа у Base64.
metadata object Ні Додаткові реквізити для ПТАХ.

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

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

  • наявність обов'язкових полів;
  • коректність РНОКПП або ЄДРПОУ;
  • коректність звітного періоду;
  • наявність файлу;
  • допустимий формат файлу;
  • розмір файлу;
  • коректність імені файлу;
  • відповідність XML-структурі;
  • відповідність XSD, якщо схема доступна;
  • відсутність дубля документа;
  • наявність налаштувань інтеграції з ПТАХ.

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

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

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

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

Очікувана дія:

  1. Отримати документ із локальної БД.
  2. Перевірити статус документа.
  3. Отримати файл зі сховища.
  4. Підготувати метадані.
  5. Викликати Ptah Integration Adapter.
  6. Отримати зовнішній ID документа в ПТАХ.
  7. Зберегти зовнішній ID у БД.
  8. Оновити статус документа.
  9. Записати подію в журнал.

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

Система повинна підтримувати один із режимів:

Режим Опис Пріоритет
Підписання в ПТАХ Документ передається в ПТАХ, а підписання виконується засобами платформи. Основний режим, якщо підтримується API.
Підписання в Python-сервісі Python-сервіс підписує документ до передачі в ПТАХ. Опційно.
Ручне підписання Користувач підписує документ у веб-інтерфейсі або клієнті ПТАХ. Резервний режим.

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

Якщо API.ПТАХ підтримує відповідний метод, Python-сервіс повинен ініціювати відправку документа отримувачу.

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

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

Очікувана дія:

  1. Перевірити, що документ створено в ПТАХ.
  2. Перевірити, що документ підписано або готовий до підписання.
  3. Викликати метод ПТАХ для відправки.
  4. Оновити статус на Sent.
  5. Записати подію в журнал.

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

Система повинна підтримувати два способи оновлення статусів:

Спосіб Опис Пріоритет
Polling Періодичне опитування API.ПТАХ. Обов'язково для MVP.
Webhook Отримання подій від ПТАХ, якщо підтримується. Опційно.

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

Система повинна завантажувати та зберігати:

  • квитанцію про отримання;
  • квитанцію про прийняття;
  • квитанцію про відхилення;
  • підписаний документ;
  • PDF-візуалізацію, якщо доступна;
  • технічний протокол обробки, якщо доступний;
  • raw-відповідь ПТАХ.

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

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

  • ValidationError;
  • Failed;
  • Rejected;
  • DeliveryError;
  • NeedResend.

Повторна відправка не дозволена для статусів:

  • Accepted;
  • Sent;
  • WaitingForReceipt;
  • SentToPtah;
  • WaitingForSignature.

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

Внутрішній статус Опис
Draft Документ створено, але ще не готовий до передачі.
Generated Файл документа сформовано.
ValidationError Документ не пройшов перевірку.
ReadyToSend Документ готовий до передачі.
Sending Документ передається в ПТАХ.
SentToPtah Документ успішно передано в ПТАХ.
CreatedInPtah Документ створено в ПТАХ.
WaitingForSignature Документ очікує підписання.
Signed Документ підписано.
Sent Документ відправлено отримувачу.
SentToTax Документ передано до ДПС, якщо такий сценарій підтримується.
WaitingForReceipt Очікується квитанція або результат обробки.
ReceiptReceived Отримано квитанцію або результат обробки.
Accepted Документ прийнято.
Rejected Документ відхилено.
DeliveryError Помилка доставки.
Failed Технічна помилка.
Cancelled Документ скасовано.

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

Фінальний мапінг статусів потрібно побудувати після отримання офіційного довідника статусів API.ПТАХ.

Попередній логічний мапінг:

Статус ПТАХ Внутрішній статус Опис
created CreatedInPtah Документ створено в ПТАХ.
uploaded SentToPtah Документ завантажено в ПТАХ.
waiting_signature WaitingForSignature Очікується підпис.
signed Signed Документ підписано.
sent Sent Документ відправлено.
sent_to_tax SentToTax Документ передано до ДПС, якщо підтримується.
waiting_receipt WaitingForReceipt Очікується квитанція або результат обробки.
receipt_received ReceiptReceived Отримано квитанцію або результат обробки.
accepted Accepted Документ прийнято.
rejected Rejected Документ відхилено.
error Failed Помилка обробки.

Уточнення: значення статусів є попередніми. Реальні коди статусів потрібно взяти з API-документації ПТАХ.

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

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

POST /api/v1/tax-reports

Приклад тіла запиту:

{
  "taxpayer_id": "1234567890",
  "taxpayer_name": "ФОП Іваненко Іван Іванович",
  "report_type": "single_tax_declaration",
  "period": "2026-Q1",
  "document_number": "DECL-2026-0001",
  "document_date": "2026-04-15",
  "file_format": "xml",
  "file_content_base64": "BASE64_XML_CONTENT",
  "metadata": {
    "source_system": "K2 ERP",
    "created_by": "user@example.com"
  }
}

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

{
  "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
  "status": "Generated",
  "message": "Document created"
}

11.2. Перевірка документа

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

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

{
  "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
  "status": "ReadyToSend",
  "errors": []
}

11.3. Передача в ПТАХ

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

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

{
  "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
  "status": "SentToPtah",
  "ptah_document_id": "external-document-id",
  "message": "Document sent to Ptah"
}

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

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

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

{
  "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
  "status": "Signed",
  "message": "Document signed via Ptah"
}

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

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

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

{
  "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
  "status": "Sent",
  "message": "Document sent via Ptah"
}

11.6. Оновлення статусу

POST /api/v1/tax-reports/{report_id}/sync-status

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

{
  "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
  "old_status": "SentToPtah",
  "new_status": "WaitingForSignature",
  "ptah_status": "waiting_signature"
}

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

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

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

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

11.9. Завантаження квитанцій

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

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

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

12. Ptah Integration Client

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

Ptah Integration Client — це Python-клас або пакет, який інкапсулює роботу з API.ПТАХ.

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

class PtahClient:
    def create_document(self, document: "DocumentPayload") -> "PtahDocumentResponse":
        pass

    def upload_tax_report(self, document: "DocumentPayload") -> "PtahDocumentResponse":
        pass

    def get_document(self, document_id: str) -> "PtahDocumentResponse":
        pass

    def get_document_status(self, document_id: str) -> "PtahStatusResponse":
        pass

    def sign_document(self, document_id: str) -> "PtahDocumentResponse":
        pass

    def send_document(self, document_id: str) -> "PtahDocumentResponse":
        pass

    def download_original(self, document_id: str) -> bytes:
        pass

    def download_signed_document(self, document_id: str) -> bytes:
        pass

    def download_receipts(self, document_id: str) -> list[bytes]:
        pass

    def cancel_document(self, document_id: str, reason: str) -> "PtahDocumentResponse":
        pass

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

from pydantic_settings import BaseSettings


class PtahSettings(BaseSettings):
    base_url: str
    api_key: str | None = None
    client_id: str | None = None
    client_secret: str | None = None
    company_code: str | None = None
    timeout_seconds: int = 30
    retry_count: int = 3
    retry_backoff_seconds: int = 5
    verify_ssl: bool = True

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

PTAH_BASE_URL=https://api.ptah.example
PTAH_API_KEY=********
PTAH_CLIENT_ID=********
PTAH_CLIENT_SECRET=********
PTAH_COMPANY_CODE=12345678
PTAH_TIMEOUT_SECONDS=30
PTAH_RETRY_COUNT=3
PTAH_RETRY_BACKOFF_SECONDS=5

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

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

13.1. Логічний процес

1. Отримати документ з БД.
2. Перевірити, що документ має статус ReadyToSend.
3. Отримати файл зі сховища.
4. Підготувати метадані.
5. Викликати PtahClient.upload_tax_report().
6. Отримати ID документа в ПТАХ.
7. Зберегти ID у локальній БД.
8. Оновити статус на SentToPtah.
9. Записати подію в журнал.

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

from uuid import UUID
from datetime import datetime, timezone


def send_report_to_ptah(report_id: UUID, db: "Session") -> "TaxReport":
    report = tax_report_repository.get_by_id(db, report_id)

    if report.status != TaxReportStatus.READY_TO_SEND:
        raise InvalidStatusError(
            f"Report {report_id} cannot be sent from status {report.status}"
        )

    file_bytes = file_storage.read(report.file_path)

    payload = DocumentPayload(
        title=report.title,
        number=report.document_number,
        date=report.document_date,
        file_name=report.file_name,
        file_content=file_bytes,
        file_format=report.file_format,
        metadata={
            "taxpayer_id": report.taxpayer_id,
            "taxpayer_name": report.taxpayer_name,
            "report_type": report.report_type,
            "period": report.period,
            "source_system": report.source_system,
        },
    )

    response = ptah_client.upload_tax_report(payload)

    report.ptah_document_id = response.id
    report.status = TaxReportStatus.SENT_TO_PTAH
    report.sent_at = datetime.now(timezone.utc)

    audit_logger.log(
        entity_id=report.id,
        event_type="SENT_TO_PTAH",
        details={
            "ptah_document_id": response.id,
            "raw_status": response.status,
        },
    )

    db.commit()
    return report

14. Підписання та відправка через ПТАХ

14.1. Логічний процес підписання

1. Перевірити, що документ створено в ПТАХ.
2. Перевірити, що документ не був відправлений раніше.
3. Викликати метод підписання ПТАХ, якщо він доступний.
4. Отримати результат підписання.
5. Оновити статус на Signed або Failed.
6. Записати подію в журнал.

14.2. Логічний процес відправки

1. Перевірити, що документ підписано.
2. Викликати метод відправки ПТАХ.
3. Отримати результат відправки.
4. Оновити статус на Sent або Failed.
5. Запустити очікування квитанцій.
6. Записати подію в журнал.

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

def sign_and_send_report(report_id: UUID, db: "Session") -> "TaxReport":
    report = tax_report_repository.get_by_id(db, report_id)

    if not report.ptah_document_id:
        raise InvalidStatusError("Report is not created in Ptah")

    if report.status not in {
        TaxReportStatus.SENT_TO_PTAH,
        TaxReportStatus.CREATED_IN_PTAH,
        TaxReportStatus.WAITING_FOR_SIGNATURE,
    }:
        raise InvalidStatusError(
            f"Report {report_id} cannot be signed from status {report.status}"
        )

    sign_response = ptah_client.sign_document(report.ptah_document_id)

    report.status = TaxReportStatus.SIGNED
    audit_logger.log(
        entity_id=report.id,
        event_type="SIGNED_IN_PTAH",
        details={"raw_status": sign_response.status},
    )

    send_response = ptah_client.send_document(report.ptah_document_id)

    report.status = TaxReportStatus.SENT
    report.sent_to_receiver_at = datetime.now(timezone.utc)

    audit_logger.log(
        entity_id=report.id,
        event_type="SENT_VIA_PTAH",
        details={"raw_status": send_response.status},
    )

    db.commit()
    return report

15. Робота зі статусами

15.1. Фонове оновлення

Система повинна мати background worker, який періодично оновлює статуси документів.

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

Статус документа Інтервал перевірки
SentToPtah кожні 5 хвилин
CreatedInPtah кожні 5 хвилин
WaitingForSignature кожні 15 хвилин
Sent кожні 10 хвилин
SentToTax кожні 10 хвилин
WaitingForReceipt кожні 10 хвилин
ReceiptReceived кожні 30 хвилин або не перевіряти
Accepted / Rejected не перевіряти

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

def sync_pending_reports() -> None:
    reports = tax_report_repository.get_reports_for_sync()

    for report in reports:
        try:
            ptah_status = ptah_client.get_document_status(
                report.ptah_document_id
            )

            new_status = status_mapper.map_ptah_status(ptah_status)

            if new_status != report.status:
                old_status = report.status

                tax_report_repository.update_status(
                    report_id=report.id,
                    new_status=new_status,
                    raw_status=ptah_status.raw_status,
                )

                audit_logger.log(
                    entity_id=report.id,
                    event_type="STATUS_CHANGED",
                    details={
                        "old_status": old_status,
                        "new_status": new_status,
                        "ptah_status": ptah_status.raw_status,
                    },
                )

        except Exception as exc:
            audit_logger.log(
                entity_id=report.id,
                event_type="STATUS_SYNC_FAILED",
                details={"error": str(exc)},
            )

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

16.1. tax_reports

Поле Тип Опис
id uuid Внутрішній ID документа.
taxpayer_id varchar РНОКПП або ЄДРПОУ.
taxpayer_name varchar Назва платника.
report_type varchar Тип звіту.
period varchar Звітний період.
document_number varchar Номер документа.
document_date date Дата документа.
title varchar Назва документа.
file_name varchar Назва файлу.
file_path varchar Шлях до файлу у сховищі.
file_format varchar XML, PDF, ZIP тощо.
status varchar Внутрішній статус.
ptah_document_id varchar ID документа у ПТАХ.
ptah_raw_status varchar Останній raw-статус ПТАХ.
last_sync_at timestamp Дата останньої синхронізації.
sent_at timestamp Дата передачі в ПТАХ.
sent_to_receiver_at timestamp Дата відправки отримувачу.
sent_to_tax_at timestamp Дата відправки до ДПС, якщо підтримується.
accepted_at timestamp Дата прийняття.
rejected_at timestamp Дата відхилення.
error_message text Остання помилка.
source_system varchar ERP або інша система-джерело.
created_at timestamp Дата створення.
updated_at timestamp Дата оновлення.

16.2. tax_report_events

Поле Тип Опис
id uuid ID події.
report_id uuid ID документа.
event_type varchar Тип події.
old_status varchar Попередній статус.
new_status varchar Новий статус.
payload jsonb Технічні дані події.
created_by varchar Користувач або system.
created_at timestamp Дата події.

16.3. tax_report_files

Поле Тип Опис
id uuid ID файлу.
report_id uuid ID документа.
file_type varchar original, signed, pdf, receipt_1, receipt_2, error_protocol.
file_name varchar Назва файлу.
file_path varchar Шлях до файлу.
content_type varchar MIME-тип.
size_bytes integer Розмір файлу.
created_at timestamp Дата створення.

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

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

Тип помилки Опис Дія системи
ValidationError Некоректні дані документа. Не відправляти документ, показати список помилок.
PtahAuthError Помилка авторизації в API.ПТАХ. Зупинити відправку, повідомити адміністратора.
PtahApiError API повернув помилку. Записати відповідь API, дозволити повтор.
PtahTimeoutError Перевищено час очікування. Виконати retry.
PtahUnavailableError Платформа ПТАХ недоступна. Повторити пізніше, повідомити адміністратора.
DuplicateDocumentError Документ вже був переданий. Заборонити повтор без підтвердження.
FileStorageError Неможливо прочитати або записати файл. Зафіксувати помилку, повідомити адміністратора.
StatusMappingError Невідомий статус від ПТАХ. Зберегти raw-статус, створити подію UnknownStatus.
SignatureError Помилка підписання документа. Зберегти помилку, дозволити повторне підписання.

17.2. Retry-логіка

Retry застосовується для:

  • timeout;
  • тимчасової недоступності API.ПТАХ;
  • HTTP 429;
  • HTTP 500;
  • HTTP 502;
  • HTTP 503;
  • HTTP 504;
  • тимчасових мережевих помилок.

Retry не застосовується для:

  • помилок валідації;
  • неправильного API key;
  • відсутності прав доступу;
  • відхилення документа отримувачем;
  • дублювання документа;
  • некоректного формату файлу;
  • помилки КЕП через неправильний пароль.

18. Безпека

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

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

19. Налаштування

19.1. Змінні середовища

APP_ENV=production
DATABASE_URL=postgresql+psycopg://user:password@db:5432/reports
FILE_STORAGE_PATH=/data/tax-reports

PTAH_BASE_URL=https://api.ptah.example
PTAH_API_KEY=********
PTAH_CLIENT_ID=********
PTAH_CLIENT_SECRET=********
PTAH_COMPANY_CODE=12345678
PTAH_TIMEOUT_SECONDS=30
PTAH_RETRY_COUNT=3
PTAH_RETRY_BACKOFF_SECONDS=5

STATUS_SYNC_ENABLED=true
STATUS_SYNC_INTERVAL_SECONDS=300
RECEIPT_DOWNLOAD_ENABLED=true

19.2. Конфігурація типів документів

document_types:
  single_tax_declaration:
    title: "Декларація платника єдиного податку"
    allowed_formats:
      - xml
      - pdf
    requires_signature: true
    requires_receipt: true

  tax_request:
    title: "Запит до податкової"
    allowed_formats:
      - xml
      - pdf
    requires_signature: true
    requires_receipt: true

  unified_report:
    title: "Об'єднана звітність"
    allowed_formats:
      - xml
      - zip
    requires_signature: true
    requires_receipt: true

  vat_declaration:
    title: "Декларація з ПДВ"
    allowed_formats:
      - xml
      - zip
    requires_signature: true
    requires_receipt: true

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

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

Подія Що зберігати
Створення документа ID, користувач, дата, тип документа.
Валідація Результат, список помилок.
Передача в ПТАХ Endpoint, час, статус відповіді, зовнішній ID.
Підписання Результат, дата, raw-відповідь ПТАХ.
Відправка Результат, дата, raw-відповідь ПТАХ.
Помилка API HTTP-код, тіло відповіді, correlation ID.
Оновлення статусу Старий статус, новий статус, raw-статус ПТАХ.
Завантаження квитанції Тип файлу, назва, дата.
Повторна відправка Причина, користувач, дата.
Скасування документа Причина, користувач, дата.

21. Acceptance Criteria

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

Критерій Очікуваний результат
AC-1 ERP передає дані документа у Python-сервіс. У системі створюється запис tax_reports.
AC-2 Передано файл документа. Файл зберігається у файловому сховищі.
AC-3 Передано некоректні дані. Система повертає список помилок валідації.

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

Критерій Очікуваний результат
AC-4 Документ має статус ReadyToSend. Система дозволяє передачу в ПТАХ.
AC-5 API.ПТАХ повертає успішну відповідь. У документі зберігається ptah_document_id.
AC-6 API.ПТАХ повертає помилку. Система зберігає помилку та не втрачає документ.
AC-7 Документ вже був переданий. Система не створює дубль без окремого підтвердження.

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

Критерій Очікуваний результат
AC-8 Документ створено в ПТАХ. Система дозволяє ініціювати підписання, якщо це підтримується API.
AC-9 Підписання виконано успішно. Статус документа змінюється на Signed.
AC-10 Документ підписано. Система дозволяє відправку документа.
AC-11 Відправка виконана успішно. Статус документа змінюється на Sent.

21.4. Статуси

Критерій Очікуваний результат
AC-12 Worker запускає синхронізацію. Статуси документів оновлюються автоматично.
AC-13 ПТАХ повертає новий статус. Внутрішній статус документа змінюється.
AC-14 ПТАХ повертає невідомий статус. Raw-статус зберігається, створюється подія UnknownStatus.

21.5. Квитанції та файли

Критерій Очікуваний результат
AC-15 Документ прийнято. Система завантажує квитанцію або результат обробки.
AC-16 Документ відхилено. Система зберігає причину відхилення.
AC-17 Користувач відкриває картку документа. Він бачить всі пов'язані файли та статуси.

22. MVP

До MVP входить:

  • REST API для створення документа;
  • збереження документа;
  • базова валідація;
  • Ptah Integration Client;
  • передача документа в ПТАХ;
  • збереження зовнішнього ID;
  • ручний запуск синхронізації статусу;
  • журнал подій;
  • базова обробка помилок.

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

  • webhook-інтеграція;
  • інтеграція напряму з ДПС;
  • власний модуль КЕП;
  • складний UI;
  • автоматичне оновлення XSD;
  • підтримка всіх типів звітності;
  • автоматичне створення декларацій з бухгалтерських даних.

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

Етап 1. Базова структура Python-сервісу

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

Етап 2. Робота з документами

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

Етап 3. Ptah Integration Client

  • реалізувати авторизацію;
  • реалізувати upload_tax_report;
  • реалізувати create_document;
  • реалізувати get_document_status;
  • реалізувати download_document;
  • реалізувати download_receipts;
  • реалізувати обробку помилок;
  • реалізувати retry.

Етап 4. Передача документів

  • реалізувати endpoint send-to-ptah;
  • зберігати ptah_document_id;
  • оновлювати статуси;
  • логувати API-взаємодію.

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

  • реалізувати sign endpoint;
  • реалізувати send endpoint;
  • обробити помилки КЕП;
  • обробити помилки відправки;
  • фіксувати всі етапи в журналі.

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

  • реалізувати background worker;
  • реалізувати періодичне оновлення статусів;
  • реалізувати мапінг статусів;
  • реалізувати обробку невідомих статусів.

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

  • реалізувати завантаження квитанцій;
  • реалізувати збереження PDF/XML/receipt-файлів;
  • реалізувати прив'язку файлів до документа;
  • реалізувати перегляд історії.

Етап 8. Production hardening

  • додати Dockerfile;
  • додати docker-compose;
  • додати structured logging;
  • додати metrics;
  • додати alerting;
  • додати rate limiting;
  • додати security review.

24. Ризики

Ризик Опис Як зменшити
Непідтверджений сценарій подання звітності до ДПС Публічно API.ПТАХ описаний як API для ЕДО, але сценарій податкової звітності потрібно підтвердити. Отримати офіційну API-документацію та підтвердження від постачальника.
Неповна або закрита API-документація Частина методів може бути доступна лише за договором або в окремому тарифі. Отримати офіційну документацію та тестовий доступ.
Зміна API Endpoint-и або формати відповіді можуть змінюватися. Інкапсулювати API в окремому PtahClient.
Невідомі статуси ПТАХ може повертати статуси, яких немає в системі. Зберігати raw-статус та мати UnknownStatus.
Дублювання документів Повторна відправка може створити дубль. Перевіряти ptah_document_id перед відправкою.
Помилки авторизації Доступ до API може бути неправильним або простроченим. Додати healthcheck інтеграції та повідомлення адміністратору.
Недоступність ПТАХ Платформа або мережа можуть бути тимчасово недоступні. Використовувати retry та чергу задач.
Помилки КЕП Можливі проблеми з ключами, паролями або сертифікатами. Відображати зрозумілу помилку та дозволяти повторне підписання.
Персональні дані Документи можуть містити РНОКПП, ЄДРПОУ, фінансові дані. Маскувати логи та обмежити доступ.

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

  1. Який саме продукт використовується: ПТАХ, API.ПТАХ або інтеграція через інший продукт Linkos Group?
  2. Чи підтримує ПТАХ сценарій подання податкової звітності до ДПС?
  3. Який базовий URL API?
  4. Який механізм авторизації використовується?
  5. Які endpoint-и використовуються для створення документа?
  6. Які endpoint-и використовуються для підписання?
  7. Які endpoint-и використовуються для відправки?
  8. Які endpoint-и використовуються для отримання статусів?
  9. Які endpoint-и використовуються для отримання квитанцій?
  10. Який формат документа підтримується: XML, PDF, ZIP, JSON?
  11. Чи Python-сервіс має сам формувати XML, чи отримує готовий XML з ERP?
  12. Де виконується КЕП: у Python-сервісі, у ПТАХ або користувачем у веб-інтерфейсі?
  13. Чи потрібна підтримка ФОП, юридичних осіб або обох варіантів?
  14. Які типи звітів підтримуються першими?
  15. Чи є тестове середовище?
  16. Чи підтримуються webhook-и?
  17. Який SLA по оновленню статусів?
  18. Де зберігати файли: локально, S3, MinIO, DMS?
  19. Хто має доступ до API key?
  20. Чи потрібно робити UI, чи тільки backend API?

26. Приклад структури Python-проєкту

tax_reporting_ptah_service/
  app/
    main.py
    config.py
    api/
      routes/
        tax_reports.py
        health.py
    core/
      security.py
      logging.py
      exceptions.py
    db/
      session.py
      models.py
      migrations/
    services/
      tax_report_service.py
      validation_service.py
      status_sync_service.py
      receipt_service.py
      signing_service.py
    integrations/
      ptah/
        client.py
        schemas.py
        status_mapper.py
        exceptions.py
    repositories/
      tax_report_repository.py
      event_repository.py
      file_repository.py
    workers/
      sync_statuses.py
      download_receipts.py
    storage/
      file_storage.py
  tests/
    unit/
    integration/
  Dockerfile
  docker-compose.yml
  pyproject.toml
  README.md

27. Технічні вимоги до Python

Компонент Рекомендація
Python 3.11 або вище.
Web framework FastAPI.
HTTP client httpx.
Validation Pydantic.
ORM SQLAlchemy.
DB PostgreSQL.
Migrations Alembic.
Background jobs Celery, RQ або APScheduler.
Tests pytest.
Containers Docker.
Logging structlog або стандартний logging у JSON-форматі.

28. Definition of Done

Задача вважається завершеною, якщо:

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

29. Джерела

30. Див. також