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'