Skip to content

Commit fc86ee9

Browse files
authored
Merge pull request #45 from artpods56/chore/update-openapi-spec
chore: update OpenAPI spec to KSeF API 2.6.0 and regenerate models
2 parents 1351c3c + ca1e575 commit fc86ee9

22 files changed

Lines changed: 785 additions & 34 deletions

openapi.json

Lines changed: 598 additions & 29 deletions
Large diffs are not rendered by default.

src/ksef2/__openapi_version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version = "2.5.0"
1+
version = "2.6.0"

src/ksef2/clients/async_invoices.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
)
99
from ksef2.core.async_protocols import AsyncMiddleware
1010
from ksef2.core.crypto import encrypt_symmetric_key, generate_session_key
11+
from ksef2.domain.models.compression import CompressionType, normalize_compression_type
1112
from ksef2.domain.models.invoices import (
1213
ExportHandle,
1314
ExportInvoicesPayload,
@@ -94,6 +95,7 @@ async def schedule_export(
9495
encryption_certificate: str,
9596
encryption_public_key_id: str | None = None,
9697
only_metadata: bool = False,
98+
compression_type: CompressionType | str | None = None,
9799
) -> ExportHandle:
98100
aes_key, iv = generate_session_key()
99101
encrypted_key = encrypt_symmetric_key(
@@ -107,6 +109,11 @@ async def schedule_export(
107109
initialization_vector=base64.b64encode(iv).decode(),
108110
public_key_id=encryption_public_key_id,
109111
only_metadata=only_metadata,
112+
compression_type=(
113+
normalize_compression_type(compression_type)
114+
if compression_type is not None
115+
else None
116+
),
110117
)
111118
)
112119
spec_resp = await self._endpoints.export(body=spec_request)

src/ksef2/clients/invoices.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
)
99
from ksef2.core.crypto import encrypt_symmetric_key, generate_session_key
1010
from ksef2.core.protocols import Middleware
11+
from ksef2.domain.models.compression import CompressionType, normalize_compression_type
1112
from ksef2.domain.models.invoices import (
1213
ExportHandle,
1314
ExportInvoicesPayload,
@@ -97,6 +98,7 @@ def schedule_export(
9798
encryption_certificate: str,
9899
encryption_public_key_id: str | None = None,
99100
only_metadata: bool = False,
101+
compression_type: CompressionType | str | None = None,
100102
) -> ExportHandle:
101103
"""Schedule an export and return the handle needed to decrypt it later."""
102104
aes_key, iv = generate_session_key()
@@ -111,6 +113,11 @@ def schedule_export(
111113
initialization_vector=base64.b64encode(iv).decode(),
112114
public_key_id=encryption_public_key_id,
113115
only_metadata=only_metadata,
116+
compression_type=(
117+
normalize_compression_type(compression_type)
118+
if compression_type is not None
119+
else None
120+
),
114121
)
115122
)
116123
spec_resp = self._endpoints.export(body=spec_request)

