blocker fix phases added

This commit is contained in:
hamid
2026-08-02 20:37:14 +03:30
parent fb58ca54e1
commit 42f38f5a72
17 changed files with 661 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
# Phase 04 — The 30-minute payment countdown can lie
**Blocker:** blockers.md § "Payments" (the timezone item).
**Depends on:** nothing. Small and contained.
**Related:** [13-booking-lifecycle.md](13-booking-lifecycle.md)'s "today's visits" fix needs a consistent
timezone decision — resolve that the same way once you land this.
---
**Root cause, precise.** `BookingRequest.PaymentDeadlineAt`/`NurseResponseDeadlineAt` are `DateTime` (not
`DateTimeOffset`, deliberately, per a comment about SQLite test-provider compatibility —
`BookingRequest.cs:53-60`). The value is written correctly as UTC
(`AcceptBookingRequestCommand.Handler.cs:41-50`), but **SQL Server's `datetime2` carries no timezone**, and
EF's SQL Server provider returns `Kind = Unspecified` on read — nothing resets it to `Utc`
(`BookingRequestConfig.cs:19-26` has no `.HasConversion(...)` for these two properties, unlike
`BaseEntity.CreatedAt`/`ModifiedAt`, which correctly use `DateTimeOffset`). System.Text.Json therefore
serializes it **without** a trailing `Z`. `Date.parse()` on the client
(`client/src/components/CountdownTimer/CountdownTimer.tsx:84`) reads a `Z`-less ISO string as **local time**,
not UTC — for a Tehran browser (UTC+3:30) that's ~3.5 hours added to the true deadline, so the countdown
shows hours more time than actually remains and expires while still showing time left.
**The fix.** Add an EF Core value converter (new file, e.g.
`server/src/Infrastructure/Baya.Infrastructure.Persistence/ValueConversion/UtcDateTimeConverter.cs`, same
pattern as the existing `EncryptedStringConverter.cs`): `convertFromProvider: v =>
DateTime.SpecifyKind(v, DateTimeKind.Utc)` (no-op on write). Apply it to both `PaymentDeadlineAt` and
`NurseResponseDeadlineAt` in `BookingRequestConfig.cs:19-26`. No migration needed — same column type, only
the in-memory `Kind` tag changes on read.
**Flag:** the same defect class (a `DateTime` read back from `datetime2` losing `Kind`) likely recurs
anywhere else a server-frozen instant feeds a client countdown (e.g. `dispute_window_ends_at`, BNPL
`settled_at`) — worth a grep for other `DateTime` (not `DateTimeOffset`) properties before considering this
class of bug fully closed, not just the one already reported.