Przejdź do treści

Faktura w zasobie Document: prawo VAT i struktura pod KSeF (FA)

Ten rozdział nie jest profilem KSeF w rozumieniu dokumentacji czy certyfikacji Ministerstwa Finansów. Opisuje weryfikację zgodności: że dane wymagane przez polskie prawo (ustawa o VAT, art. 106e) oraz logiczną strukturę faktury FA(2)/FA(3) używaną przy wymianie z Krajowym Systemem e-Faktur (KSeF) da się zmieścić w kanonicznym zasobie Document — bez tworzenia osobnego „obiektu KSeF”, lecz przez nagłówek, position[], attribute[] oraz konwencje FK (nazewnictwo i lokalizacja pól).

Chodzi więc o to, żeby integrator mógł sprawdzić: czy payload API.ERP ma miejsce na wszystkie istotne elementy faktury (w tym pod KSeF)? — a nie o rejestrowany profil w systemie KSeF.

Ułożenie jest zbliżone do podejścia Common Data Model (Microsoft CDM) dla faktur (Invoice, FreeTextInvoiceHeader, CustInvoiceTrans): nagłówek + wiersze + sumy.

Dla dedykowanego zasobu kanonicznego Invoice / InvoicePosition (osobna struktura API, nie ten dokument oparty na Document) zob. model kanoniczny oraz profile kanoniczne (snapshot z kodu).


1. Document jako faktura

