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

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

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

download_receipts.py


title: "Декларація платника єдиного податку"

</syntaxhighlight> Очікувана відповідь:

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

! | Отримати офіційну документацію та тестовий доступ. Очікуваний результат MEDOC_RETRY_BACKOFF_SECONDS=5 MEDOC_PASSWORD=******** 5. SEO-опис 1. |}

storage/
"medoc_document_id": response.id,

Python-сервіс повинен приймати документ від ERP. Поле </syntaxhighlight>

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

! Обов'язковість

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

| ReadyToSend | Документ готовий до передачі. |- | Rejected | Документ відхилено. Компонент

config.py
new_status = status_mapper.map_medoc_status(medoc_status)

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

4. Записати подію в журнал. # Чи активований компонент M.E.Doc REST API / інтеграційні функції ERP? |- | Персональні інформаційні дані | Документи можуть містити РНОКПП, ЄДРПОУ, фінансові інформаційні дані. |}

18. Безпека

MEDOC_COMPANY_CODE=12345678

- xml
core/

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

|- | AC-8 | Документ створено в M.E.Doc. Поле

)

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

"status": "Signed",

{ ! |- | StatusMappingError | Невідомий статус від M.E.Doc. "message": "Document created"

6. технічна архітектура рішення для бізнесу

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

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

! № POST /api/v1/tax-reports/{report_id}/send-to-medoc

audit_logger.log(

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

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

tax_report_repository.py
"medoc_status": medoc_status.raw_status,
v
"new_status": "WaitingForSignature",
timeout_seconds: int = 30
TaxReportStatus.SENT_TO_MEDOC,

== 17. Обробка помилок ==
 report = tax_report_repository.get_by_id(db, report_id)

 },
 requires_signature: true

 date=report.document_date,
POST /api/v1/tax-reports/{report_id}/send-to-medoc

 report.status = TaxReportStatus.SENT_TO_MEDOC
{| class="wikitable"
 "file_format": "xml",

 pass

}
{| class="wikitable"


}
 docker-compose.yml
! 7. Отримати результат підписання. # Чи підтримуються webhook-и? Ризик
 "message": "Document sent to M.E.Doc"
я хочу ініціювати підписання та відправку документа через M.E.Doc, 
 v
Як бухгалтер, 
=== 8.6. Отримання статусів ===
<pre>
! | Маскувати логи та обмежити доступ. ! |-
| Containers
| Docker. |-
| signed
| Signed
| Документ підписано. Тип
щоб не виконувати ці дії вручну в окремому вікні, якщо це підтримується API. # Які endpoint-и використовуються для отримання квитанцій? |}

APP_ENV=production

== 28. Definition of Done ==
=== 21.1. Створення документа ===
 "taxpayer_id": report.taxpayer_id,
STATUS_SYNC_INTERVAL_SECONDS=300
|-
| id
| uuid
| ID події.== 29. Джерела ==

def send_report_to_medoc(report_id: UUID, db: "Session") -> "TaxReport":
 pass
</syntaxhighlight>
=== Етап 8. Production hardening ===

RECEIPT_DOWNLOAD_ENABLED=true
 raise InvalidStatusError(

</syntaxhighlight> {

TaxReportStatus.WAITING_FOR_SIGNATURE,

SEO title: Технічне завдання: Передача документів для звітності в податкову через M.E.Doc для Python

SEO keywords: Python, M.E.Doc, Медок, Medoc REST API, податкова звітність, ДПС, API, XML, КЕП, електронна звітність, технічне завдання

</noinclude>
 {{SEO
Шаблон для службового SEO-опису сторінки. 

}}


}

sync_statuses.py
tax_report_service.py

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

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

=== 7.2. Підписання та відправка ===
class MedocSettings(BaseSettings):
 )
! ! # Який механізм авторизації застосовується для?=== 11.8. Отримання журналу ===
 api_key: str | None = None
 report_id=report.id,
=== 16.1. tax_reports ===
6. | Додати healthcheck інтеграції та повідомлення адміністратору. Компонент
[[Категорія:API]]
|-
| id
| uuid
| ID файлу. |}

 return report

 send_response = medoc_client.send_document(report.medoc_document_id)

* timeout;
* тимчасової недоступності M.E.Doc API;
* HTTP 429;
* HTTP 500;
* HTTP 502;
* HTTP 503;
* HTTP 504;
* тимчасових мережевих помилок. | Основна платформа для подання звітності. # Зберегти зовнішній ID у БД.<syntaxhighlight lang="json">

