Технічне завдання: передача документів для звітності в податкову через Медок для Python
Головна ідея: розробити Python-сервіс, який формує, перевіряє, передає та контролює документи податкової звітності через інтеграцію з M.E.Doc / Medoc REST API.
Важливо: M.E.Doc REST API використовується як інтеграційний шар між обліковою системою та програмою M.E.Doc. Для повної реалізації потрібно мати ліцензію/модуль інтеграції, налаштований M.E.Doc, доступ до REST API та офіційну документацію методів.
Технічний стек: Python 3.11+, FastAPI, PostgreSQL, SQLAlchemy, Alembic, httpx, Pydantic, Celery/RQ/APScheduler, Docker.
1. Мета
Метою задачі є створення Python-сервісу для передачі документів податкової звітності через M.E.Doc.
Сервіс повинен забезпечити:
- прийом даних звітності з ERP / облікової системи;
- формування або прийом готового XML-документа;
- перевірку документа перед передачею;
- передачу документа в M.E.Doc;
- запуск підписання та відправки через M.E.Doc, якщо підтримується API;
- отримання зовнішнього ID документа;
- синхронізацію статусів;
- отримання квитанцій або результатів обробки;
- збереження історії передачі;
- обробку помилок;
- повторну відправку;
- журналювання всіх технічних і бізнес-подій.
2. Область застосування
Функціонал використовується для автоматизації передачі документів податкової звітності з ERP або облікової системи до M.E.Doc з подальшим поданням до ДПС.
До області задачі входить:
- створення Python API для прийому документів;
- створення клієнта інтеграції з M.E.Doc REST API;
- формування XML або прийом готового XML;
- збереження документа;
- перевірка обов'язкових реквізитів;
- передача документа в M.E.Doc;
- запуск підписання / відправки через M.E.Doc;
- отримання статусів;
- отримання квитанцій;
- журнал подій;
- retry-механізм;
- захист API-ключів і службових доступів;
- інтеграція з ERP.
До першої версії не входить:
- повна заміна інтерфейсу M.E.Doc;
- власна реалізація подання напряму до API ДПС;
- власна реалізація КЕП, якщо підписання виконується у M.E.Doc;
- автоматичне оновлення всіх XSD-схем;
- повноцінний UI для бухгалтера;
- автоматична бухгалтерська перевірка сум;
- підтримка всіх типів податкової, статистичної та фінансової звітності.
3. Джерела інтеграції
| Компонент | Призначення | Коментар |
|---|---|---|
| M.E.Doc | Формування, підписання, відправка та отримання квитанцій по звітності. | Основна система для подання звітності. |
| M.E.Doc REST API | Інтеграційний API для роботи з документами. | Потрібна активна інтеграція та документація методів. |
| M.E.Doc Інтеграція | Модуль обміну з обліковими системами. | Дозволяє переносити первинні документи та регламентовану звітність. |
| Python-сервіс | Інтеграційний шар між ERP та M.E.Doc. | Реалізується в межах цього ТЗ. |
| ERP / облікова система | Джерело даних для звітності. | Наприклад K2 ERP або інша система. |
4. Передумови
Для реалізації задачі необхідно отримати:
- встановлений та налаштований M.E.Doc;
- активний модуль M.E.Doc Інтеграція / REST API;
- мережевий доступ до M.E.Doc API;
- базовий URL M.E.Doc REST API;
- спосіб авторизації в API;
- технічну документацію endpoint-ів;
- перелік доступних типів звітності;
- формат передачі файлів;
- формат метаданих документа;
- правила створення документа в M.E.Doc;
- правила підписання документа;
- правила відправки документа;
- правила отримання статусів;
- правила отримання квитанцій;
- тестовий контур або тестову організацію;
- технічний контакт з боку постачальника M.E.Doc.
5. Терміни та скорочення
| Термін | Опис |
|---|---|
| Python-сервіс | Окремий backend-сервіс або модуль, який виконує інтеграцію з M.E.Doc. |
| M.E.Doc / Медок | Програмний комплекс для електронної звітності та документообігу. |
| Medoc REST API | API для інтеграції облікових систем з M.E.Doc. |
| ДПС | Державна податкова служба України. |
| XML | Формат електронного документа звітності. |
| XSD | Схема перевірки XML-документа. |
| КЕП | Кваліфікований електронний підпис. |
| API | Програмний інтерфейс інтеграції. |
| Webhook | Механізм отримання подій від зовнішньої системи. |
| Polling | Періодичне опитування зовнішнього API. |
| Квитанція | Підтвердження прийняття, відхилення або обробки звіту. |
6. Архітектура рішення
6.1. Загальна схема
ERP / Accounting System
|
| 1. Дані для звітності або готовий XML
v
Python Tax Reporting Service
|
| 2. Валідація та збереження документа
v
Medoc Integration Adapter
|
| 3. Передача документа через Medoc REST API
v
M.E.Doc
|
| 4. Підписання / відправка / обробка
v
ДПС
|
| 5. Квитанції / статуси
v
M.E.Doc
|
| 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 | Перевіряє реквізити, структуру та статус документа. |
| Medoc Client | Python-клієнт для роботи з M.E.Doc REST API. |
| Status Sync Worker | Фоновий процес для оновлення статусів. |
| Receipt Loader | Завантажує квитанції та результати обробки. |
| Storage Layer | Зберігає документи, квитанції, статуси та логи. |
| Audit Logger | Фіксує всі дії користувачів і системи. |
7. User Story
7.1. Передача документа в M.E.Doc
Як користувач ERP, я хочу передати документ звітності в M.E.Doc без ручного імпорту, щоб скоротити час підготовки та подання звітності.
7.2. Підписання та відправка
Як бухгалтер, я хочу ініціювати підписання та відправку документа через M.E.Doc, щоб не виконувати ці дії вручну в окремому вікні, якщо це підтримується 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 | Ні | Додаткові реквізити для M.E.Doc. |
8.2. Валідація документа
Перед передачею система повинна перевірити:
- наявність обов'язкових полів;
- коректність РНОКПП або ЄДРПОУ;
- коректність звітного періоду;
- наявність файлу;
- допустимий формат файлу;
- розмір файлу;
- коректність імені файлу;
- відповідність XML-структурі;
- відповідність XSD, якщо схема доступна;
- відсутність дубля документа;
- наявність налаштувань інтеграції з M.E.Doc.
8.3. Передача документа в M.E.Doc
Python-сервіс повинен мати метод для передачі документа в M.E.Doc.
Логічний endpoint Python-сервісу:
POST /api/v1/tax-reports/{report_id}/send-to-medoc
Очікувана дія:
- Отримати документ із локальної БД.
- Перевірити статус документа.
- Отримати файл зі сховища.
- Підготувати метадані.
- Викликати Medoc Integration Adapter.
- Отримати зовнішній ID документа в M.E.Doc.
- Зберегти зовнішній ID у БД.
- Оновити статус документа.
- Записати подію в журнал.
8.4. Підписання документа
Система повинна підтримувати один із режимів:
| Режим | Опис | Пріоритет |
|---|---|---|
| Підписання в M.E.Doc | Документ передається в M.E.Doc, а підписання виконується засобами M.E.Doc. | Основний режим. |
| Підписання в Python-сервісі | Python-сервіс підписує документ до передачі в M.E.Doc. | Опційно. |
| Ручне підписання | Користувач підписує документ у клієнті M.E.Doc. | Резервний режим. |
8.5. Відправка документа до ДПС
Якщо M.E.Doc REST API підтримує відповідний метод, Python-сервіс повинен ініціювати відправку документа до ДПС.
Логічний endpoint Python-сервісу:
POST /api/v1/tax-reports/{report_id}/send-to-tax
Очікувана дія:
- Перевірити, що документ створено в M.E.Doc.
- Перевірити, що документ підписано або готовий до підписання.
- Викликати метод M.E.Doc для відправки.
- Оновити статус на SentToTax.
- Записати подію в журнал.
8.6. Отримання статусів
Система повинна підтримувати два способи оновлення статусів:
| Спосіб | Опис | Пріоритет |
|---|---|---|
| Polling | Періодичне опитування M.E.Doc REST API. | Обов'язково для MVP. |
| Webhook | Отримання подій від M.E.Doc, якщо підтримується. | Опційно. |
8.7. Отримання квитанцій
Система повинна завантажувати та зберігати:
- квитанцію №1;
- квитанцію №2;
- квитанцію про відхилення;
- підписаний документ;
- PDF-візуалізацію, якщо доступна;
- технічний протокол обробки, якщо доступний;
- raw-відповідь M.E.Doc.
8.8. Повторна відправка
Повторна відправка дозволена тільки для документів у статусах:
- ValidationError;
- Failed;
- Rejected;
- DeliveryError;
- NeedResend.
Повторна відправка не дозволена для статусів:
- Accepted;
- SentToTax;
- WaitingForTaxReceipt;
- SentToMedoc;
- WaitingForSignature.
9. Статуси документа
| Внутрішній статус | Опис |
|---|---|
| Draft | Документ створено, але ще не готовий до передачі. |
| Generated | Файл документа сформовано. |
| ValidationError | Документ не пройшов перевірку. |
| ReadyToSend | Документ готовий до передачі. |
| Sending | Документ передається в M.E.Doc. |
| SentToMedoc | Документ успішно передано в M.E.Doc. |
| CreatedInMedoc | Документ створено в M.E.Doc. |
| WaitingForSignature | Документ очікує підписання. |
| Signed | Документ підписано. |
| SentToTax | Документ передано до ДПС. |
| WaitingForTaxReceipt | Очікується квитанція або результат обробки. |
| Receipt1Received | Отримано квитанцію №1. |
| Accepted | Документ прийнято. |
| Rejected | Документ відхилено. |
| DeliveryError | Помилка доставки. |
| Failed | Технічна помилка. |
| Cancelled | Документ скасовано. |
10. Мапінг статусів M.E.Doc
Фінальний мапінг статусів потрібно побудувати після отримання офіційного довідника статусів M.E.Doc.
Попередній логічний мапінг:
| Статус M.E.Doc | Внутрішній статус | Опис |
|---|---|---|
| created | CreatedInMedoc | Документ створено в M.E.Doc. |
| imported | SentToMedoc | Документ імпортовано / передано в M.E.Doc. |
| waiting_signature | WaitingForSignature | Очікується підпис. |
| signed | Signed | Документ підписано. |
| sent | SentToTax | Документ відправлено. |
| receipt_1 | Receipt1Received | Отримано квитанцію №1. |
| waiting_receipt | WaitingForTaxReceipt | Очікується квитанція. |
| accepted | Accepted | Документ прийнято. |
| rejected | Rejected | Документ відхилено. |
| error | Failed | Помилка обробки. |
Уточнення: значення статусів є попередніми. Реальні коди статусів потрібно взяти з API-документації M.E.Doc.
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. Передача в M.E.Doc
POST /api/v1/tax-reports/{report_id}/send-to-medoc
Очікувана відповідь:
{
"id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
"status": "SentToMedoc",
"medoc_document_id": "external-document-id",
"message": "Document sent to M.E.Doc"
}
11.4. Підписання документа
POST /api/v1/tax-reports/{report_id}/sign
Очікувана відповідь:
{
"id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
"status": "Signed",
"message": "Document signed via M.E.Doc"
}
11.5. Відправка до ДПС
POST /api/v1/tax-reports/{report_id}/send-to-tax
Очікувана відповідь:
{
"id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
"status": "SentToTax",
"message": "Document sent to tax authority via M.E.Doc"
}
11.6. Оновлення статусу
POST /api/v1/tax-reports/{report_id}/sync-status
Очікувана відповідь:
{
"id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
"old_status": "SentToMedoc",
"new_status": "WaitingForSignature",
"medoc_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. Medoc Integration Client
12.1. Призначення
Medoc Integration Client — це Python-клас або пакет, який інкапсулює роботу з M.E.Doc REST API.
12.2. Основні методи
class MedocClient:
def create_document(self, document: "DocumentPayload") -> "MedocDocumentResponse":
pass
def upload_tax_report(self, document: "DocumentPayload") -> "MedocDocumentResponse":
pass
def get_document(self, document_id: str) -> "MedocDocumentResponse":
pass
def get_document_status(self, document_id: str) -> "MedocStatusResponse":
pass
def sign_document(self, document_id: str) -> "MedocDocumentResponse":
pass
def send_document(self, document_id: str) -> "MedocDocumentResponse":
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) -> "MedocDocumentResponse":
pass
12.3. Конфігурація клієнта
from pydantic_settings import BaseSettings
class MedocSettings(BaseSettings):
base_url: str
api_key: str | None = None
username: str | None = None
password: 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
Приклад змінних середовища:
MEDOC_BASE_URL=http://medoc-server.local:8080 MEDOC_API_KEY=******** MEDOC_USERNAME=integration_user MEDOC_PASSWORD=******** MEDOC_COMPANY_CODE=12345678 MEDOC_TIMEOUT_SECONDS=30 MEDOC_RETRY_COUNT=3 MEDOC_RETRY_BACKOFF_SECONDS=5
Заборонено: зберігати API key, паролі, токени або паролі КЕП у коді, Git-репозиторії чи відкритих логах.
13. Передача документа в M.E.Doc
13.1. Логічний процес
1. Отримати документ з БД. 2. Перевірити, що документ має статус ReadyToSend. 3. Отримати файл зі сховища. 4. Підготувати метадані. 5. Викликати MedocClient.upload_tax_report(). 6. Отримати ID документа в M.E.Doc. 7. Зберегти ID у локальній БД. 8. Оновити статус на SentToMedoc. 9. Записати подію в журнал.
13.2. Приклад Python-логіки
from uuid import UUID
from datetime import datetime, timezone
def send_report_to_medoc(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 = medoc_client.upload_tax_report(payload)
report.medoc_document_id = response.id
report.status = TaxReportStatus.SENT_TO_MEDOC
report.sent_at = datetime.now(timezone.utc)
audit_logger.log(
entity_id=report.id,
event_type="SENT_TO_MEDOC",
details={
"medoc_document_id": response.id,
"raw_status": response.status,
},
)
db.commit()
return report
14. Підписання та відправка через M.E.Doc
14.1. Логічний процес підписання
1. Перевірити, що документ створено в M.E.Doc. 2. Перевірити, що документ не був відправлений раніше. 3. Викликати метод підписання M.E.Doc. 4. Отримати результат підписання. 5. Оновити статус на Signed або Failed. 6. Записати подію в журнал.
14.2. Логічний процес відправки
1. Перевірити, що документ підписано. 2. Викликати метод відправки M.E.Doc. 3. Отримати результат відправки. 4. Оновити статус на SentToTax або 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.medoc_document_id:
raise InvalidStatusError("Report is not created in M.E.Doc")
if report.status not in {
TaxReportStatus.SENT_TO_MEDOC,
TaxReportStatus.CREATED_IN_MEDOC,
TaxReportStatus.WAITING_FOR_SIGNATURE,
}:
raise InvalidStatusError(
f"Report {report_id} cannot be signed from status {report.status}"
)
sign_response = medoc_client.sign_document(report.medoc_document_id)
report.status = TaxReportStatus.SIGNED
audit_logger.log(
entity_id=report.id,
event_type="SIGNED_IN_MEDOC",
details={"raw_status": sign_response.status},
)
send_response = medoc_client.send_document(report.medoc_document_id)
report.status = TaxReportStatus.SENT_TO_TAX
report.sent_to_tax_at = datetime.now(timezone.utc)
audit_logger.log(
entity_id=report.id,
event_type="SENT_TO_TAX",
details={"raw_status": send_response.status},
)
db.commit()
return report
15. Робота зі статусами
15.1. Фонове оновлення
Система повинна мати background worker, який періодично оновлює статуси документів.
Рекомендована періодичність:
| Статус документа | Інтервал перевірки |
|---|---|
| SentToMedoc | кожні 5 хвилин |
| CreatedInMedoc | кожні 5 хвилин |
| WaitingForSignature | кожні 15 хвилин |
| SentToTax | кожні 10 хвилин |
| WaitingForTaxReceipt | кожні 10 хвилин |
| Receipt1Received | кожні 10 хвилин |
| Accepted / Rejected | не перевіряти |
15.2. Приклад worker-а
def sync_pending_reports() -> None:
reports = tax_report_repository.get_reports_for_sync()
for report in reports:
try:
medoc_status = medoc_client.get_document_status(
report.medoc_document_id
)
new_status = status_mapper.map_medoc_status(medoc_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=medoc_status.raw_status,
)
audit_logger.log(
entity_id=report.id,
event_type="STATUS_CHANGED",
details={
"old_status": old_status,
"new_status": new_status,
"medoc_status": medoc_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 | Внутрішній статус. |
| medoc_document_id | varchar | ID документа у M.E.Doc. |
| medoc_raw_status | varchar | Останній raw-статус M.E.Doc. |
| last_sync_at | timestamp | Дата останньої синхронізації. |
| sent_at | timestamp | Дата передачі в M.E.Doc. |
| 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 | Некоректні дані документа. | Не відправляти документ, показати список помилок. |
| MedocAuthError | Помилка авторизації в M.E.Doc API. | Зупинити відправку, повідомити адміністратора. |
| MedocApiError | API повернув помилку. | Записати відповідь API, дозволити повтор. |
| MedocTimeoutError | Перевищено час очікування. | Виконати retry. |
| MedocUnavailableError | Сервер M.E.Doc недоступний. | Повторити пізніше, повідомити адміністратора. |
| DuplicateDocumentError | Документ вже був переданий. | Заборонити повтор без підтвердження. |
| FileStorageError | Неможливо прочитати або записати файл. | Зафіксувати помилку, повідомити адміністратора. |
| StatusMappingError | Невідомий статус від M.E.Doc. | Зберегти raw-статус, створити подію UnknownStatus. |
| SignatureError | Помилка підписання документа. | Зберегти помилку, дозволити повторне підписання. |
17.2. Retry-логіка
Retry застосовується для:
- timeout;
- тимчасової недоступності M.E.Doc API;
- HTTP 429;
- HTTP 500;
- HTTP 502;
- HTTP 503;
- HTTP 504;
- тимчасових мережевих помилок.
Retry не застосовується для:
- помилок валідації;
- неправильного API key;
- відсутності прав доступу;
- відхилення документа податковою;
- дублювання документа;
- некоректного формату файлу;
- помилки КЕП через неправильний пароль.
18. Безпека
Система повинна забезпечити:
- зберігання API key тільки у змінних середовища або secret storage;
- заборону логування API key;
- заборону зберігання паролів КЕП у відкритому вигляді;
- маскування персональних даних у технічних логах;
- контроль доступу до документів;
- контроль доступу до квитанцій;
- журналювання всіх операцій;
- HTTPS для API-запитів, якщо M.E.Doc API розгорнутий з TLS;
- перевірку SSL-сертифіката, якщо використовується HTTPS;
- обмеження доступу до адміністративних endpoint-ів;
- резервне копіювання документів і квитанцій.
19. Налаштування
19.1. Змінні середовища
APP_ENV=production DATABASE_URL=postgresql+psycopg://user:password@db:5432/reports FILE_STORAGE_PATH=/data/tax-reports MEDOC_BASE_URL=http://medoc-server.local:8080 MEDOC_API_KEY=******** MEDOC_USERNAME=integration_user MEDOC_PASSWORD=******** MEDOC_COMPANY_CODE=12345678 MEDOC_TIMEOUT_SECONDS=30 MEDOC_RETRY_COUNT=3 MEDOC_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, користувач, дата, тип документа. |
| Валідація | Результат, список помилок. |
| Передача в M.E.Doc | Endpoint, час, статус відповіді, зовнішній ID. |
| Підписання | Результат, дата, raw-відповідь M.E.Doc. |
| Відправка до ДПС | Результат, дата, raw-відповідь M.E.Doc. |
| Помилка API | HTTP-код, тіло відповіді, correlation ID. |
| Оновлення статусу | Старий статус, новий статус, raw-статус M.E.Doc. |
| Завантаження квитанції | Тип файлу, назва, дата. |
| Повторна відправка | Причина, користувач, дата. |
| Скасування документа | Причина, користувач, дата. |
21. Acceptance Criteria
21.1. Створення документа
| № | Критерій | Очікуваний результат |
|---|---|---|
| AC-1 | ERP передає дані документа у Python-сервіс. | У системі створюється запис tax_reports. |
| AC-2 | Передано файл документа. | Файл зберігається у файловому сховищі. |
| AC-3 | Передано некоректні дані. | Система повертає список помилок валідації. |
21.2. Передача в M.E.Doc
| № | Критерій | Очікуваний результат |
|---|---|---|
| AC-4 | Документ має статус ReadyToSend. | Система дозволяє передачу в M.E.Doc. |
| AC-5 | M.E.Doc API повертає успішну відповідь. | У документі зберігається medoc_document_id. |
| AC-6 | M.E.Doc повертає помилку. | Система зберігає помилку та не втрачає документ. |
| AC-7 | Документ вже був переданий. | Система не створює дубль без окремого підтвердження. |
21.3. Підписання та відправка
| № | Критерій | Очікуваний результат |
|---|---|---|
| AC-8 | Документ створено в M.E.Doc. | Система дозволяє ініціювати підписання. |
| AC-9 | Підписання виконано успішно. | Статус документа змінюється на Signed. |
| AC-10 | Документ підписано. | Система дозволяє відправку до ДПС. |
| AC-11 | Відправка виконана успішно. | Статус документа змінюється на SentToTax. |
21.4. Статуси
| № | Критерій | Очікуваний результат |
|---|---|---|
| AC-12 | Worker запускає синхронізацію. | Статуси документів оновлюються автоматично. |
| AC-13 | M.E.Doc повертає новий статус. | Внутрішній статус документа змінюється. |
| AC-14 | M.E.Doc повертає невідомий статус. | Raw-статус зберігається, створюється подія UnknownStatus. |
21.5. Квитанції та файли
| № | Критерій | Очікуваний результат |
|---|---|---|
| AC-15 | Документ прийнято. | Система завантажує квитанцію №2 або результат обробки. |
| AC-16 | Документ відхилено. | Система зберігає причину відхилення. |
| AC-17 | Користувач відкриває картку документа. | Він бачить всі пов'язані файли та статуси. |
22. MVP
До MVP входить:
- REST API для створення документа;
- збереження документа;
- базова валідація;
- Medoc Integration Client;
- передача документа в M.E.Doc;
- збереження зовнішнього ID;
- ручний запуск синхронізації статусу;
- журнал подій;
- базова обробка помилок.
До MVP не входить:
- webhook-інтеграція;
- інтеграція напряму з ДПС;
- власний модуль КЕП;
- складний UI;
- автоматичне оновлення XSD;
- підтримка всіх типів звітності;
- автоматичне створення декларацій з бухгалтерських даних.
23. Етапи реалізації
Етап 1. Базова структура Python-сервісу
- створити FastAPI-проєкт;
- налаштувати PostgreSQL;
- створити моделі tax_reports, tax_report_events, tax_report_files;
- реалізувати конфігурацію через environment variables;
- реалізувати healthcheck endpoint.
Етап 2. Робота з документами
- реалізувати створення документа;
- реалізувати збереження файлу;
- реалізувати валідацію;
- реалізувати статуси;
- реалізувати журнал подій.
Етап 3. Medoc Integration Client
- реалізувати авторизацію;
- реалізувати upload_tax_report;
- реалізувати create_document;
- реалізувати get_document_status;
- реалізувати download_document;
- реалізувати download_receipts;
- реалізувати обробку помилок;
- реалізувати retry.
Етап 4. Передача документів
- реалізувати endpoint send-to-medoc;
- зберігати medoc_document_id;
- оновлювати статуси;
- логувати API-взаємодію.
Етап 5. Підписання та відправка
- реалізувати sign endpoint;
- реалізувати send-to-tax endpoint;
- обробити помилки КЕП;
- обробити помилки відправки;
- фіксувати всі етапи в журналі.
Етап 6. Синхронізація статусів
- реалізувати background worker;
- реалізувати періодичне оновлення статусів;
- реалізувати мапінг статусів;
- реалізувати обробку невідомих статусів.
Етап 7. Квитанції та результати обробки
- реалізувати завантаження квитанцій;
- реалізувати збереження PDF/XML/receipt-файлів;
- реалізувати прив'язку файлів до документа;
- реалізувати перегляд історії.
Етап 8. Production hardening
- додати Dockerfile;
- додати docker-compose;
- додати structured logging;
- додати metrics;
- додати alerting;
- додати rate limiting;
- додати security review.
24. Ризики
| Ризик | Опис | Як зменшити |
|---|---|---|
| Неповна або закрита API-документація | Частина методів M.E.Doc може бути доступна лише в межах ліцензійного модуля. | Отримати офіційну документацію та тестовий доступ. |
| Залежність від локального M.E.Doc | API може працювати тільки за наявності встановленого та налаштованого M.E.Doc. | Передбачити healthcheck M.E.Doc API. |
| Зміна API | Endpoint-и або формати відповіді можуть змінюватися. | Інкапсулювати API в окремому MedocClient. |
| Невідомі статуси | M.E.Doc може повертати статуси, яких немає в системі. | Зберігати raw-статус та мати UnknownStatus. |
| Дублювання документів | Повторна відправка може створити дубль. | Перевіряти medoc_document_id перед відправкою. |
| Помилки авторизації | Доступ до API може бути неправильним або простроченим. | Додати healthcheck інтеграції та повідомлення адміністратору. |
| Недоступність M.E.Doc | Сервер M.E.Doc або мережа можуть бути тимчасово недоступні. | Використовувати retry та чергу задач. |
| Помилки КЕП | Можливі проблеми з ключами, паролями або сертифікатами. | Відображати зрозумілу помилку та дозволяти повторне підписання. |
| Персональні дані | Документи можуть містити РНОКПП, ЄДРПОУ, фінансові дані. | Маскувати логи та обмежити доступ. |
25. Відкриті питання
- Яка версія M.E.Doc використовується?
- Чи активований модуль M.E.Doc REST API / Інтеграція?
- Який базовий URL API?
- Який механізм авторизації використовується?
- Які endpoint-и використовуються для створення документа?
- Які endpoint-и використовуються для підписання?
- Які endpoint-и використовуються для відправки?
- Які endpoint-и використовуються для отримання статусів?
- Які endpoint-и використовуються для отримання квитанцій?
- Який формат документа підтримується: XML, PDF, ZIP, JSON?
- Чи Python-сервіс має сам формувати XML, чи отримує готовий XML з ERP?
- Де виконується КЕП: у Python-сервісі, у M.E.Doc або користувачем у клієнті M.E.Doc?
- Чи потрібна підтримка ФОП, юридичних осіб або обох варіантів?
- Які типи звітів підтримуються першими?
- Чи є тестове середовище?
- Чи підтримуються webhook-и?
- Який SLA по оновленню статусів?
- Де зберігати файли: локально, S3, MinIO, DMS?
- Хто має доступ до API key?
- Чи потрібно робити UI, чи тільки backend API?
26. Приклад структури Python-проєкту
tax_reporting_medoc_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/
medoc/
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 створення документа працює;
- документ зберігається у БД та файловому сховищі;
- документ проходить валідацію;
- документ передається в M.E.Doc;
- зовнішній ID документа зберігається;
- статус документа оновлюється;
- помилки API обробляються;
- retry-механізм працює;
- журнал подій заповнюється;
- написані unit-тести для ключових сервісів;
- написані інтеграційні тести для MedocClient з mock API;
- документація для запуску додана в README;
- фінальні endpoint-и M.E.Doc винесені в конфігурацію.
29. Джерела
- https://medoc.ua/page/integrationapi
- https://medoc.ua/faq/opis-metodv-web-api
- https://medoc.ua/integration
- https://medoc.ua/page/integration
- https://medoc.ua/faq/priklad-stvorennja-pervinnogo-dokumentu-za-dopomogoju-medoc-web-api
- https://medoc.ua/faq/Import-dovidnyka-kontrahentiv-za-dopomohoiu-restapi