Faktura to Document z:

  • type = invoice (1..1; system https://api-erp.kamsoft.pl/ns/document-type).
  • identifier (1..) — co najmniej jeden numer faktury (Identifier.system + value, np. system=company); mogą być dodatkowe (KSeF, origin itd.). Rodzaj identyfikatora wynika z Identifier.system*, nie z osobnego code systemu.
  • issueDate (1..1) — data wystawienia (obligatoryjna wg art. 106e).
  • participant (2..) — referencje do PartyRole: wystawca (Podmiot1) i nabywca (Podmiot2) obowiązkowo; ewentualnie kolejne role (np. płatnik). Document.participant referuje do PartyRole (role=seller/supplier, role=buyer/customer). Strona (nazwa, adres, NIP) wynika z PartyRole.party* → Party.
  • position (1..*) — co najmniej jeden wiersz lub linia podsumowania; wiersze faktury (invoice-line) oraz opcjonalnie linie podsumowania VAT (vat-summary-line).
  • attribute (1..*) — podsumowanie dokumentu: co najmniej suma brutto (total-gross); zwykle także total-net, total-vat; opcjonalnie rozbicie VAT per stawka.

Pola specyficzne dla faktury (daty sprzedaży, płatności, KSeF, podział płatności) są w konwencji FK — rozszerzenia Document lub atrybuty z ustalonym code (patrz sekcja 3).

Pola referencyjne a wartości wbudowane: W tym mapowaniu część pól zawiera referencje (Reference) do innych zasobów, a nie pełne obiekty. Document.participant to tablica referencji do PartyRole (np. PartyRole/role-seller-01); w każdym PartyRole pole party to referencja do Party (np. Party/supplier-01). Dane wystawcy i nabywcy (nazwa, adres, NIP) znajdują się w zasobie Party — w payloadzie faktury mogą być dostarczone w contained (inline) lub pobrane osobnym wywołaniem. Podobnie paymentAccount (konwencja FK) to referencja do BankAccount; valueReference w wierszu faktury to referencje do ProductDefinition lub Product. Pola niebędące referencjami (issueDate, identifier, valueMoney, valueString, attribute z valueMoney itd.) niosą wartości bezpośrednio.


2. Mapowanie wymogów prawnych (art. 106e ustawy o VAT) na Document

Poniższa tabela łączy obowiązkowe elementy faktury z przepisów z konkretnymi polami w Document i konwencji FK. Dzięki temu reguły prawne są wprost odzwierciedlone w strukturze.

Wymóg prawny (art. 106e / KSeF) Pole w modelu Kard. Lokalizacja w Document / konwencja FK
Data wystawienia issueDate 1..1 Document.issueDate
Kolejny numer identyfikujący fakturę invoiceNumber 1..1 Document.identifier — co najmniej jeden z numerem faktury (Identifier.system + value, np. system=company)
Imiona, nazwiska/nazwy i adresy wystawcy seller 1..1 Document.participant[0] = Reference(PartyRole) (role=seller); dane w zasobie Party wskazanym przez PartyRole.party = Reference(Party)
Imiona, nazwiska/nazwy i adresy nabywcy buyer 1..1 Document.participant[1] = Reference(PartyRole) (role=buyer); dane w PartyRole.party = Reference(Party)
NIP podatnika (wystawcy) sellerTaxId 1..1 W zasobie Party (referencja PartyRole.party z participant[0]); Identifier z type=nip, system=urn:pl:nip
NIP nabywcy (z wyjątkami) buyerTaxId 0..1 W zasobie Party (referencja PartyRole.party z participant[1]); Identifier z type=nip, system=urn:pl:nip
Opis towaru/usługi lineDescription 0..1 DocumentPosition (invoice-line).valueString
Ilość quantity 0..1 DocumentPosition.valueItem (type=quantity) lub valueQuantity
Cena jednostkowa netto unitPriceNet 0..1 DocumentPosition.valueItem (type=unit-price) + valueMoney
Rabaty i opusty discount 0..1 DocumentPosition.valueItem lub attribute (document/position) z code np. discount
Wartość sprzedaży netto (wiersz) netAmount 1..1 DocumentPosition.valueItem (type=net-amount) + valueMoney
Stawka VAT (wiersz) vatRate 0..1 DocumentPosition.valueCodeableConcept (system vat-rate: 23, 8, 5, 0)
Kwota VAT (wiersz) vatAmount 0..1 DocumentPosition.valueItem (type=vat-amount) + valueMoney
Akcyza (wiersz) exciseAmount 0..1 DocumentPosition.valueItem (type=excise-amount) + valueMoney; opcjonalnie valueCodeableConcept (rodzaj/stawka akcyzy)
Suma wartości netto z podziałem na stawki totalNetByRate 0..* Document.attribute (np. total-net-23, total-net-8) lub position (vat-summary-line)
Kwota VAT z podziałem na stawki totalVatByRate 0..* Document.attribute lub position (vat-summary-line)
Suma akcyzy (dokument) totalExcise 0..1 Document.attribute (code=total-excise, valueMoney)
Kwota należności ogółem totalGross 1..1 Document.attribute (code=total-gross, valueMoney)
Numer identyfikacyjny KSeF 0..1 Document.identifier – element z Identifier.system wskazującym na KSeF (np. https://ksef.mf.gov.pl/), Identifier.value = numer nadany przez KSeF
Data sprzedaży (gdy inna niż wystawienia) saleDate 0..1 Konwencja FK: saleDate (date)
Termin płatności / data płatności dueDate 0..1 Konwencja FK: dueDate (date)
Sposób zapłaty / podział płatności paymentMethod, splitPayment 0..1 Konwencja FK: paymentMethod (CodeableConcept), splitPayment (boolean)
Rachunek bankowy do płatności paymentAccount 0..1 Konwencja FK: paymentAccount (Reference BankAccount)

Uwaga: wystawca i nabywca są wyrażeni przez referencje: participant to Reference(PartyRole) (nie pełny obiekt PartyRole); w PartyRole pole party to Reference(Party). Dane strony (nazwa, adres, NIP) są w zasobie Party; w payloadzie faktury można je osadzić w contained lub udostępnić osobnym zasobem.


3. Pola rozszerzenia FK (faktura w Document)

Pola poniżej nie są w rdzeniu Document; należą do konwencji FK dla faktury i są realizowane przez atrybuty (Document.attribute z ustalonym code) oraz ustalone rozszerzenia schematu. W API/OpenAPI mogą być opisane jako rozszerzenie schematu Document.

Pole rozszerzenia FK Typ Kard. Odpowiednik prawny / KSeF Uwagi
saleDate date 0..1 Data sprzedaży (gdy inna niż data wystawienia) Art. 106e; KSeF Fa.DataSprzedazy
dueDate date 0..1 Termin płatności CDM: DueDate
paymentMethod CodeableConcept 0..1 Sposób zapłaty (przelew, gotówka, karta…) System np. payment-method
paymentAccount Reference(BankAccount) 0..1 Rachunek bankowy do wpłaty Referencja do BankAccount (nie pełny obiekt); numer konta w zasobie docelowym
splitPayment boolean 0..1 Mechanizm podzielonej płatności (MPP) Wymóg oznakowania na fakturze
(numer KSeF) 0..1 Numer nadany przez KSeF Document.identifier – element z system wskazującym na KSeF (np. https://ksef.mf.gov.pl/), value = numer KSeF; nie osobne pole ksefIdentifier
ksefAcquisitionDate dateTime 0..1 Data otrzymania w KSeF (rejestracji) Oficjalna data otrzymania faktury
invoiceNumber string 0..1 Kolejny numer faktury (jeśli nie tylko identifier) Może być wyciągnięte z identifier
currency string (ISO 4217) 0..1 Waluta faktury Domyślnie z valueMoney w position/attribute
totalAmount Money 0..1 Kwota należności ogółem Redundantne z attribute total-gross; dla wygody API

Te pola są „wprost” nazwane zgodnie z funkcją prawną/biznesową, co ułatwia walidację i mapowanie na format wymagany przy obsłudze KSeF (nadal w ramach weryfikacji zgodności modelu, a nie profilu urzędowego).


4. Mapowanie struktury logicznej KSeF (FA) na Document

Struktura FA(2)/FA(3) (Naglowek, Podmiot1/2/3, Fa, FaWiersz, Stopka) mapuje się na Document w następujący sposób:

Element FA (KSeF) Odpowiednik w Document
Naglowek (numer, daty, identyfikatory) Document.identifier (w tym element z system KSeF, value = numer KSeF), Document.issueDate, Document.type, Document.status; konwencja FK: saleDate, dueDate, ksefAcquisitionDate
Podmiot1 (wystawca) Document.participant[0] = Reference(PartyRole); role=seller; dane strony w zasobie Party (Reference w PartyRole.party)
Podmiot2 (nabywca) Document.participant[1] = Reference(PartyRole); role=buyer; dane w Party (PartyRole.party)
Podmiot3 (inne, np. płatnik) Document.participant[2] = Reference(PartyRole) z role (CodeableConcept)
Fa (część faktury: wiersze, rozliczenia, płatności) Document.position[] (wiersze + opcjonalnie vat-summary-line), Document.attribute[] (sumy, w tym total-excise), konwencja FK: paymentMethod, paymentAccount, splitPayment
FaWiersz (pojedynczy wiersz) DocumentPosition: code=invoice-line, positionNo, valueItem (quantity, unit-price, net-amount, vat-amount, excise-amount), valueCodeableConcept (vat-rate, rodzaj akcyzy), valueReference = referencje do ProductDefinition/Product, valueString (opis)
Stopka (podsumowanie) Document.attribute (total-net, total-vat, total-excise, total-gross) oraz opcjonalnie position z code=vat-summary-line per stawka

Dzięki temu jeden zasób Document z type=invoice oraz konwencje FK pozwalają zmieścić zarówno wymagania prawne, jak i logiczną strukturę FA używaną przy KSeF — bez duplikowania osobnego modelu wyłącznie pod KSeF.


5. Wiersz faktury (DocumentPosition, code=invoice-line)

Dla position z code = invoice-line (system https://api-erp.kamsoft.pl/ns/document-position-type) konwencja FK dla faktury ustala użycie pól. Wymagane w każdym wierszu: code (1..1), positionNo (1..1), wartość netto pozycji net-amount (1..1); pozostałe pola wg potrzeb.

Element prawny / biznesowy Kard. Pole DocumentPosition
Rodzaj pozycji 1..1 code = invoice-line
Numer pozycji 1..1 positionNo (integer, od 1)
Opis towaru/usługi 0..1 valueString
Ilość 0..1 valueQuantity lub valueItem (type=quantity)
Jednostka miary 0..1 valueQuantity.unit lub valueCodeableConcept
Cena jedn. netto 0..1 valueItem (type=unit-price, valueMoney)
Wartość netto pozycji 1..1 valueItem (type=net-amount, valueMoney)
Stawka VAT 0..1 valueCodeableConcept (system vat-rate: 23, 8, 5, 0)
Kwota VAT pozycji 0..1 valueItem (type=vat-amount, valueMoney)
Akcyza (wiersz) 0..1 valueItem (type=excise-amount, valueMoney); opcjonalnie valueCodeableConcept (rodzaj akcyzy – system np. excise-type)
Towar/usługa (katalog/instancja) 0..* valueReference = referencja do ProductDefinition lub Product (nie pełny obiekt)
Rabat 0..1 valueItem (type=discount) lub attribute w pozycji

Numeracja wierszy: positionNo (1, 2, 3, …) — spójna dla referencji pozycji źródłowych.


6. Zgodność z Common Data Model (CDM)

Model Document dla faktury (z konwencją FK) jest zbieżny z podejściem Microsoft Common Data Model:

  • Invoice (CRM): nagłówek (daty, kontrahent, kwoty) + powiązane szczegóły — u nas Document (participant → PartyRole seller/buyer, issueDate, attribute total-gross) + position.
  • FreeTextInvoiceHeaderEntity (Finance): InvoiceNumber, InvoiceDate, DueDate, CustomerAccount, CurrencyCode, PaymentTerms — u nas: identifier (system + value — numer faktury), issueDate, konwencja FK: dueDate, participant[1] → PartyRole (buyer), PartyRole.party = nabywca, currency w Money, konwencja FK: paymentMethod/dueDate.
  • CustInvoiceTrans (wiersze): ilość, kwoty, VAT — u nas DocumentPosition (valueItem: quantity, net-amount, vat-amount; valueCodeableConcept: vat-rate).

Różnica: w CDM często osobne encje dla nagłówka i wierszy; u nas jeden zasób Document z position[] i attribute[], co upraszcza wymianę i walidację jednym dokumentem.


7. Odniesienia

  • Document — rdzeń dokumentu (identifier, issueDate, participant, position, attribute)
  • DocumentPosition — wiersz faktury (invoice-line) i vat-summary-line
  • Attribute — atrybuty dokumentu (total-net, total-vat, total-gross)
  • PartyRole (participant → seller, buyer), Party (PartyRole.party — dane wystawcy i nabywcy)
  • BankAccount — rachunek do płatności (konwencja FK: paymentAccount)
  • KSeF – struktura FA(3) — struktura logiczna e-faktury
  • Art. 106e ustawy z 11.03.2004 r. o podatku od towarów i usług — obowiązkowe elementy faktury
  • Przykład JSON faktury: Document-Examples §2 FK – Faktura (Invoice)