Плагін MedocExchange — Документація¶
Загальний опис¶
MedocExchange — платний плагін для модуля Essentials системи ESWF.
Два рівні функціональності:
| Рівень | Що входить | Статус |
|---|---|---|
| Production (MVP) | Експорт Invoice → видаткова накладна (J1203001 / F1203001) → ZIP → імпорт бухгалтером у M.E.Doc |
✅ стабільний |
| 🧪 Experimental | Податкові накладні в DOP: модель TaxInvoice, генерація J1201006 XML, імпорт вхідних ПН, звірка з ЄРПН |
⚠️ окремий future-track |
🧪 Experimental: податкові накладні в DOP¶
⚠️ Важливо — читайте до використання
Робота з податковими накладними (J1201006) та ЄРПН у цьому плагіні — це experimental-track, винесений як окрема майбутня ініціатива.
Початковий scope інтеграції (й той, який рекомендовано для продакшена): 1. DOP генерує лише видаткові накладні формату J1203001 з
Invoice. 2. Бухгалтер завантажує XML у M.E.Doc. 3. Податкові накладні створюються та реєструються у M.E.Doc, а не в DOP.Чому tax invoice в DOP — ризиковано: - Податкове законодавство України змінюється дуже швидко (формати ПН, правила блокування, КВЕДи, нові теги у XML). - M.E.Doc оновлює формати оперативно; DOP не може гарантувати той самий темп без спеціалізованої команди податкового супроводу. - Розходження з ЄРПН → штрафи клієнту → репутаційний ризик платформи.
Поточний статус experimental-блоку (розділ «Flow 2026-04-22» нижче): - Код написаний та покритий тестами (backend). - UI/frontend інтеграції немає. - Може бути видалений або суттєво перероблений у наступних релізах. - Не використовувати у production без додаткового юридичного/податкового аудиту.
Коли повернемося: якщо виникне клієнтський попит на повний tax-accounting всередині DOP і з'явиться виділена команда податкового супроводу — тоді ця секція стане частиною окремого модуля
tax-accountingз власним lifecycle. Поки — «колись, може, зробимо».
Production-flow (рекомендований) описано нижче — розділ «Структура XML (J1203001)», «Сервіс генерації XML», «Management Command load_uktzed», «Валідація перед експортом».
Призначення plugin'а в цілому: обмін документами з програмою M.E.Doc / СОТА та ДПС України — експорт видаткових накладних (MVP), + experimental flow для податкових накладних та звірки з ЄРПН.
| Параметр | Значення |
|---|---|
| App label | medoc_exchange |
| URL prefix | /api/v1/medoc/ |
| Plugin key | medoc_exchange |
| Тип ліцензії | Платна (перевірка через shop.License) |
| Формати XML | J1203001 / F1203001 (видаткова накладна), J1201006 / F1201006 (податкова накладна) |
| Кодування XML | windows-1251 |
| Архів | ZIP (для експорту видаткових) |
🧪 Flow 2026-04-22 — experimental: повний цикл роботи з податковими накладними¶
⚠️ Experimental. Див. попередження на початку документа. Не використовувати без додаткового аудиту.
Квітень 2026 — в коді модуля з'явився окремий experimental-блок, який охоплює не лише експорт Invoice у формат видаткової накладної, а й lifecycle податкової накладної (ПН), яка реєструється в ЄРПН. Цей блок розглядається як відкладена окрема ініціатива (див. попередження вище) і не входить у production-scope MVP-інтеграції.
Три головних процеси¶
┌────────────────────────┐ ┌────────────────────────┐ ┌────────────────────────┐
│ 1. EXPORT OUT │ │ 2. IMPORT IN │ │ 3. RECONCILE │
│ │ │ │ │ │
│ Invoice / Purch.Inv. │ │ XML від постачальника │ │ CSV-витяг з ЄРПН │
│ ↓ │ │ ↓ │ │ ↓ │
│ build_tax_invoice_ │ │ parse_medoc_xml() │ │ parse_erpn_extract() │
│ from_source() │ │ ↓ │ │ ↓ │
│ ↓ │ │ import_as_tax_invoice │ │ reconcile() │
│ TaxInvoice (draft) │ │ ↓ │ │ ↓ │
│ ↓ │ │ TaxInvoice (direction │ │ matched / │
│ TaxInvoiceExporter │ │ ='in') │ │ amount_mismatch / │
│ ↓ │ │ ↓ │ │ missing_in_erpn / │
│ J1201006 XML │ │ try_match_existing_ │ │ extra_in_erpn │
│ ↓ │ │ purchase_invoice() │ │ │
│ → M.E.Doc / СОТА │ │ │ │ │
│ → ЄРПН │ │ │ │ │
└────────────────────────┘ └────────────────────────┘ └────────────────────────┘
Модель TaxInvoice¶
Файл: backend/medoc_exchange/models.py
TaxInvoice — окрема сутність (не просто згенерований XML), що має власний lifecycle ЄРПН: draft → submitted → registered → blocked/rejected.
| Поле | Опис |
|---|---|
direction |
out (видана — наше ПДВ-зобов'язання) / in (отримана — наш податковий кредит) |
tax_type |
standard / adjustment (розрахунок коригування) / summary (зведена) |
number, date |
Реквізити ПН |
source_invoice FK |
Джерело — Invoice (sale) |
source_purchase_invoice FK |
Джерело — PurchaseInvoice (purchase) |
source_payment FK |
Джерело — IncomingPayment (аванс) |
seller_tin/name, buyer_tin/name |
Денормалізовані реквізити (зберігаються, навіть якщо контрагента видалили) |
total_net, total_vat, total_gross |
Суми |
erpn_status |
draft / submitted / registered / blocked / rejected |
erpn_sent_at, erpn_reg_date, erpn_error |
Історія реєстрації в ЄРПН |
xml_content, xml_filename |
Збережений XML (для аудиту) |
reconciled_at, reconciliation |
Результат останньої звірки з ЄРПН |
1. Експорт податкової накладної¶
Helper: build_tax_invoice_from_source(source, tenant, direction, ...)
Створює TaxInvoice з будь-якого джерела (Invoice / PurchaseInvoice / IncomingPayment), автоматично:
- підставляє ІПН / назву продавця та покупця;
- міняє місцями ІПН-и при direction='in' (вхідна ПН — продавець стає постачальник, покупець — ми);
- переносить суми net / vat / gross.
Клас: TaxInvoiceExporter(tax_invoice) — будує XML J1201006/F1201006.
exporter = TaxInvoiceExporter(tax_invoice)
xml_bytes = exporter.build_xml() # windows-1251 encoded
filename = exporter.get_filename() # '010001234567890J12010060000010001540.xml'
Fallback-ланцюжок вибору рядків:
1. source Invoice.lines (QuerySet) → якщо не порожній.
2. source PurchaseInvoice.lines → якщо не порожній.
3. source IncomingPayment → одна aggregate-рядок «Аванс за договором Х».
4. Aggregate summary з ti.total_net / ti.total_vat (коли рядків взагалі немає).
Константи формату J1201006:
| Константа | Значення |
|---|---|
DOC_CODE_LEGAL |
'J12' |
DOC_CODE_FOP |
'F12' |
DOC_SUB |
'010' (податкова накладна) |
DOC_VER |
'06' (поточна версія схеми) |
⚠️ Порівняння з видатковою накладною: J1203001 (
DOC_SUB='030') — це видаткова накладна (первинний документ продажу товарів/послуг). J1201006 (DOC_SUB='010') — податкова накладна, що реєструється в ЄРПН. Це різні документи з різними XML-тегами.
2. Імпорт вхідних податкових накладних¶
Сервіс: backend/medoc_exchange/services/importer.py
from medoc_exchange.services.importer import parse_medoc_xml, import_as_tax_invoice
# Розбір XML
parsed = parse_medoc_xml(xml_bytes) # автоматичне декодування windows-1251
# {'doc_type': 'J1201006', 'seller_tin': '12345678', 'buyer_tin': '98765432',
# 'date': date(2026,4,15), 'number': '154', 'total_gross': Decimal('1200.00'),
# 'lines': [...]}
# Створення TaxInvoice
tax_invoice = import_as_tax_invoice(parsed, tenant=request.tenant) # direction='in'
# Спроба прив'язки до існуючого PurchaseInvoice
pi = try_match_existing_purchase_invoice(parsed, tenant=request.tenant)
# Matcher: (supplier_invoice_number, date, seller_tin) → PurchaseInvoice
API: POST /api/v1/medoc/import/ (multipart file=<xml>).
3. Звірка з ЄРПН¶
Сервіс: backend/medoc_exchange/services/reconciliation.py
Раз на місяць бухгалтер вивантажує з кабінету ДПС CSV-витяг своїх накладних з ЄРПН. Сервіс розкладає їх у 4 кошики:
| Bucket | Опис | Що робити |
|---|---|---|
matched |
Номер, дата, ІПН, сума збіглися | ✅ ок |
amount_mismatch |
Номер/дата/ІПН збіглися, сума різна | ⚠️ розібратись — можлива помилка обліку або не зареєстроване коригування |
missing_in_erpn |
У нас є — в ЄРПН нема | 🔴 критично — ПН не зареєстровано, штраф |
extra_in_erpn |
В ЄРПН є — у нас нема | 🟡 вхідні від постачальника, які ми не зафіксували — імпортувати |
Толерантний CSV-парсер parse_erpn_extract(csv_text) підтримує:
- Декілька форматів дати: YYYY-MM-DD, DD.MM.YYYY, DDMMYYYY.
- Числа: 1234.56, "1 234,56" (з пробілом-роздільником тисяч та комою-десятковим).
API: POST /api/v1/medoc/reconcile/ (multipart file=<csv>).
{
"summary": {
"matched_count": 24,
"amount_mismatch_count": 1,
"missing_in_erpn_count": 2,
"extra_in_erpn_count": 3
},
"matched": [...],
"amount_mismatch": [{"our": {...}, "erpn": {...}, "diff": "50.00"}],
"missing_in_erpn": [...],
"extra_in_erpn": [...]
}
API ViewSet для TaxInvoice¶
Маршрут: /api/v1/medoc/tax-invoices/ (через TaxInvoiceViewSet).
| Action | Метод | Опис |
|---|---|---|
list / retrieve / create / update / destroy |
стандартний ModelViewSet CRUD | |
from_invoice |
POST /tax-invoices/from-invoice/{invoice_id}/ |
Створити ПН з Invoice |
from_purchase_invoice |
POST /tax-invoices/from-purchase-invoice/{pi_id}/ |
Створити вхідну ПН з PurchaseInvoice |
xml |
GET /tax-invoices/{id}/xml/ |
Згенерувати J1201006 XML (windows-1251) |
mark_registered |
POST /tax-invoices/{id}/mark-registered/ |
Відмітити як зареєстровану в ЄРПН |
Тести¶
Файл: backend/medoc_exchange/tests/test_tax_invoice.py — 6 тестів:
| Тест | Що перевіряє |
|---|---|
TestTaxInvoiceBuilder.test_from_sales_invoice_is_outgoing |
Правильне заповнення TIN-ів для direction='out' |
TestTaxInvoiceBuilder.test_swaps_tins_when_incoming |
Swap ІПН для direction='in' |
TestTaxInvoiceExporterXML.test_xml_has_declarhead_and_body |
XML містить DECLARHEAD/DECLARBODY + правильні теги |
TestImporterRoundTrip.test_parse_back_exported_xml |
Round-trip export → import |
TestReconciliation.test_reconcile_buckets |
Розкладання по 4 кошиках |
TestParseExtractCSV.test_parser_tolerates_variants |
Толерантність CSV-парсера до форматів |
Структура файлів¶
backend/medoc_exchange/
├── __init__.py
├── apps.py # MedocExchangeConfig
├── admin.py # UKTZEDDirectory в Django Admin
├── models.py # UKTZEDDirectory
├── serializers.py # UKTZEDDirectorySerializer
├── views.py # 4 endpoint + ViewSet
├── urls.py # маршрутизація
├── migrations/
│ ├── __init__.py
│ └── 0001_initial.py # створення таблиці uktzeddirectory
├── services/
│ ├── __init__.py
│ ├── validator.py # validate_invoice_for_export()
│ └── exporter.py # MedocExporter — генерація XML/ZIP
└── management/
└── commands/
└── load_uktzed.py # python manage.py load_uktzed
Пов'язані зміни в існуючих файлах:
backend/essentials/models/item.py # + поле uktzed_code (ForeignKey)
backend/essentials/migrations/0007_item_uktzed_code.py
backend/eswf/settings/base.py # + 'medoc_exchange' в INSTALLED_APPS
backend/eswf/urls.py # + path('api/v1/medoc/', ...)
Моделі¶
UKTZEDDirectory (medoc_exchange/models.py)¶
Глобальний довідник УКТЗЕД. Не прив'язаний до тенанта — загальний для всіх.
| Поле | Тип | Опис |
|---|---|---|
code |
CharField(10) |
Код УКТЗЕД (до 10 цифр), унікальний, індексований |
description |
CharField(1000) |
Опис англійською |
description_ua |
CharField(1000) |
Опис українською |
is_service |
BooleanField |
True для послуг (префікс 00) |
class UKTZEDDirectory(models.Model):
code = models.CharField(max_length=10, unique=True, db_index=True)
description = models.CharField(max_length=1000)
description_ua = models.CharField(max_length=1000, blank=True)
is_service = models.BooleanField(default=False)
class Meta:
ordering = ['code']
Зміна в Item (essentials/models/item.py)¶
Додано поле uktzed_code — обов'язкове для M.E.Doc експорту:
uktzed_code = models.ForeignKey(
'medoc_exchange.UKTZEDDirectory',
on_delete=models.SET_NULL, null=True, blank=True,
verbose_name='UKTZED Code',
help_text='УКТ ЗЕД — код для експорту в M.E.Doc.',
)
API Endpoints¶
Всі захищені JWT. Три з чотирьох додатково перевіряють активну ліцензію плагіну.
GET /api/v1/medoc/uktzed/¶
Пошук по довіднику УКТЗЕД (без ліцензії).
| Параметр | Опис |
|---|---|
?search= |
Пошук по code, description, description_ua |
?ordering=code |
Сортування |
Відповідь:
{
"count": 15000,
"results": [
{"id": 1, "code": "0101100000", "description_ua": "Коні чистокровні племінні", "is_service": false},
...
]
}
POST /api/v1/medoc/validate/¶
Перевірка накладної перед експортом. Повертає список помилок або {"valid": true}.
Тіло запиту:
Відповідь (успіх):
Відповідь (помилки) — HTTP 422:
{
"valid": false,
"errors": [
{"field": "organization.edrpou", "message": "Organization \"ТОВ Приклад\": EDRPOU or INN must be set."},
{"field": "lines[2].item.uktzed_code", "message": "Line 2: item \"Товар Б\" has no UKTZED code."}
]
}
GET /api/v1/medoc/export/<invoice_id>/¶
Генерація та завантаження ZIP-архіву з XML-файлом формату M.E.Doc.
- Відповідь:
application/zip,Content-Disposition: attachment; filename="...zip" - При невалідних даних — HTTP 422 з JSON помилками (аналогічно validate)
GET /api/v1/medoc/cloud/<invoice_id>/¶
Повернення даних накладної у структурованому JSON для хмарного агента або інтеграції з СОТА.
Відповідь:
{
"doc_type": "J1203001",
"xml_filename": "010001234567890J12030001000001540 0.xml",
"date": "23022026",
"number": "154",
"seller": {
"name": "ТОВ Продавець",
"full_name": "Товариство з обмеженою відповідальністю \"Продавець\"",
"tin": "12345678",
"is_vat_payer": true,
"tax_system": "general"
},
"buyer": {
"name": "ТОВ Покупець",
"tin": "98765432",
"client_type": "company"
},
"total_net": "1000.00",
"total_vat": "200.00",
"total_gross": "1200.00",
"currency": "UAH",
"lines": [
{
"name": "Товар А",
"uktzed_code": "8471300000",
"uktzed_description": "Машини обчислювальні портативні...",
"unit": "шт",
"quantity": "2.000",
"price": "500.0000",
"amount": "1000.0000",
"vat_rate": "20",
"vat_amount": "200.0000"
}
]
}
Структура XML (J1203001 / F1203001)¶
Формат відповідає вимогам ДПС / M.E.Doc для видаткових накладних.
<?xml version="1.0" encoding="windows-1251"?>
<DECLAR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DECLARHEAD>
<C_DOC>J12</C_DOC> <!-- J12 = юр.особа | F12 = ФОП -->
<C_DOC_SUB>030</C_DOC_SUB>
<C_DOC_VER>01</C_DOC_VER>
<C_DOC_TYPE>0</C_DOC_TYPE> <!-- 0 = оригінал, 1 = уточнюючий -->
<C_DOC_CNT>1</C_DOC_CNT>
<D_FILL>23022026</D_FILL> <!-- DDMMYYYY -->
<HKSTI>12345678</HKSTI> <!-- ЄДРПОУ або ІПН продавця -->
</DECLARHEAD>
<DECLARBODY>
<HFILL>23022026</HFILL> <!-- дата документа DDMMYYYY -->
<HNUM>154</HNUM> <!-- номер документа -->
<HTIN_SEL>12345678</HTIN_SEL> <!-- ЄДРПОУ/ІПН продавця -->
<HNAME_SEL>ТОВ Продавець</HNAME_SEL>
<HTIN_BUY>98765432</HTIN_BUY> <!-- ЄДРПОУ/ІПН покупця -->
<HNAME_BUY>ТОВ Покупець</HNAME_BUY>
<!-- Рядки таблиці: R01, R02, ... (нумерація з 01) -->
<R01G1S>Товар А</R01G1S> <!-- назва номенклатури -->
<R01G7>8471300000</R01G7> <!-- код УКТЗЕД -->
<R01G32>шт</R01G32> <!-- одиниця виміру -->
<R01G6>2</R01G6> <!-- кількість -->
<R01G5>500.00</R01G5> <!-- ціна без ПДВ -->
<R01G11>1000.00</R01G11> <!-- сума без ПДВ -->
<R01G14>200.00</R01G14> <!-- сума ПДВ -->
<HSUM>1000.00</HSUM> <!-- загальна сума без ПДВ -->
<HPDV>200.00</HPDV> <!-- загальна сума ПДВ -->
<HZAG>1200.00</HZAG> <!-- загальна сума з ПДВ -->
</DECLARBODY>
</DECLAR>
Визначення типу документа¶
Organization.tax_system |
C_DOC |
Формат файлу |
|---|---|---|
general (ТОВ/АТ) |
J12 |
J1203001 |
simplified (ФОП) |
F12 |
F1203001 |
Формат назви файлу¶
M.E.Doc вимагає суворий формат імені XML-файлу:
| Частина | Довжина | Приклад | Опис |
|---|---|---|---|
| РЕГІОН | 2 | 01 |
Код регіону (Вінниця=01, Київ=80 тощо) |
| РАЙОН | 3 | 000 |
Код підрозділу ДПС |
| ЄДРПОУ | 8-10 | 0012345678 |
ЄДРПОУ організації (доповнюється нулями до 10) |
| КОД_ДОКУМ | 8 | J1203001 |
J12+SUB+VER або F12+SUB+VER |
| ПОРЦІЯ | 6 | 000001 |
Порція файлів (зазвичай 000001) |
| НОМ_ДОКУМ | 6 | 000154 |
Номер документа (доповнюється нулями) |
| ТИП | 1 | 0 |
0=оригінал, 1=уточнюючий |
Приклад: 01000012345678J12030010000010001540.xml
Поля
region_codeтаdistrict_codeнаразі не є полями моделіOrganization. Поточна реалізація використовує значення за замовчуванням01і000. Для точного формування імені — додайте ці поля доOrganizationта міграцію.
Логіка перевірки ліцензії¶
POST /api/v1/medoc/validate/
GET /api/v1/medoc/export/<id>/
GET /api/v1/medoc/cloud/<id>/
│
▼
shop.License.objects.filter(
tenant=request.tenant,
product__plugin_key='medoc_exchange',
is_active=True,
).exists()
│
False ──► HTTP 403: "Active MedocExchange license required."
True ──► продовження виконання
Активація ліцензії відбувається через App Store ESWF (/api/v1/shop/):
1. Користувач купує продукт з plugin_key='medoc_exchange'
2. Система створює запис License(tenant=..., product=..., is_active=True)
3. Плагін починає працювати для даного тенанту
Валідація перед експортом¶
Файл: services/validator.py
Функція validate_invoice_for_export(invoice) виконує такі перевірки:
| # | Перевірка | Поле помилки |
|---|---|---|
| 1 | invoice.number не порожній |
number |
| 2 | invoice.date не порожня |
date |
| 3 | invoice.organization вказана |
organization |
| 4 | organization.edrpou або organization.inn заповнені |
organization.edrpou |
| 5 | client.edrpou або client.inn заповнені |
client.edrpou |
| 6 | Накладна має хоча б один рядок | lines |
| 7 | Кожен товар у рядку має uktzed_code |
lines[N].item.uktzed_code |
Повертає [] (порожній список) якщо все в порядку.
Сервіс генерації XML¶
Файл: services/exporter.py
Клас MedocExporter¶
exporter = MedocExporter(invoice)
# Отримати XML як bytes (windows-1251)
xml_bytes = exporter.build_xml()
# Отримати ім'я файлу
filename = exporter.get_filename() # "01000...J12030001000015400.xml"
# Отримати ZIP (bytes, filename)
zip_bytes, zip_name = exporter.build_zip()
Константи¶
| Константа | Значення | Опис |
|---|---|---|
DOC_CODE_LEGAL |
'J12' |
Юридична особа |
DOC_CODE_FOP |
'F12' |
ФОП |
DOC_SUB |
'030' |
Підтип документа |
DOC_VER |
'01' |
Версія форми |
Management Command: load_uktzed¶
Файл: management/commands/load_uktzed.py
Формати вхідного файлу¶
JSON:
[
{
"code": "0101100000",
"description": "Pure-bred breeding horses",
"description_ua": "Коні чистокровні племінні",
"is_service": false
}
]
CSV:
code,description,description_ua,is_service
0101100000,Pure-bred breeding horses,Коні чистокровні племінні,false
0201100000,Carcasses and half-carcasses,Туші та напівтуші,false
Запуск¶
# Завантаження з JSON
python manage.py load_uktzed uktzed.json
# Завантаження з CSV з очищенням існуючих записів
python manage.py load_uktzed uktzed.csv --clear
Де взяти базу УКТЗЕД¶
- Завантажити Excel з сайту Держмитслужби: https://customs.gov.ua (розділ «Класифікатор УКТ ЗЕД»)
- Конвертувати Excel → JSON одноразовим скриптом:
import pandas as pd, json
df = pd.read_excel('uktzed.xlsx', dtype=str)
df.columns = ['code', 'description_ua']
df['description'] = df['description_ua']
df['is_service'] = False
with open('uktzed.json', 'w', encoding='utf-8') as f:
json.dump(df.to_dict(orient='records'), f, ensure_ascii=False, indent=2)
- Запустити команду:
Розгортання та міграції¶
cd backend
# Застосувати міграції (створює таблицю uktzeddirectory + поле item.uktzed_code)
python manage.py migrate
# Завантажити довідник УКТЗЕД
python manage.py load_uktzed uktzed.json
# Перевірити API (потребує активної ліцензії)
curl -H "Authorization: Bearer <token>" \
http://localhost:8000/api/v1/medoc/uktzed/?search=8471
Налаштування в Django¶
settings/base.py¶
eswf/urls.py¶
Схема взаємодії компонентів¶
Frontend DOP
│
│ 1. POST /api/v1/medoc/validate/ {"invoice_id": 42}
│◄────────────────────────────────── {"valid": true}
│
│ 2. GET /api/v1/medoc/export/42/
│◄────────────────────────────────── ZIP (windows-1251 XML)
│
▼ Користувач зберігає ZIP
│
▼ Імпорт у M.E.Doc → Створення податкової накладної → Відправка до ДПС
або:
│ GET /api/v1/medoc/cloud/42/
│◄────────────────────────────────── JSON payload
│
▼ Локальний агент / СОТА інтеграція → Автоматична відправка
Статус та плани розвитку¶
| Функціональність | Статус |
|---|---|
| Довідник УКТЗЕД (модель + admin + search API) | ✅ реалізовано |
Поле uktzed_code на товарі |
✅ реалізовано |
| Валідація перед експортом | ✅ реалізовано |
| Генерація J1203001 XML (видаткова, юр. особа) | ✅ реалізовано |
| Генерація F1203001 XML (видаткова, ФОП) | ✅ реалізовано |
| Упаковка в ZIP-архів | ✅ реалізовано |
| Cloud/JSON endpoint для агента | ✅ реалізовано |
| Перевірка ліцензії через App Store | ✅ реалізовано |
Management command load_uktzed |
✅ реалізовано |
Модель TaxInvoice + lifecycle ЄРПН |
🧪 experimental (2026-04-22) — див. попередження |
| Генерація J1201006 XML (податкова накладна) | 🧪 experimental (2026-04-22) |
| Імпорт вхідних XML → авто-створення TaxInvoice (direction=in) | 🧪 experimental (2026-04-22) |
| Звірка з ЄРПН (CSV → 4 buckets) | 🧪 experimental (2026-04-22) |
| TaxInvoiceViewSet (CRUD + from_invoice/xml/mark_registered) | 🧪 experimental (2026-04-22) — backend only, UI немає |
| Tax accounting в DOP як окремий модуль | 🔮 deferred — «колись, може, зробимо» |
Поля region_code, district_code на Organization |
⏳ не реалізовано |
| Уточнюючий документ / розрахунок коригування (adjustment) | ⏳ не реалізовано |
| Кілька документів в одному ZIP | ⏳ не реалізовано |
| Frontend UI кнопка «Експорт до M.E.Doc» + TaxInvoice list | ⏳ не реалізовано |
| Підпис ЕЦП (КЕП) через локальний агент | ⏳ не реалізовано |
| Автоматична відправка через СОТА API | ⏳ не реалізовано |