diff --git a/src/Backend/SolutionErp.Api/Program.cs b/src/Backend/SolutionErp.Api/Program.cs index 68b7116..06728a4 100644 --- a/src/Backend/SolutionErp.Api/Program.cs +++ b/src/Backend/SolutionErp.Api/Program.cs @@ -27,7 +27,11 @@ builder.Host.UseSerilog((ctx, cfg) => cfg .Enrich.FromLogContext()); // ---------- Core services ---------- -builder.Services.AddControllers(); +// [S85 anh Kiệt — TZ FIX] Serialize DateTime UTC-with-Z. EF đọc datetime2 = Unspecified kind → +// default thiếu 'Z' → FE new Date(naive) hiểu là local → lệch +7h ("mới tạo báo 7h trước"). +// UtcDateTimeJsonConverter ép 'Z' cho MỌI timestamp API → FE convert đúng về giờ local. +builder.Services.AddControllers().AddJsonOptions(o => + o.JsonSerializerOptions.Converters.Add(new SolutionErp.Api.Serialization.UtcDateTimeJsonConverter())); builder.Services.AddSignalR(); builder.Services.AddSingleton(); builder.Services.AddHttpContextAccessor(); diff --git a/src/Backend/SolutionErp.Api/Serialization/UtcDateTimeJsonConverter.cs b/src/Backend/SolutionErp.Api/Serialization/UtcDateTimeJsonConverter.cs new file mode 100644 index 0000000..8bebae6 --- /dev/null +++ b/src/Backend/SolutionErp.Api/Serialization/UtcDateTimeJsonConverter.cs @@ -0,0 +1,27 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace SolutionErp.Api.Serialization; + +// [S85 anh Kiet — TZ FIX] Timestamps luu UTC (DateTime.UtcNow) nhung EF doc tu SQL Server +// datetime2 = DateTimeKind.Unspecified -> System.Text.Json mac dinh serialize KHONG co 'Z' +// (vd "2026-06-23T08:20:00") -> FE new Date(naive) hieu la LOCAL -> lech +7h (VN UTC+7, +// "moi tao ma bao 7h truoc"). Converter nay ep serialize UTC ISO-8601 CO 'Z' -> FE new +// Date("...Z") convert dung ve local. System.Text.Json tu dung converter nay cho non-null +// value cua DateTime? (Nullable) nen khong can dang ky rieng cho DateTime?. +public sealed class UtcDateTimeJsonConverter : JsonConverter +{ + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => reader.GetDateTime(); + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + var utc = value.Kind switch + { + DateTimeKind.Utc => value, + DateTimeKind.Local => value.ToUniversalTime(), + _ => DateTime.SpecifyKind(value, DateTimeKind.Utc), // Unspecified (tu EF) = coi la UTC + }; + writer.WriteStringValue(utc.ToString("O")); // ISO-8601 round-trip, co 'Z' + } +}