Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@ npm install qrcode node-forge
- `qrcode` jest wymagane dla `client.qr`
- `node-forge` jest wymagane dla `XadesKeyPair.fromPkcs12*`

## Budowanie faktur FA(3)

SDK udostępnia typed builder `FA3Invoice` do generowania poprawnie sformatowanego XML FA(3):

```ts
import { FA3Invoice, FA3Party, FA3TaxCategory } from "ksef-client";

const invoice = FA3Invoice.basic("FV/001/2026")
.seller(FA3Party.polishCompany({ nip: "1111111111", name: "Sprzedawca", address: "ul. Test 1" }))
.buyer(FA3Party.polishCompany({ nip: "2222222222", name: "Nabywca", address: "ul. Test 2" }))
.issueDate("2026-01-07")
.addServiceLine("Usluga", { quantity: "1", unitNetPrice: "100", tax: FA3TaxCategory.standard23() })
.build();

const xml = invoice.toXml();
const wellFormedXml = invoice.toXmlWellFormed();
```

Szczegoly API, korekty, zaliczki i walidacja XML: [`docs/xml/invoice.md`](docs/xml/invoice.md).

## Quick Start

```ts
Expand Down
90 changes: 83 additions & 7 deletions docs/xml/invoice.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# Faktury XML (`buildFakturaXml`, `serializeInvoiceXml`, `buildPefXml`)
# Faktury XML (`FA3Invoice`, `buildFakturaXml`, `serializeInvoiceXml`, `buildPefXml`)

Narzędzia z tej sekcji służą do przygotowania dokumentów XML przekazywanych dalej do workflowów sesji (`online`, `batch`, `offline`).

## API

- `buildFakturaXml(faktura: FakturaInput, options?: FakturaXmlOptions): string`
- `FA3Invoice.basic(number)` / `correction(number)` / `advance(number)` / `settlement(number)`
- `validateFa3XmlWellFormed(xml, options?): void` — sprawdza poprawność składniową XML (well-formedness)
- `serializeInvoiceXml(input: InvoiceXmlInput, options?: FakturaXmlOptions): Buffer`
- `buildPefXml(input: PefUblDocumentInput, options?: { pretty?: boolean }): string`

Expand All @@ -17,6 +19,7 @@ Narzędzia z tej sekcji służą do przygotowania dokumentów XML przekazywanych
- `XmlDocument` (struktura `preserveOrder` z `parseXml`),
- `XmlObject` (dowolny dokument XML jako obiekt),
- `FakturaInput` (obiekt FA2/FA3),
- obiekt buildera FA(3) z `toFakturaInput()` (`FA3Invoice`),
- `PefUblDocumentInput` (`{ Invoice: ... }` albo `{ CreditNote: ... }`).

Dokumenty RR nie mają dedykowanego buildera w SDK. Dla RR użyj gotowego XML (`string`/`Buffer`) i przekaż go dalej do sesji/workflow.
Expand All @@ -39,10 +42,64 @@ Zachowanie:
- normalizacja `KodFormularza` z formatu obiektowego do XML (`@_kodSystemowy`, `@_wersjaSchemy`, `#text`),
- deterministyczne porządkowanie pól (w tym kluczy `P_*`) i pomijanie wartości `undefined`.

## Przykład 1: obiekt FA -> XML
## Przykład 1: typed builder FA(3)

```ts
import { buildFakturaXml } from "ksef-client-typescript";
import { FA3Invoice, FA3Party, FA3TaxCategory } from "ksef-client";

const seller = FA3Party.polishCompany({
nip: "1111111111",
name: "Sprzedawca Sp. z o.o.",
address: { line1: "ul. Test 1", line2: "00-001 Warszawa" },
});

const buyer = FA3Party.polishCompany({
nip: "2222222222",
name: "Nabywca S.A.",
address: "ul. Test 2",
});

const invoice = FA3Invoice.basic("FV/001/2026")
.seller(seller)
.buyer(buyer)
.issueDate("2026-01-07")
.issuePlace("Warszawa")
.addServiceLine("Usluga konsultingowa", {
quantity: "2",
unitNetPrice: "500",
tax: FA3TaxCategory.standard23(),
})
.splitPayment()
.paymentDue("2026-01-21")
.bankAccount({ number: "PL00109010140000071219812874" })
.build();

const xml = invoice.toXml();
```

