Przejdź do treści

Model kanoniczny: Invoice i InvoicePosition

Dokument zawiera analizę porównawczą (KSeF, systemy ERP, UBL/CDM) oraz propozycję dedykowanych zasobów kanonicznych Invoice i InvoicePosition – niezależnie od uniwersalnego Document i rozdziału Faktura w Document a KSeF / prawo (weryfikacja, że dane faktury mieszczą się w modelu Document). Niniejszy model definiuje osobne obiekty z jawnymi polami faktury i wiersza.

Profil maszynowy (snapshot z kodu): zestawienie i pliki JSON — Profile kanoniczne; bezpośrednio: Invoice.profile.json, InvoicePosition.profile.json.


1. Cel: Invoice i InvoicePosition jako zasoby dedykowane

  • Document – dokument uniwersalny (FK, WHS, CRM, EOD, HR) z position[] (DocumentPosition) i attribute[]; typ przez type (np. invoice).
  • Faktura w Document – mapowanie na Document i weryfikacja zgodności z art. 106e oraz strukturą FA przy KSeF; zob. Faktura i KSeF (Document).
  • Invoice (niniejszy model) – dedykowany zasób tylko dla faktur: nagłówek z polami wprost (seller, buyer, issueDate, dueDate, paymentAccount, currency, totalNet, totalVat, totalGross, position[] jako InvoicePosition). Ułatwia walidację, API i mapowanie 1:1 na KSeF/ERP bez przechodzenia przez warstwę Document z konwencją FK.

InvoicePosition – jedna pozycja faktury (wiersz): positionNo, description, quantity, unit, unitPriceNet, netAmount, vatRate, vatAmount, productReference, discount. Zagnieżdżony w Invoice (rekomendacja) lub osobny zasób z referencją do Invoice.


2. Analiza porównawcza: nagłówek faktury

Źródło Encja / obiekt Kluczowe pola nagłówka
KSeF FA(2)/FA(3) Naglowek, Podmiot1/2/3, Fa P_1 (numer), P_2_1 (data wystawienia), Podmiot1 (wystawca), Podmiot2 (nabywca), Fa (wiersze, płatność), DataSprzedazy, TerminPlatnosci, WarunkiPlatnosci, NrKontaBankowego, NumerKSeF
UBL 2.3 Invoice ID, IssueDate, AccountingSupplierParty, AccountingCustomerParty, PaymentMeans, LegalMonetaryTotal (LineExtensionAmount, TaxExclusiveAmount, TaxInclusiveAmount, PayableAmount), InvoiceLine[]
SAP SD VBRK (Billing Doc) VBELN, FKART, FKDAT (data), KUNAG (nabywca), VKORG, WAERK (waluta), NETWR, MWSKZ (VAT)
SAP FI BKPF + BSEG / RSEG Dokument księgowy: nagłówek (daty, waluta) + pozycje (konto, kwota Wn/Ma)
Oracle AR RA_CUSTOMER_TRX trx_number, trx_date, bill_to_customer_id, currency_code, term_id (termin płatności), status; lines w RA_CUSTOMER_TRX_LINES
D365 F&O CustInvoiceTable (FreeText) InvoiceId, InvoiceDate, CustomerAccount, DueDate, CurrencyCode, Payment; CustInvoiceTrans (wiersze)
Microsoft CDM Invoice (CRM), FreeTextInvoiceHeaderEntity InvoiceNumber, InvoiceDate, DueDate, CustomerId, TotalAmount, Currency; CDM CustInvoiceTrans: Amount, Quantity, LineNumber
Nasz Document + profil Document + attribute/profile identifier (w tym system KSeF, value = numer KSeF), issueDate, participant (seller/buyer), attribute (total-net, total-vat, total-gross), profil: saleDate, dueDate, paymentMethod, paymentAccount, splitPayment

