# 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`, 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` 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.