src/ksef2/domain/models/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from ksef2.domain.models.base import KSeFBaseModel, KSeFBaseParams
2+
from ksef2.domain.models.compression import CompressionType, CompressionTypeEnum
23
from ksef2.domain.models.session import (
34
BaseSessionState,
45
FormSchema,
@@ -177,6 +178,8 @@
177178
# base
178179
"KSeFBaseModel",
179180
"KSeFBaseParams",
181+
"CompressionType",
182+
"CompressionTypeEnum",
180183
# session
181184
"BaseSessionState",
182185
"FormSchema",

src/ksef2/domain/models/batch.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@
55
import base64
66
from typing import Self
77

8+
from pydantic import field_validator
9+
810
from ksef2.domain.models.base import KSeFBaseModel
11+
from ksef2.domain.models.compression import (
12+
CompressionType,
13+
normalize_compression_type,
14+
)
915
from ksef2.domain.models.session import BaseSessionState, FormSchema
1016

1117

@@ -45,9 +51,21 @@ class BatchFileInfo(KSeFBaseModel):
4551
file_hash: str
4652
"""SHA-256 hash of the batch file, Base64 encoded."""
4753

54+
compression_type: CompressionType | None = None
55+
"""Compression used for the batch file. Defaults to KSeF's ZIP behavior."""
56+
4857
parts: list[BatchFilePart]
4958
"""List of file parts. Max 50 parts, each max 100MB before encryption."""
5059

60+
@field_validator("compression_type", mode="before")
61+
@classmethod
62+
def _normalize_compression(cls, value: object) -> object:
63+
if value is None:
64+
return None
65+
if isinstance(value, str):
66+
return normalize_compression_type(value)
67+
return value
68+
5169

5270
class BatchEncryptionData(KSeFBaseModel):
5371
"""Encryption material used for the prepared batch payload."""
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from enum import StrEnum
2+
from typing import Literal
3+
4+
type CompressionType = Literal["zip", "tar_gz"]
5+
type CompressionTypeSpecValue = Literal["Zip", "TarGz"]
6+
7+
8+
class CompressionTypeEnum(StrEnum):
9+
ZIP = "Zip"
10+
TAR_GZ = "TarGz"
11+
12+
13+
_COMPRESSION_TYPE_TO_SPEC: dict[CompressionType, CompressionTypeSpecValue] = {
14+
"zip": "Zip",
15+
"tar_gz": "TarGz",
16+
}
17+
_COMPRESSION_TYPE_FROM_SPEC: dict[CompressionTypeSpecValue, CompressionType] = {
18+
value: key for key, value in _COMPRESSION_TYPE_TO_SPEC.items()
19+
}
20+
21+
22+
def normalize_compression_type(
23+
value: CompressionType | CompressionTypeEnum | str,
24+
) -> CompressionType:
25+
if isinstance(value, CompressionTypeEnum):
26+
return _COMPRESSION_TYPE_FROM_SPEC[value.value]
27+
28+
lowered_value = value.strip().lower()
29+
if lowered_value in _COMPRESSION_TYPE_TO_SPEC:
30+
return lowered_value # pyright: ignore[reportReturnType]
31+
32+
if value in _COMPRESSION_TYPE_FROM_SPEC:
33+
return _COMPRESSION_TYPE_FROM_SPEC[value] # pyright: ignore[index]
34+
35+
raise ValueError(
36+
f"Invalid compression type: {value}. Valid compression types are: "
37+
f"{', '.join(_COMPRESSION_TYPE_TO_SPEC)}"
38+
)
39+
40+
41+
def compression_type_to_spec(
42+
value: CompressionType | CompressionTypeEnum | str,
43+
) -> CompressionTypeSpecValue:
44+
return _COMPRESSION_TYPE_TO_SPEC[normalize_compression_type(value)]

src/ksef2/domain/models/invoices.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
from pydantic import field_validator
77

88
from ksef2.domain.models.base import KSeFBaseModel
9+
from ksef2.domain.models.compression import (
10+
CompressionType,
11+
normalize_compression_type,
12+
)
913
from ksef2.domain.models.session import FormSchema
1014
from ksef2.domain.types import CurrencyCodes, KsefInvoiceTypes
1115

@@ -330,6 +334,16 @@ class ExportInvoicesPayload(KSeFBaseModel):
330334
initialization_vector: str
331335
public_key_id: str | None = None
332336
only_metadata: bool = False
337+
compression_type: CompressionType | None = None
338+
339+
@field_validator("compression_type", mode="before")
340+
@classmethod
341+
def _normalize_compression_type(cls, value: object) -> object:
342+
if value is None:
343+
return None
344+
if isinstance(value, str):
345+
return normalize_compression_type(value)
346+
return value
333347

334348

335349
class SendInvoicePayload(KSeFBaseModel):

src/ksef2/infra/mappers/invoices/requests.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from pydantic import BaseModel
88

99
from ksef2.core.crypto import sha256_b64
10+
from ksef2.domain.models.compression import compression_type_to_spec
1011
from ksef2.domain.models import invoices
1112
from ksef2.infra.mappers.helpers import to_aware_datetime
1213
from ksef2.infra.schema.api import spec
@@ -248,6 +249,11 @@ def _(request: invoices.ExportInvoicesPayload) -> spec.InvoiceExportRequest:
248249
),
249250
onlyMetadata=request.only_metadata,
250251
filters=to_spec(request.filter),
252+
compressionType=(
253+
spec.CompressionType(compression_type_to_spec(request.compression_type))
254+
if request.compression_type is not None
255+
else None
256+
),
251257
)
252258

253259

src/ksef2/infra/mappers/sessions/requests.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from pydantic import BaseModel
66

7+
from ksef2.domain.models.compression import compression_type_to_spec
78
from ksef2.domain.models.batch import (
89
BatchFileInfo,
910
BatchFilePart,
@@ -80,6 +81,11 @@ def _(request: BatchFileInfo) -> spec.BatchFileInfo:
8081
return spec.BatchFileInfo(
8182
fileSize=request.file_size,
8283
fileHash=request.file_hash,
84+
compressionType=(
85+
spec.CompressionType(compression_type_to_spec(request.compression_type))
86+
if request.compression_type is not None
87+
else None
88+
),
8389
fileParts=[to_spec(part) for part in request.parts],
8490
)
8591

0 commit comments

Comments
 (0)