Files
ksef_app/tests/test_ksef_xml_generator.py
Mateusz Gruszczyński 35571df778 push
2026-03-13 11:03:13 +01:00

126 lines
4.8 KiB
Python

from datetime import date
import xml.etree.ElementTree as ET
from app.models.catalog import InvoiceLine
from app.models.company import Company
from app.models.invoice import Invoice, InvoiceType
from app.services.invoice_service import InvoiceService
NS = {'fa': 'http://crd.gov.pl/wzor/2025/06/25/13775/'}
def test_render_structured_xml_uses_fa3_schema_and_split_payment(app):
with app.app_context():
company = Company.query.first()
company.name = 'Test Co Sp. z o.o.'
company.tax_id = '5250000001'
company.address = 'ul. Testowa 1, 00-001 Warszawa'
company.bank_account = '11 1111 1111 1111 1111 1111 1111'
invoice = Invoice(
company_id=company.id,
company=company,
ksef_number='DRAFT/1',
invoice_number='FV/1/2026',
contractor_name='Klient Sp. z o.o.',
contractor_nip='5260000002',
contractor_address='ul. Odbiorcy 2, 00-002 Warszawa',
issue_date=date(2026, 3, 12),
net_amount=100,
vat_amount=23,
gross_amount=123,
invoice_type=InvoiceType.SALE,
split_payment=True,
currency='PLN',
seller_bank_account='11 1111 1111 1111 1111 1111 1111',
source='issued',
external_metadata={},
)
lines = [
InvoiceLine(
description='Usługa abonamentowa',
quantity=1,
unit='usł.',
unit_net=100,
vat_rate=23,
net_amount=100,
vat_amount=23,
gross_amount=123,
)
]
xml = InvoiceService().render_structured_xml(invoice, lines=lines, nfz_meta={})
root = ET.fromstring(xml)
assert root.tag == '{http://crd.gov.pl/wzor/2025/06/25/13775/}Faktura'
assert root.findtext('fa:Naglowek/fa:KodFormularza', namespaces=NS) == 'FA'
kod = root.find('fa:Naglowek/fa:KodFormularza', NS)
assert kod is not None
assert kod.attrib['kodSystemowy'] == 'FA (3)'
assert kod.attrib['wersjaSchemy'] == '1-0E'
assert root.findtext('fa:Naglowek/fa:WariantFormularza', namespaces=NS) == '3'
assert root.findtext('fa:Fa/fa:P_2', namespaces=NS) == 'FV/1/2026'
assert root.findtext('fa:Fa/fa:Adnotacje/fa:P_18A', namespaces=NS) == '1'
assert root.findtext('fa:Fa/fa:P_13_1', namespaces=NS) == '100.00'
assert root.findtext('fa:Fa/fa:P_14_1', namespaces=NS) == '23.00'
assert root.findtext('fa:Fa/fa:P_15', namespaces=NS) == '123.00'
assert root.findtext('fa:Fa/fa:Platnosc/fa:FormaPlatnosci', namespaces=NS) == '6'
assert root.findtext('fa:Fa/fa:Platnosc/fa:RachunekBankowy/fa:NrRB', namespaces=NS) == '11111111111111111111111111'
assert root.findtext('fa:Fa/fa:FaWiersz/fa:P_8A', namespaces=NS) == 'usł.'
assert root.findtext('fa:Fa/fa:FaWiersz/fa:P_8B', namespaces=NS) == '1'
def test_render_structured_xml_maps_nfz_metadata_to_dodatkowy_opis(app):
with app.app_context():
company = Company.query.first()
invoice = Invoice(
company_id=company.id,
company=company,
ksef_number='DRAFT/2',
invoice_number='FV/NFZ/1/2026',
contractor_name='NFZ',
contractor_nip='1234567890',
issue_date=date(2026, 3, 12),
net_amount=200,
vat_amount=46,
gross_amount=246,
invoice_type=InvoiceType.SALE,
split_payment=False,
currency='PLN',
source='nfz',
external_metadata={},
)
lines = [
InvoiceLine(
description='Świadczenie medyczne',
quantity=2,
unit='usł.',
unit_net=100,
vat_rate=23,
net_amount=200,
vat_amount=46,
gross_amount=246,
)
]
nfz_meta = {
'recipient_branch_id': '01',
'settlement_from': '2026-03-01',
'settlement_to': '2026-03-31',
'provider_identifier': 'NFZ-ABC',
'service_code': 'SVC-1',
'contract_number': 'UM-2026-01',
'template_identifier': 'TPL-77',
}
xml = InvoiceService().render_structured_xml(invoice, lines=lines, nfz_meta=nfz_meta)
root = ET.fromstring(xml)
dodatki = root.findall('fa:Fa/fa:DodatkowyOpis', NS)
pairs = {item.findtext('fa:Klucz', namespaces=NS): item.findtext('fa:Wartosc', namespaces=NS) for item in dodatki}
assert pairs['IDWew'] == '01'
assert pairs['P_6_Od'] == '2026-03-01'
assert pairs['P_6_Do'] == '2026-03-31'
assert pairs['NrUmowy'] == 'UM-2026-01'
assert root.findtext('fa:Podmiot3/fa:DaneIdentyfikacyjne/fa:IDWew', namespaces=NS) == '01'