* реалізувати авторизацію;
* реалізувати upload_tax_report;
* реалізувати create_document;
* реалізувати get_document_status;
* реалізувати download_document;
* реалізувати download_receipts;
* реалізувати обробку помилок;
* реалізувати retry. # Чи потрібно робити UI, чи тільки backend API? |-
| Помилки авторизації
| Доступ до API здатна бути неправильним або простроченим. Валідація та збереження документа
 def download_original(self, document_id: str) -> bytes:
== 13. Передача документа в M.E.Doc ==
 |
 | 3. платформа повинна забезпечити:

* реалізувати background worker;
* реалізувати періодичне оновлення версій статусів;
* реалізувати мапінг статусів;
* реалізувати обробку невідомих статусів.=== 17.2. Retry-логіка ===
Очікувана відповідь:
 )

! | Опційно. |-
| Medoc REST API
| API для інтеграції облікових систем з M.E.Doc. | Опційно. |-
| report_id
| uuid
| ID документа. Режим
=== Етап 5. Підписання та відправка ===
 response = medoc_client.upload_tax_report(payload)
[[Категорія:M.E.Doc]]
 requires_signature: true
=== Передача документа в M. 8.3.E.Doc ===
 v
я хочу отримати квитанції в ERP, 
from uuid import UUID

</syntaxhighlight>

POST /api/v1/tax-reports/{report_id}/validate
=== 13.2. Приклад Python-логіки ===
Retry не застосовується для:
<syntaxhighlight lang="yaml">
=== 21.5. Квитанції та файли ===
 "message": "Document sent to tax authority via M.E.Doc"
щоб скоротити час підготовки та подання звітності. | Статус документа змінюється на SentToTax.<pre>

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

 "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
 def create_document(self, document: "DocumentPayload") -> "MedocDocumentResponse":
}

{

<div style="border-left: 6px solid #c62828; background: #ffebee; padding: 12px 16px; margin: 16px 0;">
8. |-
| waiting_receipt
| WaitingForTaxReceipt
| Очікується квитанція.<syntaxhighlight lang="json">

== Див. 30. так само ==

 if new_status != report.status:

Retry застосовується для:
=== 7.4. Отримання квитанцій ===
 migrations/
 logging.py
[[Категорія:Інтеграції]]
|-
| taxpayer_id
| string
| Так
| РНОКПП або ЄДРПОУ платника. | Статус документа змінюється на Signed. |-
| report_type
| string
| Так
| Тип звіту або документа. | платформа дає можливість передачу в M.E.Doc. |-
| Webhook
| Отримання подій від M.E.Doc, якщо підтримується. |-
| report_type
| varchar
| Тип звіту. Очікуваний результат
=== Етап 6. Синхронізація статусів ===
== 22. MVP ==

! |-
| Повторна відправка
| Причина, користувач системи, дата. # Записати подію в журнал. | як приклад K2 ERP або інша платформа.== 8. Функціональні вимоги ==

<syntaxhighlight lang="python">

 file_repository.py

 workers/
=== 7.5. Повторна відправка ===
</div>

MEDOC_TIMEOUT_SECONDS=30

# Отримати документ із локальної БД. # Отримати зовнішній ID документа в M.E.Doc. платформа повинна завантажувати та зберігати:

* реалізувати завантаження квитанцій;
* реалізувати збереження PDF/XML/receipt-файлів;
* реалізувати прив'язку файлів до документа;
* реалізувати перегляд історії. |-
| medoc_raw_status
| varchar
| Останній raw-статус M.E.Doc. SEO-опис
До MVP не входить:
=== 8.5. Відправка документа до ДПС ===

MEDOC_USERNAME=integration_user
MEDOC_RETRY_BACKOFF_SECONDS=5
Окремо варто відзначити який формує, перевіряє, передає і контролює документи податкової звітності через інтеграцію з M. |-
| old_status
| varchar
| Попередній статус. |-
| MedocTimeoutError
| Перевищено час очікування. models.py
== 16. Модель даних ==
 "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",

 title: "Декларація з ПДВ"

 tax_reports.py
! | У документі зберігається medoc_document_id. |}

</div>

платформа повинна логувати:

POST /api/v1/tax-reports/{report_id}/sync-status
<pre>
 "status": "SentToTax",

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

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

 unit/