Builder automatycznie wylicza podsumowania VAT (`P_13_*`, `P_14_*`, `P_15`) i generuje m.in.
`Adnotacje`, `FaWiersz`, płatności, korekty, zaliczki, rozliczenia, zamówienia, transport,
nowe środki transportu, stopkę i załączniki tekstowe/tabelaryczne. Dla sekcji niewspieranych metodami
wygodnymi można użyć typowanych nazwami XSD rozszerzeń `withRawFa(...)`, `withRawRoot(...)`,
`transactionTerms({ raw: ... })` albo `attachment({ raw: ... })`. `withRawRoot(...)` nie podmienia
sekcji zarządzanych przez builder (`Naglowek`, `Podmiot1`, `Podmiot2`, `Fa`, `Stopka`, `Zalacznik`).

Walidacja poprawności składniowej XML FA(3) jest dostępna przez `invoice.toXmlWellFormed()`,
`invoice.toBufferWellFormed()` albo `validateFa3XmlWellFormed(xml)`. Sprawdza wyłącznie
well-formedness przy użyciu `fast-xml-parser` — **nie** weryfikuje zgodności ze schematem XSD.
Pliki `.xsd` w paczce służą jako referencja; `resolveFa3SchemaPath()` lokalizuje je w `src/xml/fa3-schemas/`.

Najważniejsze różnice względem buildera Python:

- brak draftowego `FA3BatchDraft` z JSON round-trip; paczki ZIP można nadal budować przez istniejący batch workflow,
- walidacja biznesowa w TS jest lżejsza i skupiona na wymaganych polach oraz typach faktur,
- `documentDiscount(amount, reason)` / `documentCharge(amount, reason)` — rozliczenie na fakturze rozliczeniowej,
- `correctedAdditionalParty(party)` — korekta danych podmiotu z `Podmiot3` (mapowane do `Podmiot2K` zgodnie ze schematem FA(3)),

## Przykład 2: obiekt FA -> XML

```ts
import { buildFakturaXml } from "ksef-client";

const xml = buildFakturaXml(
{
Expand Down Expand Up @@ -83,10 +140,10 @@ const xml = buildFakturaXml(
);
```

## Przykład 2: PEF UBL -> XML
## Przykład 3: PEF UBL -> XML

```ts
import { buildPefXml } from "ksef-client-typescript";
import { buildPefXml } from "ksef-client";

const pefXml = buildPefXml({
Invoice: {
Expand All @@ -96,15 +153,34 @@ const pefXml = buildPefXml({
});
```

## Przykład 3: `serializeInvoiceXml(...)`
## Przykład 4: `serializeInvoiceXml(...)`

```ts
import { serializeInvoiceXml } from "ksef-client-typescript";
import { FA3Invoice, FA3Party, serializeInvoiceXml } from "ksef-client";

const seller = FA3Party.polishCompany({
nip: "1111111111",
name: "Sprzedawca Sp. z o.o.",
address: "ul. Test 1",
});

const buyer = FA3Party.polishCompany({
nip: "2222222222",
name: "Nabywca S.A.",
address: "ul. Test 2",
});

const fromString = serializeInvoiceXml("<Faktura>...</Faktura>");
const fromObject = serializeInvoiceXml({
Root: { "@_xmlns": "urn:example", A: "1" },
});
const fromBuilder = serializeInvoiceXml(
FA3Invoice.basic("FV/1")
.seller(seller)
.buyer(buyer)
.addServiceLine("Usluga", { quantity: "1", unitNetPrice: "100" })
.build(),
);
```

## Uwagi operacyjne
Expand Down
Loading
Loading