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>
3.3 KiB
3.3 KiB
Datumy v requestech a UTC kontrola SDK
Problém
POST /issued-invoices (a stejně tak další Post/Patch endpointy) končil chybou HTTP 500
s prázdným tělem. V logu kontejneru:
IdokladSdk.Exceptions.IdokladValidationException: Model is not valid.
DateTime must be in UTC format.
DateTime must be in UTC format.
DateTime must be in UTC format.
DateTime must be in UTC format
at IdokladSdk.Clients.BaseClient.ValidateModel[T](T model)
at IdokladSdk.Clients.BaseClient.PostAsync[TPostModel,TGetModel](String resource, TPostModel model, ...)
Chyby byly čtyři, protože model faktury má čtyři datumy: DateOfIssue, DateOfMaturity,
DateOfTaxing a DateOfVatApplication.
Příčina:
- Klient posílá datum bez časové zóny, například
"DateOfIssue":"2026-08-25". - Newtonsoft s výchozím
DateTimeZoneHandling.RoundtripKindtakovou hodnotu načte jakoDateTimeKind.Unspecified. - SDK před odesláním requestu validuje model a u každé položky
DateTimevyžadujeKind == Utc. Validace tedy selhala ještě předtím, než se cokoli odeslalo do iDokladu. IdokladValidationExceptiondědí zSystem.ComponentModel.DataAnnotations.ValidationException, ne zIdokladBaseException.ExceptionHandlingMiddlewareji proto nezachytil a request skončil jako neošetřená 500 bez těla. Z odpovědi nebylo poznat, co je špatně.
Ověřeno, že s tím nesouvisí změna serializace z serializace-odpovedi.md.
Deserializace stejného JSONu dává Kind=Unspecified shodně s původním DefaultContractResolver
i s novým SdkContractResolver.
Řešení
| Soubor | Změna |
|---|---|
Program.cs |
SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc |
Infrastructure/ExceptionHandlingMiddleware.cs |
nový catch (IdokladValidationException) mapovaný na HTTP 400 |
Detaily:
DateTimeZoneHandling.Utcu hodnoty bez zóny pouze nastavíKindnaUtc, hodnotu neposouvá. Z"2026-08-25"vznikne2026-08-25T00:00:00Z, takže datum zůstává stejné.- Hodnota, která zónu nese (například
"2026-08-25T10:00:00+02:00"), se přepočítá do UTC. To je požadované chování, iDoklad pracuje s UTC. - Nastavení platí pro celý serializer, tedy pro všechny agendy, ne jen pro vydané faktury.
- Nový
catchvracíproblem+jsonse statusem 400, zprávou ze SDK a seznamem vadných vlastností v poliinvalidProperties. Validační chyba už neskončí jako prázdná 500.
Ověření
dotnet build -c Releasebez chyb.- Deserializace původního JSONu z logu klienta:
- před změnou všechny čtyři datumy
Kind=Unspecified - po změně všechny čtyři
Kind=Utca shodná hodnota data
- před změnou všechny čtyři datumy
- Běh služby lokálně,
POST /issued-invoicesse stejným tělem, jaké dřív padalo:- dříve: HTTP 500, prázdné tělo, v logu
DateTime must be in UTC format - nyní: HTTP 401
invalid_client, tedy request prošel validací a došel až k přihlášení do iDokladu (test běžel s neplatnými credentials)
- dříve: HTTP 500, prázdné tělo, v logu
- Model s chybějícími povinnými poli vrací HTTP 400 se seznamem chyb.
Po nasazení musí projít:
POST https://services.csbot.cz/apps/idoklad/issued-invoices
s datumy ve tvaru 2026-08-25.
Navazující revize všech ostatních endpointů: revize-endpointu.md.