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:
JiriUhlir
2026-08-25 11:13:21 +02:00
co-authored by Claude Opus 5
parent 73f01d0228
commit 225161e4ca
7 changed files with 194 additions and 11 deletions
+17 -1
View File
@@ -96,7 +96,23 @@ public sealed class IntegrationController : ControllerBase
/// <summary>Upload an attachment for a document.</summary>
[HttpPost("attachments")]
public async Task<IActionResult> UploadAttachment([FromBody] AttachmentUploadModel model, CancellationToken ct)
=> Ok(await _service.UploadAttachmentAsync(model, ct));
{
// AttachmentUploadModel carries no validation attributes and the SDK dereferences the file
// name without a null check, so an incomplete model would end as an unhandled 500.
if (string.IsNullOrWhiteSpace(model.FileName))
{
ModelState.AddModelError(nameof(model.FileName), "The FileName field is required.");
}
if (model.FileBytes is null || model.FileBytes.Length == 0)
{
ModelState.AddModelError(nameof(model.FileBytes), "The FileBytes field is required.");
}
return ModelState.IsValid
? Ok(await _service.UploadAttachmentAsync(model, ct))
: ValidationProblem(ModelState);
}
/// <summary>Delete a single attachment by its id.</summary>
[HttpDelete("attachments/{attachmentId:int}")]