126 lines
4.8 KiB
Python
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'
|