Files
JiriUhlirandClaude Opus 5 225161e4ca 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>
2026-08-25 11:13:21 +02:00

3.8 KiB

Revize všech endpointů po opravě datumů

Kontrola navazuje na 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.