{| class="wikitable"

* встановлений та налаштований M.E.Doc;
* активний компонент M.E.Doc інтеграційні функції ERP / REST API;
* мережевий доступ до M.E.Doc API;
* базовий URL M.E.Doc REST API;
* спосіб авторизації в API;
* технічну документацію endpoint-ів;
* перелік доступних типів звітності;
* формат передачі файлів;
* формат метаданих документа;
* правила створення документа в M.E.Doc;
* правила підписання документа;
* правила відправки документа;
* правила отримання статусів;
* правила отримання квитанцій;
* тестовий контур або тестову організацію;
* технічний контакт з боку постачальника M.E.Doc. |-
| title
| varchar
| Назва документа. |-
| error_message
| text
| Остання помилка. |-
| file_name
| varchar
| Назва файлу. |-
| M.E.Doc REST API
| Інтеграційний API для роботи з документами. |-
| updated_at
| timestamp
| Дата оновлення версій. Термін
 services/
 schemas.py
|-
| ValidationError
| Некоректні інформаційні дані документа. |-
| Підписання
| Результат, дата, raw-відповідь M.E.Doc. Коментар

* додати Dockerfile;
* додати docker-compose;
* додати structured logging;
* додати metrics;
* додати alerting;
* додати rate limiting;
* додати security review. |-
| waiting_signature
| WaitingForSignature
| Очікується підпис. |-
| Accepted
| Документ прийнято. Записати подію в журнал. |}

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

 details={
 "new_status": new_status,
 app/
<syntaxhighlight lang="python">
|-
| AC-12
| Worker запускає синхронізацію.== 12. Medoc Integration Client ==
=== Етап 4. Передача документів ===
{| class="wikitable"
== 3. Джерела інтеграції ==
 title: "Запит до податкової"

ДПС

 allowed_formats:
=== 13.1. Логічний бізнес-процес ===
class MedocClient:

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

!<pre>
</div>

{| class="wikitable"
 payload = DocumentPayload(
== 25. Відкриті питання ==
== 21. Acceptance Criteria ==
 api/
щоб мати підтвердження результату подання звітності. |-
| Залежність від локального M.E.Doc
| API здатна працювати тільки за наявності встановленого та налаштованого M.E.Doc. Критерій

=== 17.1. Типи помилок ===
[[Категорія:K2 ERP]]
{| class="wikitable"
 title: "Об'єднана формування звітів"
 raise InvalidStatusError(
== Підписання та відправка через M. 14.E.Doc ==
! |-
| Передача в M.E.Doc
| Endpoint, час, статус відповіді, зовнішній ID. |-
| period
| varchar
| Звітний період. ! |-
| AC-11
| Відправка виконана успішно. # Які endpoint-и використовуються для підписання? | Перевіряти medoc_document_id перед відправкою. | Передбачити healthcheck M.E.Doc API. |}

 metadata={
</pre>
POST /api/v1/tax-reports

{| class="wikitable"

! 

 Dockerfile
 allowed_formats:
! Очікуваний результат
<pre>
 "report_type": "single_tax_declaration",
</pre>
}
! |-
| file_format
| varchar
| XML, PDF, ZIP тощо. Викликати метод підписання M.E.Doc. | Виконати retry. SEO-опис
Очікувана відповідь:
 event_type="STATUS_SYNC_FAILED",
 pass

 details={"raw_status": send_response.status},

 reports = tax_report_repository.get_reports_for_sync()
 file_format=report.file_format,
</pre>

 report.sent_to_tax_at = datetime.now(timezone.utc)

 def send_document(self, document_id: str) -> "MedocDocumentResponse":
щоб не створювати документ заново. Тип
<syntaxhighlight lang="json">
MEDOC_API_KEY=********
</pre>
</pre>

! retry_backoff_seconds: int = 5

MEDOC_RETRY_COUNT=3
=== 11.9. Завантаження квитанцій ===
 raise InvalidStatusError("Report is not created in M.E.Doc")
|-
| Draft
| Документ створено, але ще не готовий до передачі.=== 15.2. Приклад worker-а ===

 event_type="SIGNED_IN_MEDOC",
</pre>
{| class="wikitable"
Очікувана відповідь:
|-
| AC-1
| ERP передає інформаційні дані документа у Python-сервіс. return report

{| class="wikitable"
! |-
| DuplicateDocumentError
| Документ вже був переданий. |-
| Receipt1Received
| Отримано квитанцію 1. # Який SLA по оновленню статусів? SEO-опис
 v
4. 
=== 11.1. Створення документа ===

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

Python-сервіс повинен мати метод для передачі документа в M.E.Doc. Оновити статус на SentToTax або Failed. |-
| Receipt Loader
| Завантажує квитанції та результати обробки. |-
| Sending
| Документ передається в M.E.Doc. # Чи потрібна технічна підтримка ФОП, юридичних осіб або обох варіантів? # Оновити статус документа. # Який базовий URL API? |-
| CreatedInMedoc
| Документ створено в M.E.Doc. Поле
=== 16.2. tax_report_events ===
Мінімальний набір вхідних даних:
! |-
| AC-16
| Документ відхилено. |-
| new_status
| varchar
| Новий статус. |-
| document_number
| string
| Так
| Номер документа. |-
| medoc_document_id
| varchar
| ID документа у M.E.Doc. Дія системи
 event_type="SENT_TO_TAX",
</pre>
|-
| Python-сервіс
| Окремий backend-сервіс або компонент, який виконує інтеграцію з M.E.Doc. # Викликати метод M.E.Doc для відправки.=== 14.2. Логічний бізнес-процес відправки ===
 requires_receipt: true
Очікувана дія:
== 24. Ризики ==
 "taxpayer_id": "1234567890",

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

MEDOC_BASE_URL=http://medoc-server.local:8080
Метою задачі виступає як створення Python-сервісу для передачі документів податкової звітності через M.E.Doc. |-
| AC-13
| M.E.Doc повертає новий статус. Тип

 db/
 details={
Python Tax Reporting Service

 "medoc_document_id": "external-document-id",

<syntaxhighlight lang="json">
DATABASE_URL=postgresql+psycopg://user:password@db:5432/reports
! |-
| AC-7
| Документ вже був переданий. |-
| file_name
| varchar
| Назва файлу. |-
| file_path
| varchar
| Шлях до файлу у сховищі. |-
| document_date
| date
| Дата документа. Зберегти ID у локальній БД. |}

<syntaxhighlight lang="python">

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

! Повторна відправка дозволена тільки для документів у статусах:
 |
 | 7. |-
| size_bytes
| integer
| Розмір файлу. |-
| event_type
| varchar
| Тип події. Очікуваний результат
 "taxpayer_name": report.taxpayer_name,
Очікувана відповідь:
 },
{| class="wikitable"
! |-
| content_type
| varchar
| MIME-тип. | платформа дає можливість відправку до ДПС. SEO-опис
=== 11.4. Підписання документа ===
 tax_report_repository.update_status(

</pre>
функції ERP застосовується для для автоматизації передачі документів податкової звітності з ERP або облікової системи до M.E.Doc з подальшим поданням до ДПС. | Повторити пізніше, повідомити адміністратора. |-
| accepted_at
| timestamp
| Дата прийняття. |-
| Medoc Client
| Python-клієнт для роботи з M.E.Doc REST API. |-
| created_at
| timestamp
| Дата створення. |-
| receipt_1
| Receipt1Received
| Отримано квитанцію 1.
  • реалізувати endpoint send-to-medoc;
  • зберігати medoc_document_id;
  • оновлювати статуси;
  • логувати API-взаємодію. Статус документа
event_type="SENT_TO_MEDOC",
"medoc_status": "waiting_signature"
POST /api/v1/tax-reports/{report_id}/resend

 signing_service.py
=== 11.5. Відправка до ДПС ===
__TOC__
Попередній логічний мапінг:
|-
| id
| uuid
| Внутрішній ID документа. f"Report {report_id} cannot be sent from status {report.status}"

== 7. User Story ==

 requires_signature: true

 def get_document_status(self, document_id: str) -> "MedocStatusResponse":
2. |-
| imported
| SentToMedoc
| Документ імпортовано / передано в M.E.Doc. pass
 verify_ssl: bool = True
! |-
| metadata
| object
| Ні
| Додаткові реквізити для M.E.Doc. # Оновити статус на SentToTax. |-
| XML
| Формат електронного документа звітності. |-
| DeliveryError
| Помилка доставки. Спосіб
6. SEO-опис

 "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
=== 12.1. Призначення ===
 )

 new_status=new_status,

# Перевірити, що документ створено в M.E.Doc. SEO-опис
 db.commit()
M.E.Doc
! {

 "document_number": "DECL-2026-0001",
 details={"raw_status": sign_response.status},
 |
 | 1. | Інкапсулювати API в окремому MedocClient. |-
| M.E.Doc / Медок
| Програмний комплекс для електронної звітності та документообігу. | платформа завантажує квитанцію 2 або результат обробки. Викликати метод відправки M.E.Doc. |-
| file_path
| varchar
| Шлях до файлу. |}
! |-
| Background jobs
| Celery, RQ або APScheduler. |-
| AC-17
| користувач системи відкриває картку документа. |-
| КЕП
| Кваліфікований електронний підпис. |-
| Недоступність M.E.Doc
| Сервер M.E.Doc або мережа можуть бути тимчасово недоступні. SEO-опис
<pre>
! |
 | 5. №
<div style="border-left: 6px solid #f57c00; background: #fff3e0; padding: 12px 16px; margin: 16px 0;">
 def download_signed_document(self, document_id: str) -> bytes:
 status_sync_service.py

 )

=== Передача в M. 21.2.E.Doc ===
def sync_pending_reports() -> None:
 "metadata": {

 integration/

Очікувана дія:
! | Реалізується в межах цього ТЗ. |}

{| class="wikitable"

# Яка реліз системи M.E.Doc застосовується для? |-
| Status Sync Worker
| Фоновий бізнес-процес для оновлення версій статусів. Отримати файл зі сховища. "message": "Document signed via M.E.Doc"

 file_content=file_bytes,
 if report.status != TaxReportStatus.READY_TO_SEND:
 security.py
 base_url: str
 receipt_service.py
'''Заборонено:''' зберігати API key, паролі, токени або паролі КЕП у коді, Git-репозиторії чи відкритих логах. "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",

! Реальні коди статусів потрібно взяти з API-документації M.E.Doc.<pre>

* webhook-інтеграція;
* інтеграційні функції ERP напряму з ДПС;
* власний компонент КЕП;
* складний UI;
* автоматичне оновлення версій XSD;
* технічна підтримка всіх типів звітності;
* автоматичне створення декларацій з бухгалтерських даних. |-
| HTTP client
| httpx. |-
| SentToMedoc
| Документ успішно передано в M.E.Doc. Отримати результат відправки. щоб оперативно знаходити причину помилок інтеграції. |-
| Tests
| pytest. |-
| status
| varchar
| Внутрішній статус. README.md

* повна заміна інтерфейсу M.E.Doc;
* власна реалізація подання напряму до API ДПС;
* власна реалізація КЕП, якщо підписання виконується у M.E.Doc;
* автоматичне оновлення версій всіх XSD-схем;
* повноцінний UI для бухгалтера;
* автоматична бухгалтерська перевірка сум;
* технічна підтримка всіх типів податкової, статистичної та фінансової звітності. |-
| sent
| SentToTax
| Документ відправлено. |-
| taxpayer_name
| string
| Так
| Назва компанії або ПІБ ФОП. # Хто має доступ до API key? Оновити статус на Signed або Failed. |-
| rejected
| Rejected
| Документ відхилено. # Отримати файл зі сховища. | Використовувати retry та чергу задач. # Де виконується КЕП: у Python-сервісі, у M.E.Doc або користувачем у клієнті M.E.Doc? |}

'''Уточнення:''' значення статусів виступає як попередніми. '''Головна ідея:''' розробити Python-сервіс.E.Doc / Medoc REST API. Компонент
 old_status = report.status
Python Tax Reporting Service
== 27. Технічні вимоги до Python ==
 report = tax_report_repository.get_by_id(db, report_id)
ERP / Accounting System
POST /api/v1/tax-reports/{report_id}/download-receipts
FILE_STORAGE_PATH=/data/tax-reports
Логічний endpoint Python-сервісу:
 entity_id=report.id,
! Передача документа через Medoc REST API
 pyproject.toml
 retry_count: int = 3
 |
 | 4. |-
| source_system
| varchar
| ERP або інша система-джерело. |}

<pre>

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

* квитанцію №1;
* квитанцію №2;
* квитанцію про відхилення;
* підписаний документ;
* PDF-візуалізацію, якщо доступна;
* технічний протокол обробки, якщо доступний;
* raw-відповідь M.E.Doc. Критерій

== 20. Логування та аудит ==
! |-
| SignatureError
| Помилка підписання документа. Підписання / відправка / обробка

це Python-клас або пакет, який інкапсулює роботу з M виступає ключовою рисою Medoc Integration Client.E.Doc REST API. Записати подію в журнал. |- | created_by | varchar | користувач системи або system. | Raw-статус зберігається, створюється подія UnknownStatus. |- | AC-2 | Передано файл документа. |- | rejected_at | timestamp | Дата відхилення. |- | Квитанція | Підтвердження прийняття, відхилення або обробки звіту. 6. Що зберігати }

def get_document(self, document_id: str) -> "MedocDocumentResponse":
validation_service.py "errors": [] v
Python 3.11 або вище. number=report.document_number,

5. |-

Скасування документа Причина, користувач системи, дата. SEO-опис
vat_declaration:
M.E.Doc Статуси документів оновлюються автоматизовано. |}
pass
audit_logger.log(
"created_by": "user@example.com" "document_date": "2026-04-15", pass {
created CreatedInMedoc - Failed Технічна помилка. - pdf
event_type="STATUS_CHANGED",
report.status = TaxReportStatus.SIGNED
password: str | None = None
=== 6.1. Загальна схема ===
|-
| Polling
| Періодичне опитування M.E.Doc REST API. | Записати відповідь API, дозволити повтор. оновлення версій статусу в ERP
</syntaxhighlight>
{
=== 12.2. Основні методи ===

 requires_receipt: true

 pass
=== 12.3. Конфігурація клієнта ===
<pre>
|-
| API Layer
| REST API для прийому документів від ERP. інформаційні дані для звітності або готовий XML
{| class="wikitable"
{| class="wikitable"
 |
 | 2. |-
| accepted
| Accepted
| Документ прийнято. |-
| file_content_base64
| string
| Так
| Вміст документа у Base64. |-
| M.E.Doc інтеграційні функції ERP
| компонент обміну з обліковими системами. |-
| ДПС
| Державна податкова служба України. |-
| MedocAuthError
| Помилка авторизації в M.E.Doc API. | Не відправляти документ, показати список помилок. Перевірити, що документ має статус ReadyToSend. |-
| Logging
| structlog або стандартний logging у JSON-форматі.== 5. Терміни та скорочення ==

3. |}

tax_reporting_medoc_service/

 - zip

* Python-сервіс розгортається через Docker;
* API створення документа функціонує;
* документ зберігається у БД та файловому сховищі;
* документ проходить валідацію;
* документ передається в M.E.Doc;
* зовнішній ID документа зберігається;
* статус документа оновлюється;
* помилки API обробляються;
* retry-механізм функціонує;
* журнал подій заповнюється;
* написані unit-тести для ключових сервісів;
* написані інтеграційні тести для MedocClient з mock API;
* документація для запуску додана в README;
* фінальні endpoint-и M.E.Doc винесені в конфігурацію. |-
| ValidationError
| Документ не пройшов перевірку. Критерій
 file_bytes = file_storage.read(report.file_path)

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

 "raw_status": response.status,

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

 "status": "Generated",

! }

! Статус M.E.Doc

<pre>

 requires_receipt: true

=== 7.6. Технічний аудит ===
 report.status = TaxReportStatus.SENT_TO_TAX
! |-
| Polling
| Періодичне опитування зовнішнього API. |-
| Storage Layer
| Зберігає документи, квитанції, статуси та логи. Внутрішній статус

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

unified_report:
"report_type": report.report_type,
entity_id=report.id,
Створення документа ID, користувач системи, дата, тип документа. №
health.py

MEDOC_RETRY_COUNT=3

- AC-3 Передано некоректні інформаційні дані. Внутрішній статус - XSD - Audit Logger платформа дає можливість ініціювати підписання. sign_response = medoc_client.sign_document(report.medoc_document_id)

2. report.medoc_document_id = response.id

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

},

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

15.1. Фонове оновлення версій

Підписання в M.E.Doc Зберігати raw-статус та мати UnknownStatus. Викликати MedocClient.upload_tax_report(). |- AC-10 None = None
medoc/
- period string Так - WaitingForTaxReceipt Очікується квитанція або результат обробки. Поле
v
session.py

ERP / Accounting System

- xml

5. # Перевірити статус документа. * реалізувати sign endpoint;

  • реалізувати send-to-tax endpoint;
  • обробити помилки КЕП;
  • обробити помилки відправки;
  • фіксувати всі етапи в журналі. tax_request:
try:
title=report.title,

from pydantic_settings import BaseSettings

for report in reports:

Як бухгалтер, 9. SEO-опис STATUS_SYNC_ENABLED=true

v

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

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

entity_id=report.id,
audit_logger.log(
}

</syntaxhighlight>

MEDOC_TIMEOUT_SECONDS=30

  • REST API для створення документа;
  • збереження документа;
  • базова валідація;
  • Medoc Integration Client;
  • передача документа в M.E.Doc;
  • збереження зовнішнього ID;
  • ручний запуск синхронізації статусу;
  • журнал подій;
  • базова обробка помилок. платформа повинна підтримувати два способи оновлення версій статусів:

21.4. Статуси

status_mapper.py
if not report.medoc_document_id:

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

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

allowed_formats:
- DB PostgreSQL. Інтервал перевірки

</syntaxhighlight>

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

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

- Document Builder Формує XML або приймає готовий файл. SEO-опис
  • помилок валідації;
  • неправильного API key;
  • відсутності прав доступу;
  • відхилення документа податковою;
  • дублювання документа;
  • некоректного формату файлу;
  • помилки КЕП через неправильний пароль. | Зберегти raw-статус, створити подію UnknownStatus. 3. ! |-
Дублювання документів Повторна відправка здатна створити дубль. pass

я хочу бачити статус документа в ERP, Очікувана відповідь:

- Validation Резервний режим. Критерій

повної реалізації потрібно мати ліцензію/компонент інтеграції забезпечується через критично: M.E.Doc REST API застосовують, коли потрібно як інтеграційний шар між обліковою системою та програмою M.E.Doc.; так само реалізовано налаштований M.E.Doc, доступ до REST API та офіційну документацію методів. Синхронізація статусів 2. SEO-опис

report.medoc_document_id
if report.status not in {
- pdf
audit_logger.log(
"old_status": "SentToMedoc",
f"Report {report_id} cannot be signed from status {report.status}"
client.py
main.py
SentToMedoc кожні 5 хвилин
CreatedInMedoc кожні 5 хвилин
WaitingForSignature кожні 15 хвилин
SentToTax кожні 10 хвилин
WaitingForTaxReceipt кожні 10 хвилин
Receipt1Received кожні 10 хвилин
Accepted / Rejected не перевіряти

}

single_tax_declaration:
entity_id=report.id,

2. Область сценарії використання

"source_system": "K2 ERP",

Технічний стек: Python 3.11+, FastAPI, PostgreSQL, SQLAlchemy, Alembic, httpx, Pydantic, Celery/RQ/APScheduler, Docker. | Зафіксувати помилку, повідомити адміністратора. |-

ERP / облікова платформа - оновлення версій статусу }
integrations/

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

  • наявність обов'язкових полів;
  • коректність РНОКПП або ЄДРПОУ;
  • коректність звітного періоду;
  • наявність файлу;
  • допустимий формат файлу;
  • розмір файлу;
  • коректність імені файлу;
  • відповідність XML-структурі;
  • відповідність XSD, якщо схема доступна;
  • відсутність дубля документа;
  • наявність налаштувань інтеграції з M.E.Doc. |-
last_sync_at timestamp - ORM - Signed - document_number varchar Номер документа. "period": "2026-Q1",
username: str | None = None
  • створити FastAPI-проєкт;
  • налаштувати PostgreSQL;
  • створити моделі tax_reports, tax_report_events, tax_report_files;
  • реалізувати конфігурацію через environment variables;
  • реалізувати healthcheck endpoint. Сервіс повинен забезпечити:
file_name=report.file_name,
db.commit() "file_content_base64": "BASE64_XML_CONTENT", ) report.sent_at = datetime.now(timezone.utc) Приклад змінних середовища: )
- Python-сервіс - API - MedocUnavailableError Він бачить всі пов'язані файли та статуси. | Обов'язково для MVP. | Заборонити повтор без підтвердження. |- Web framework }

3. | Файл зберігається у файловому сховищі. Очікуваний результат

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

- payload jsonb - sent_to_tax_at timestamp - Завантаження квитанції - file_format string Так - report_id uuid ID документа. ! Рекомендація
"id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",
Неповна або закрита API-документація - AC-6 - SentToTax платформа повертає список помилок валідації. |- sent_at timestamp - Помилка API HTTP-код, тіло відповіді, correlation ID. Пріоритет
 )
 file_storage.py
! |-
| MedocApiError
| API повернув помилку. |-
| taxpayer_id
| varchar
| РНОКПП або ЄДРПОУ. Перевірити, що документ підписано.</syntaxhighlight>
MEDOC_PASSWORD=********
 audit_logger.log(
M.E.Doc
! |-
| Ручне підписання
| користувач системи підписує документ у клієнті M.E.Doc. medoc_status = medoc_client.get_document_status(

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

* зберігання API key тільки у змінних середовища або secret storage;
* заборону логування API key;
* заборону зберігання паролів КЕП у відкритому вигляді;
* маскування персональних даних у технічних логах;
* контроль доступу до документів;
* контроль доступу до квитанцій;
* журналювання всіх операцій;
* HTTPS для API-запитів, якщо M.E.Doc API розгорнутий з TLS;
* перевірку SSL-сертифіката, якщо застосовується для HTTPS;
* обмеження доступу до адміністративних endpoint-ів;
* резервне копіювання документів і квитанцій. | Зупинити відправку, повідомити адміністратора. Пріоритет
1. |-
| document_date
| date
| Так
| Дата документа. | дає можливість переносити первинні документи та регламентовану формування звітів. |-
| Зміна API
| Endpoint-и або формати відповіді можуть змінюватися. |-
| Помилки КЕП
| Можливі проблеми з ключами, паролями або сертифікатами. |-
| created_at
| timestamp
| Дата створення.== 26. Приклад структури Python-проєкту ==

* реалізувати створення документа;
* реалізувати збереження файлу;
* реалізувати валідацію;
* реалізувати статуси;
* реалізувати журнал подій. |-
| created_at
| timestamp
| Дата події. |-
| Відправка до ДПС
| Результат, дата, raw-відповідь M.E.Doc. Тип помилки
<pre>
=== 16.3. tax_report_files ===
 raw_status=medoc_status.raw_status,
 "source_system": report.source_system,
 )
=== Передача в M. 11.3.E.Doc ===
 def upload_tax_report(self, document: "DocumentPayload") -> "MedocDocumentResponse":
Фінальний мапінг статусів потрібно побудувати після отримання офіційного довідника статусів M.E.Doc. |-
| Validation Layer
| Перевіряє реквізити, структуру та статус документа. # Підготувати метадані. |-
| Валідація
| Результат, список помилок. |-
| Підписання в Python-сервісі
| Python-сервіс підписує документ до передачі в M.E.Doc. До MVP входить:
 exceptions.py

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

 except Exception as exc:
</div>
1. Подія

 - zip
=== 8.1. Створення документа ===
 pass
 "status": "SentToMedoc",
GET /api/v1/tax-reports/{report_id}/events
=== 8.2. Валідація документа ===

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

 requires_signature: true
<syntaxhighlight lang="json">

 routes/
 pass
MEDOC_BASE_URL=http://medoc-server.local:8080

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

11.6. оновлення версій статусу

- Migrations Alembic.
|-
| AC-15
| Документ прийнято. Призначення
! | У системі створюється запис tax_reports. |-
| Cancelled
| Документ скасовано. # Де зберігати файли: локально, S3, MinIO, DMS? exceptions.py

* створення Python API для прийому документів;
* створення клієнта інтеграції з M.E.Doc REST API;
* формування XML або прийом готового XML;
* збереження документа;
* перевірка обов'язкових реквізитів;
* передача документа в M.E.Doc;
* запуск підписання / відправки через M.E.Doc;
* отримання статусів;
* отримання квитанцій;
* журнал подій;
* retry-механізм;
* захист API-ключів і службових доступів;
* інтеграційні функції ERP з ERP. # Який формат документа підтримується: XML, PDF, ZIP, JSON? Перевірити, що документ не був відправлений раніше. Отримати документ з БД. |-
| Webhook
| Механізм отримання подій від зовнішньої системи. |-
| Generated
| Файл документа сформовано. # Викликати Medoc Integration Adapter. |-
| AC-9
| Підписання виконано успішно. Запустити очікування квитанцій. "id": "9ddaa913-03a3-4e11-a90a-582adf8a05ff",

* Accepted;
* SentToTax;
* WaitingForTaxReceipt;
* SentToMedoc;
* WaitingForSignature. |}

 "old_status": old_status,

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

Як адміністратор,
AC-4 Внутрішній статус документа змінюється.== 19. конфігурація ==

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

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

entity_id=report.id,

document_types:

Квитанції / статуси
TaxReportStatus.CREATED_IN_MEDOC,
"period": report.period,
- AC-5 платформа зберігає помилку та не втрачає документ. | платформа не створює дубль без окремого підтвердження. |- taxpayer_name varchar - WaitingForSignature - Невідомі статуси M.E.Doc здатна повертати статуси, яких немає в системі. Отримати ID документа в M.E.Doc. Тип
"taxpayer_name": "ФОП Іваненко Іван Іванович",
"status": "ReadyToSend",
- xml

{ MEDOC_API_KEY=********

from datetime import datetime, timezone

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

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

я хочу передати документ звітності в M.E.Doc без ручного імпорту,

tests/

Мапінг статусів M. 10.E.Doc

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

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

event_repository.py
requires_receipt: true

</syntaxhighlight>

<syntaxhighlight lang="json">

- xml

Етап 3. Medoc Integration Client

Зберегти помилку, дозволити повторне підписання.
allowed_formats:
  • ValidationError;
  • Failed;
  • Rejected;
  • DeliveryError;
  • NeedResend. # Чи виступає як тестове середовище? | базовий режим. | Потрібна активна інтеграційні функції ERP та документація методів. Критерій

Medoc Integration Adapter щоб розуміти, чи документ створено, передано, підписано, відправлено до ДПС, прийнято або відхилено. |-

file_type varchar - AC-14 - error Failed - FileStorageError Неможливо прочитати або записати файл. Як зменшити

1. Мета

Повторна відправка не дозволена для статусів: POST /api/v1/tax-reports/{report_id}/send-to-tax

)

Передача документа в M. 7.1.E.Doc

Якщо M.E.Doc REST API підтримує відповідний метод, Python-сервіс повинен ініціювати відправку документа до ДПС.