Wnioski dla kanonicznego Invoice (nagłówek):

  • Identyfikacja: identifier[] (numer faktury, KSeF, origin) – jak Document.
  • Daty: issueDate (1..1), saleDate (0..1), dueDate (0..1), ksefAcquisitionDate (0..1).
  • Strony: seller (1..1 Reference PartyRole), buyer (1..1 Reference PartyRole) – zamiast participant[]; ewentualnie payer (0..1 Reference PartyRole).
  • Kwoty zagregowane: totalNet, totalVat, totalGross (Money) – jawnie, nie tylko w attribute[].
  • Płatność: paymentMethod (CodeableConcept), paymentAccount (Reference BankAccount), splitPayment (boolean).
  • KSeF: numer KSeF = identifier (element z Identifier.system wskazującym na KSeF, np. https://ksef.mf.gov.pl/, Identifier.value = numer nadany przez KSeF); ksefAcquisitionDate (data otrzymania w KSeF).
  • Waluta: currency (string ISO 4217) – wspólna dla nagłówka i pozycji.
  • Powiązania: relatedDocument (Reference Invoice/Document) – korekta, zamówienie.
  • Pozostałe: status, type (invoice, correction, proforma), attachment[].

3. Analiza porównawcza: wiersz faktury (pozycja)

Źródło Encja / obiekt Kluczowe pola wiersza
KSeF FA FaWiersz P_7 (nazwa), P_8A (ilość), P_8B (jednostka), P_9 (cena jedn. netto), P_11 (wartość netto), P_12 (stawka VAT), P_13_1 (kwota VAT), P_14_1 (GTU), odniesienie do towaru/usługi
UBL 2.3 InvoiceLine ID, InvoicedQuantity, LineExtensionAmount, Item (Description, SellersItemIdentification), Price (PriceAmount), TaxTotal per line
SAP SD VBRP POSNR, MATNR (materiał), FKIMG (ilość), NETWR (netto), MWSKZ (VAT), WAERK
Oracle AR RA_CUSTOMER_TRX_LINES line_number, description, quantity, unit_selling_price, extended_amount, tax_code
D365 CustInvoiceTrans LineNum, ItemId, Qty, SalesPrice, LineAmount, TaxGroup, TaxAmount
CDM CustInvoiceTrans LineNumber, Amount, Quantity, Description, ProductId
Nasz DocumentPosition position (invoice-line) code, positionNo, valueItem (quantity, unit-price, net-amount, vat-amount), valueCodeableConcept (vat-rate), valueReference (Product), valueString (opis)

Wnioski dla kanonicznego InvoicePosition:

  • positionNo (integer, 1..1) – numer wiersza od 1.
  • description (string, 0..1) – opis towaru/usługi (P_7, UBL Item/Description).
  • quantity (Quantity, 0..1) – ilość + jednostka (P_8A, P_8B).
  • unitPriceNet (Money, 0..1) – cena jedn. netto (P_9).
  • netAmount (Money, 1..1) – wartość netto pozycji (P_11).
  • vatRate (CodeableConcept, 0..1) – stawka VAT (P_12; system vat-rate).
  • vatAmount (Money, 0..1) – kwota VAT (P_13_1).
  • productReference (Reference ProductDefinition | Product, 0..1) – towar/usługa (nie pełny obiekt).
  • discount (Money lub CodeableConcept, 0..1) – rabat/opust.
  • attribute (0..* Attribute) – rozszerzenia (np. GTU, kod kraju pochodzenia).

4. Proponowana struktura Invoice (zasób kanoniczny)

Invoice rozszerza DomainResource. Pola:

Pole Kard. Typ Opis
identifier 1..* Identifier Identyfikatory faktury: numer (system np. company); opcjonalnie element z system wskazującym na KSeF (np. https://ksef.mf.gov.pl/), value = numer nadany przez KSeF
issueDate 1..1 date Data wystawienia
saleDate 0..1 date Data sprzedaży (gdy inna niż issueDate)
dueDate 0..1 date Termin płatności
seller 1..1 Reference(PartyRole) Wystawca (PartyRole, role=seller)
buyer 1..1 Reference(PartyRole) Nabywca (PartyRole, role=buyer)
payer 0..1 Reference(PartyRole) Płatnik (gdy inny niż buyer)
totalNet 0..1 Money Suma netto (dokument)
totalVat 0..1 Money Suma VAT
totalExcise 0..1 Money Suma akcyzy (dokument); gdy na fakturze są wyroby akcyzowe
totalGross 1..1 Money Kwota należności ogółem
currency 1..1 string (ISO 4217) Waluta faktury
paymentMethod 0..1 CodeableConcept Sposób zapłaty
paymentAccount 0..1 Reference(BankAccount) Rachunek bankowy do wpłaty
splitPayment 0..1 boolean Mechanizm podzielonej płatności (MPP)
ksefAcquisitionDate 0..1 dateTime Data otrzymania w KSeF (rejestracji)
position 1..* InvoicePosition Wiersze faktury (oraz opcjonalnie linie podsumowania VAT)
attribute 0..* Attribute Atrybuty rozszerzające (np. totalNet/totalVat per stawka)
relatedDocument 0..* Reference(Invoice) lub Reference(Document) Korekta, faktura korygowana, zamówienie
attachment 0..* Attachment Załączniki

type (z DomainResource): invoice, correction, proforma (system document-type). status: draft, issued, sent, paid, cancelled.


5. Proponowana struktura InvoicePosition (typ zagnieżdżony lub zasób)

Opcja A – zagnieżdżony w Invoice (jak DocumentPosition w Document):

Pole Kard. Typ Opis
positionNo 1..1 integer Numer wiersza (od 1); do referencji np. LedgerEntry.sourcePositionNo
description 0..1 string Opis towaru/usługi
quantity 0..1 Quantity Ilość + jednostka
unitPriceNet 0..1 Money Cena jedn. netto
netAmount 1..1 Money Wartość netto pozycji
vatRate 0..1 CodeableConcept Stawka VAT (system vat-rate)
vatAmount 0..1 Money Kwota VAT pozycji
exciseAmount 0..1 Money Kwota akcyzy pozycji (gdy wyroby akcyzowe)
exciseType 0..1 CodeableConcept Rodzaj / stawka akcyzy (system np. excise-type); opcjonalnie
productReference 0..1 Reference(ProductDefinition Product)
discount 0..1 Money lub CodeableConcept Rabat/opust
attribute 0..* Attribute Rozszerzenia (GTU, kraj pochodzenia itd.)

Opcja B – InvoicePosition jako osobny zasób (DomainResource): wtedy Invoice.position → Reference(InvoicePosition) i InvoicePosition.invoice → Reference(Invoice). Daje to osobne URI i wersjonowanie per wiersz; typowe w ERP dla „invoice line” jako encji. Dla uproszczenia API kanonicznego rekomendacja: Opcja A (zagnieżdżony), z możliwością rozszerzenia do Opcji B w profilu.

Linie podsumowania VAT (odpowiednik vat-summary-line): można modelować jako InvoicePosition z konwencją (np. positionNo powyżej 9000 lub pole lineType = invoice-line | vat-summary-line) i wypełnionymi netAmount, vatRate, vatAmount (suma per stawka).


6. Mapowanie: Document + profil → Invoice / InvoicePosition

Document + profil Invoice / InvoicePosition
Document.identifier Invoice.identifier
Document.issueDate Invoice.issueDate
Document.participant[0] (seller) Invoice.seller
Document.participant[1] (buyer) Invoice.buyer
Profil: saleDate, dueDate Invoice.saleDate, dueDate
Profil: paymentMethod, paymentAccount, splitPayment Invoice.paymentMethod, paymentAccount, splitPayment
Document + FK: numer KSeF w Document.identifier (system KSeF, value), ksefAcquisitionDate Invoice.identifier (element z system KSeF, value), Invoice.ksefAcquisitionDate
Document.attribute (total-net, total-vat, total-excise, total-gross) Invoice.totalNet, totalVat, totalExcise, totalGross (+ opcjonalnie attribute)
Document.position[] (invoice-line) Invoice.position[] (InvoicePosition)
DocumentPosition.positionNo, valueString InvoicePosition.positionNo, description
DocumentPosition.valueItem (quantity, unit-price, net-amount, vat-amount, excise-amount) InvoicePosition.quantity, unitPriceNet, netAmount, vatAmount, exciseAmount
DocumentPosition.valueCodeableConcept (vat-rate, rodzaj akcyzy) InvoicePosition.vatRate, exciseType
DocumentPosition.valueReference (Product) InvoicePosition.productReference
Document.relatedDocument Invoice.relatedDocument

7. Mapowanie: KSeF FA(2)/FA(3) → Invoice / InvoicePosition

KSeF (Naglowek, Podmiot, Fa) Invoice
P_1 (numer), P_2_1 (data wystawienia) identifier, issueDate
Podmiot1 (wystawca) seller (Reference PartyRole)
Podmiot2 (nabywca) buyer (Reference PartyRole)
Podmiot3 (płatnik) payer (0..1)
DataSprzedazy, TerminPlatnosci saleDate, dueDate
WarunkiPlatnosci, NrKontaBankowego paymentMethod, paymentAccount
NumerKSeF, data rejestracji identifier (system KSeF, value = numer KSeF), ksefAcquisitionDate
Fa (sumy) totalNet, totalVat, totalExcise, totalGross, currency
FaWiersz (pozycja) InvoicePosition (patrz poniżej)
KSeF FaWiersz InvoicePosition
P_7 (nazwa towaru/usługi) description
P_8A (ilość), P_8B (jednostka) quantity (Quantity)
P_9 (cena jedn. netto) unitPriceNet
P_11 (wartość netto) netAmount
P_12 (stawka VAT) vatRate
P_13_1 (kwota VAT) vatAmount
Kwota akcyzy (wiersz) exciseAmount, exciseType
Odniesienie do towaru productReference
P_14_1 (GTU) itd. attribute (code=GTU)

8. Zgodność z systemami ERP (podsumowanie)

System Nagłówek → Invoice Wiersz → InvoicePosition
SAP SD (VBRK/VBRP) VBELN→identifier, FKDAT→issueDate, KUNAG→buyer, WAERK→currency, NETWR→totalNet POSNR→positionNo, MATNR→productReference, FKIMG→quantity, NETWR→netAmount, MWSKZ→vatRate
Oracle AR trx_number→identifier, trx_date→issueDate, bill_to_customer_id→buyer, currency_code→currency line_number→positionNo, description, quantity, unit_selling_price, extended_amount→netAmount
D365 CustInvoiceTable/Trans InvoiceId, InvoiceDate, CustomerAccount→buyer, DueDate, CurrencyCode LineNum→positionNo, Qty, SalesPrice, LineAmount, TaxGroup→vatRate
UBL 2.3 Invoice ID, IssueDate, AccountingSupplierParty→seller, AccountingCustomerParty→buyer, LegalMonetaryTotal→totalNet/totalVat/totalGross InvoiceLine: InvoicedQuantity→quantity, LineExtensionAmount→netAmount, Price/PriceAmount→unitPriceNet
CDM InvoiceNumber, InvoiceDate, DueDate, CustomerId→buyer, TotalAmount→totalGross LineNumber→positionNo, Quantity, Amount→netAmount

9. Relacja do Document i profilu

  • Document + konwencja FK dla faktury – nadal obowiązuje dla unifikacji wszystkich typów dokumentów (faktura, zamówienie, PZ, dekret) w jednym zasobie Document z position[] i attribute[]; Faktura i KSeF (Document) opisuje mapowanie oraz weryfikację, że wymagania prawne i struktura FA przy KSeF mieszczą się w tym zasobie.
  • Invoice + InvoicePositiondedykowany model kanoniczny dla faktur: jawna struktura (seller, buyer, totalNet, totalVat, totalGross, position[].netAmount, vatRate itd.), wygodna walidacja i integracja z KSeF/ERP. W implementacji można:
  • wystawiać tylko Invoice (API faktur) i opcjonalnie transformować do Document dla EOD/archiwum, albo
  • utrzymywać Document jako źródło prawdy i generować Invoice jako widok/zestawienie dla klientów API faktur.

10. Odniesienia