Skip to content

Commit 32484e8

Browse files
authored
Merge pull request #31 from smekcio/codex/api-2-3-0-alignment
feat(api): align SDK with KSeF API 2.3.0
2 parents 920c062 + a4561ab commit 32484e8

15 files changed

Lines changed: 180 additions & 9 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Projekt odwzorowuje oficjalne przepływy KSeF i zapewnia spójny model pracy w d
1212

1313
## 🔄 Kompatybilność
1414

15-
Aktualna kompatybilność: **KSeF API `v2.2.1`** ([api-changelog.md](https://github.com/CIRFMF/ksef-docs/blob/2.2.1/api-changelog.md)).
15+
Aktualna kompatybilność: **KSeF API `v2.3.0`** ([api-changelog.md](https://github.com/CIRFMF/ksef-docs/blob/2.3.0/api-changelog.md)).
1616

1717
## 🧭 Spis treści
1818

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Dokumentacja opisuje **publiczne API** biblioteki `ksef-client-python` (import:
44

55
Opis kontraktu API (OpenAPI) oraz dokumenty procesowe i ograniczenia systemu znajdują się w `ksef-docs/`.
66

7-
Kompatybilność SDK: **KSeF API `v2.2.1`**.
7+
Kompatybilność SDK: **KSeF API `v2.3.0`**.
88

99
## Wymagania
1010

docs/api/invoices.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ Wymagane minimum w `request_payload`:
3737
- `encryption.initializationVector`
3838
- `filters` (np. `subjectType` + `dateRange`)
3939

40+
Opcjonalnie:
41+
- `onlyMetadata=True` – eksport zwraca wyłącznie `_metadata.json` bez XML faktur.
42+
4043
Uwaga dla `filters.dateRange`:
4144
- ISO date-time bez offsetu jest normalizowany do `Europe/Warsaw` przed wysyłką requestu.
4245

docs/cli/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ Uwagi:
382382
- `--save-upo` wymaga `--wait-upo`.
383383
- `--save-upo` bez rozszerzenia jest traktowane jako sciezka pliku.
384384
- `--save-upo-overwrite` pozwala nadpisac istniejacy plik UPO wskazany przez `--save-upo`.
385+
- Dla `FA_RR (1)` z `--schema-version 1-1E` uzyj `--form-value FA_RR`; CLI normalizuje historyczne `RR` do `FA_RR`.
385386

386387
## `ksef send batch`
387388

@@ -408,6 +409,7 @@ Options:
408409
Walidacja:
409410
- dokladnie jedno z `--zip` albo `--dir`.
410411
- `--save-upo-overwrite` pozwala nadpisac istniejacy plik UPO wskazany przez `--save-upo`.
412+
- Dla `FA_RR (1)` z `--schema-version 1-1E` uzyj `--form-value FA_RR`; CLI normalizuje historyczne `RR` do `FA_RR`.
411413

412414
## `ksef upo get`
413415

@@ -456,12 +458,16 @@ Options:
456458
--from TEXT
457459
--to TEXT
458460
--subject-type TEXT [default: Subject1]
461+
--only-metadata
459462
--poll-interval FLOAT [default: 2.0]
460463
--max-attempts INTEGER [default: 120]
461464
--out TEXT [required]
462465
--base-url TEXT
463466
```
464467

468+
Uwagi:
469+
- `--only-metadata` pobiera tylko `_metadata.json` bez XML faktur.
470+
465471
## Exit codes
466472

467473
- `0` sukces

docs/workflows/batch-session.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ print(session_ref)
5252
## Uwagi
5353

5454
- Wysyłka partów odbywa się na pre-signed URL: **bez Bearer tokena** (workflow wykonuje wywołania z `skip_auth=True`).
55+
- Dla `FA_RR (1)` w wersji `1-1E` przekazuj `formCode.value="FA_RR"` zamiast `RR`.
5556
- Limit czasu wysyłki w sesji wsadowej wynosi **liczba partów × 20 minut na każdy part**; liczba partów wpływa bezpośrednio na czas dostępny na wysyłkę.
5657
- Podział ZIP musi nastąpić **przed szyfrowaniem** (biblioteka wykonuje to w `encrypt_batch_parts()`).
5758
- Korelacja statusów z plikami źródłowymi jest możliwa przez zapisanie hashy SHA-256 faktur (przed szyfrowaniem) i mapowanie ich na identyfikatory w procesie weryfikacji (`invoiceHash`).

docs/workflows/export.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ with KsefClient(KsefClientOptions(base_url=KsefEnvironment.DEMO.value)) as clien
3737
"encryptedSymmetricKey": encryption.encryption_info.encrypted_symmetric_key,
3838
"initializationVector": encryption.encryption_info.initialization_vector,
3939
},
40+
"onlyMetadata": False,
4041
"filters": {
4142
"subjectType": "Subject1",
4243
"dateRange": {
@@ -70,6 +71,7 @@ print(len(result.metadata_summaries), len(result.invoice_xml_files))
7071
## Uwagi
7172

7273
- Części paczki są dostępne pod `package.parts[].url` i są pobierane **bez Bearer tokena** (pre-signed URL).
74+
- Ustaw `onlyMetadata=True`, jeśli potrzebujesz wyłącznie `_metadata.json` bez XML faktur.
7375
- Dla każdego pobranego (zaszyfrowanego) partu workflow liczy hash `SHA-256` (base64) i porównuje z `x-ms-meta-hash`, jeśli nagłówek jest obecny.
7476
- Domyślnie (`KsefClientOptions.require_export_part_hash=True`) brak `x-ms-meta-hash` powoduje `ValueError`.
7577
- Niezgodność hash (`x-ms-meta-hash` vs. wyliczony hash) zawsze powoduje `ValueError`.

docs/workflows/online-session.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ print("OK")
7171
## Uwagi
7272

7373
- `encryption_data` z `open_session()` musi być użyte dla wszystkich faktur wysyłanych w ramach sesji.
74+
- Dla `FA_RR (1)` w wersji `1-1E` przekazuj `formCode.value="FA_RR"` zamiast `RR`.
7475
- Status przetwarzania jest udostępniany asynchronicznie; sprawdzanie statusu odbywa się przez polling.
7576
- Pobranie UPO:
7677
- dla faktury: `get_session_invoice_upo_by_ref()` / `...by_ksef()`

src/ksef_client/cli/commands/export_cmd.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ def export_run(
6969
subject_type: str = typer.Option(
7070
"Subject1", "--subject-type", help="KSeF subject type filter."
7171
),
72+
only_metadata: bool = typer.Option(
73+
False,
74+
"--only-metadata",
75+
help="Export only _metadata.json without invoice XML files.",
76+
),
7277
poll_interval: float = typer.Option(
7378
2.0, "--poll-interval", help="Polling interval in seconds."
7479
),
@@ -89,6 +94,7 @@ def export_run(
8994
date_from=date_from,
9095
date_to=date_to,
9196
subject_type=subject_type,
97+
only_metadata=only_metadata,
9298
poll_interval=poll_interval,
9399
max_attempts=max_attempts,
94100
out=out,

src/ksef_client/cli/commands/send_cmd.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,11 @@ def send_online(
6767
invoice: str = typer.Option(..., "--invoice", help="Path to invoice XML file."),
6868
system_code: str = typer.Option("FA (3)", "--system-code", help="Form code systemCode."),
6969
schema_version: str = typer.Option("1-0E", "--schema-version", help="Form code schemaVersion."),
70-
form_value: str = typer.Option("FA", "--form-value", help="Form code value."),
70+
form_value: str = typer.Option(
71+
"FA",
72+
"--form-value",
73+
help="Form code value (use FA_RR for FA_RR (1) 1-1E).",
74+
),
7175
upo_v43: bool = typer.Option(False, "--upo-v43", help="Request UPO v4.3 format."),
7276
wait_status: bool = typer.Option(
7377
False, "--wait-status", help="Wait until invoice processing status is final."
@@ -125,7 +129,11 @@ def send_batch(
125129
),
126130
system_code: str = typer.Option("FA (3)", "--system-code", help="Form code systemCode."),
127131
schema_version: str = typer.Option("1-0E", "--schema-version", help="Form code schemaVersion."),
128-
form_value: str = typer.Option("FA", "--form-value", help="Form code value."),
132+
form_value: str = typer.Option(
133+
"FA",
134+
"--form-value",
135+
help="Form code value (use FA_RR for FA_RR (1) 1-1E).",
136+
),
129137
parallelism: int = typer.Option(4, "--parallelism", help="Parallel upload worker count."),
130138
upo_v43: bool = typer.Option(False, "--upo-v43", help="Request UPO v4.3 format."),
131139
wait_status: bool = typer.Option(

src/ksef_client/cli/sdk/adapters.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,16 +150,27 @@ def _select_certificate(certs: list[dict[str, Any]], usage_name: str) -> str:
150150

151151

152152
def _build_form_code(system_code: str, schema_version: str, form_value: str) -> dict[str, str]:
153-
if not system_code.strip() or not schema_version.strip() or not form_value.strip():
153+
normalized_system_code = system_code.strip()
154+
normalized_schema_version = schema_version.strip()
155+
normalized_form_value = form_value.strip()
156+
if not normalized_system_code or not normalized_schema_version or not normalized_form_value:
154157
raise CliError(
155158
"Invalid form code options.",
156159
ExitCode.VALIDATION_ERROR,
157160
"Use non-empty --system-code, --schema-version and --form-value.",
158161
)
162+
163+
if (
164+
normalized_system_code == "FA_RR (1)"
165+
and normalized_schema_version == "1-1E"
166+
and normalized_form_value == "RR"
167+
):
168+
normalized_form_value = "FA_RR"
169+
159170
return {
160-
"systemCode": system_code.strip(),
161-
"schemaVersion": schema_version.strip(),
162-
"value": form_value.strip(),
171+
"systemCode": normalized_system_code,
172+
"schemaVersion": normalized_schema_version,
173+
"value": normalized_form_value,
163174
}
164175

165176

@@ -983,6 +994,7 @@ def run_export(
983994
date_from: str | None,
984995
date_to: str | None,
985996
subject_type: str,
997+
only_metadata: bool = False,
986998
poll_interval: float,
987999
max_attempts: int,
9881000
out: str,
@@ -1002,6 +1014,7 @@ def run_export(
10021014
"encryptedSymmetricKey": encryption.encryption_info.encrypted_symmetric_key,
10031015
"initializationVector": encryption.encryption_info.initialization_vector,
10041016
},
1017+
"onlyMetadata": only_metadata,
10051018
"filters": {
10061019
"subjectType": subject_type,
10071020
"dateRange": {
@@ -1060,6 +1073,7 @@ def run_export(
10601073
"metadata_file": str(metadata_path),
10611074
"metadata_count": len(processed.metadata_summaries),
10621075
"xml_files_count": files_saved,
1076+
"only_metadata": only_metadata,
10631077
"out_dir": str(out_dir),
10641078
"from": from_iso,
10651079
"to": to_iso,

0 commit comments

Comments
 (0)