revize endpointu: cteni NullableProperty, filtr v UTC, attachments
Kontrola vsech 180 operaci proti falesnemu iDoklad API a round trip 331 modelu SDK v obou smerech. - SdkNullablePropertyConverter doplnuje cteni NullableProperty<T>. Konvertor SDK umi jen zapis, takze PATCH s takovou polozkou koncil prazdnou 500 uz pri cteni tela. Tykalo se 29 modelu. Zapis zustava na konvertoru SDK, odchozi payload se nemeni. - Datum uvnitr NullableProperty se normalizuje na UTC stejne jako zbytek serializace. - ListModifiers parsuje datum ve filtru s AdjustToUniversal a AssumeUniversal. Filtr se zonou se drive posouval o offset. - POST /attachments kontroluje FileName a FileBytes, SDK na ne sahalo bez kontroly na null a vracelo neosetrenou 500. - ExceptionHandlingMiddleware ma posledni zachyt, zadny request uz nekonci prazdnou 500. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
73f01d0228
commit
225161e4ca
@@ -0,0 +1,72 @@
|
||||
# Revize všech endpointů po opravě datumů
|
||||
|
||||
Kontrola navazuje na [datumy-utc.md](datumy-utc.md). Cílem bylo najít další místa se stejnou
|
||||
povahou chyby, tedy vstup, který služba přijme, ale SDK nebo iDoklad ho odmítne, případně
|
||||
tichý posun hodnoty.
|
||||
|
||||
## Jak se to ověřovalo
|
||||
|
||||
1. Reflexní round trip všech 331 modelů SDK (Post, Patch, Get) přesně tím nastavením
|
||||
serializace, které používá služba: serializace odpovědi i deserializace requestu.
|
||||
2. Běh služby proti falešnému iDoklad API, které zachytává odchozí requesty. Projeto všech
|
||||
180 operací z OpenAPI dokumentu a zkontrolováno, co se skutečně odesílá.
|
||||
3. Porovnání klienta `iDoklad.cs` proti OpenAPI dokumentu služby, cesta i HTTP metoda.
|
||||
|
||||
## Nálezy a opravy
|
||||
|
||||
### 1. PATCH padal na NullableProperty (vážné)
|
||||
|
||||
Patch modely používají `NullableProperty<T>`, aby šlo odlišit nevyplněnou položku od položky
|
||||
nastavené na null. Konvertor SDK `NullablePropertyJsonConverter` umí jen zápis, jeho `ReadJson`
|
||||
vyhazuje `NotImplementedException`, protože SDK Patch modely nikdy nedeserializuje. Tato služba
|
||||
je deserializovat musí, takže PATCH s takovou položkou skončil prázdnou 500 už při čtení těla.
|
||||
|
||||
Týkalo se to 29 modelů, mimo jiné `IssuedInvoicePatchModel`, `ReceivedInvoicePatchModel`,
|
||||
`ProformaInvoicePatchModel`, `ContactPatchModel` a `CreditNotePatchModel`. Endpoint spadl podle
|
||||
toho, které položky klient poslal, takže se chyba projevovala nepravidelně.
|
||||
|
||||
Oprava: `Infrastructure/SdkNullablePropertyConverter.cs` čtení doplňuje, zápis nechává na
|
||||
konvertoru SDK, takže odchozí payload se nemění. Zaregistrováno v `SdkContractResolver`.
|
||||
|
||||
Ověřeno, že sémantika zůstává správná: položka vynechaná v těle requestu se do iDokladu
|
||||
neodešle. PATCH tedy nepřepisuje pole, která klient neuvedl.
|
||||
|
||||
### 2. Datum uvnitř NullableProperty nebylo v UTC
|
||||
|
||||
Když je na položce konvertor, Newtonsoft předá hodnotu jako řetězec a `DateTimeZoneHandling`
|
||||
se na ni neuplatní. Datum uvnitř `NullableProperty<DateTime>` proto zůstávalo `Unspecified`
|
||||
a narazilo by na stejnou kontrolu SDK jako u vydaných faktur. Konvertor hodnotu normalizuje
|
||||
stejným pravidlem jako zbytek serializace.
|
||||
|
||||
### 3. Filtr s časovou zónou posouval čas (tiché)
|
||||
|
||||
`Client/ListModifiers.cs` parsoval datum ve filtru bez příznaků zóny. Filtr
|
||||
`(DateOfTaxing~gte~2024-01-01T00:00:00Z)` se do iDokladu odeslal jako `2024-01-01 01:00:00`,
|
||||
tedy posunutý o hodinu, a `+02:00` se posunulo o dvě. Chyba nic nenahlásila, jen vracela jiná
|
||||
data. Opraveno na `AdjustToUniversal | AssumeUniversal`.
|
||||
|
||||
### 4. POST /attachments vracel prázdnou 500
|
||||
|
||||
`AttachmentUploadModel` nemá žádné validační atributy a SDK sahá na jméno souboru bez kontroly
|
||||
na null. Chybějící `FileName` nebo `FileBytes` tedy skončily neošetřenou `NullReferenceException`.
|
||||
Doplněna kontrola v `IntegrationController`, chybějící pole nyní vrací 400.
|
||||
|
||||
### 5. Poslední záchyt v middleware
|
||||
|
||||
`ExceptionHandlingMiddleware` má nově i `catch (Exception)`. Neočekávaná chyba se zaloguje
|
||||
a vrátí jako 400 nebo 500 s typem výjimky v těle. Žádný request už nekončí prázdnou 500,
|
||||
ze které nebylo poznat vůbec nic.
|
||||
|
||||
## Co bylo v pořádku
|
||||
|
||||
- Query parametr `lastCheck` u `GET /system/code-books/changes`. Binder MVC normalizuje
|
||||
hodnotu na UTC správně, `Z` i offset i tvar bez zóny dávají správný okamžik.
|
||||
- Serializace odpovědí. Round trip 331 modelů proběhl bez chyby v obou směrech.
|
||||
- Klient `iDoklad.cs`. Ze 177 rozpoznaných volání neodpovídá službě ani jedno špatnou cestou
|
||||
nebo metodou.
|
||||
|
||||
## Výsledek
|
||||
|
||||
Všech 180 operací proti falešnému iDoklad API: 125 vrátilo 200, 55 vrátilo 400 kvůli
|
||||
záměrně neúplnému testovacímu tělu, žádná nevrátila 5xx. Původní tělo z logu klienta,
|
||||
které chybu odstartovalo, projde a do iDokladu odejde se správnými datumy.
|
||||
Reference in New Issue
Block a user