Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/DTOs/ReplenishmentOrder/ReplenishmentOrderDTO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public class ReplenishmentOrderResponseDto
{
public Guid OrderId { get; set; }
public string Isbn { get; set; }
public DateOnly OrderDate { get; set; }
public DateTime OrderDate { get; set; }
public int Quantity { get; set; }
public string Status { get; set; }
}
19 changes: 19 additions & 0 deletions backend/Migrations/004_DateToTimestamp.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-- Migration to change DATE columns to TIMESTAMPTZ for timezone support
-- This ensures proper handling of timezone offsets in frontend/backend
-- TIMESTAMPTZ stores timestamps in UTC internally and converts based on timezone

-- Alter customer_order table
ALTER TABLE customer_order
ALTER COLUMN order_date TYPE TIMESTAMPTZ
USING order_date::TIMESTAMPTZ;

ALTER TABLE customer_order
ALTER COLUMN order_date SET DEFAULT CURRENT_TIMESTAMP;

-- Alter replenishment_order table
ALTER TABLE replenishment_order
ALTER COLUMN order_date TYPE TIMESTAMPTZ
USING order_date::TIMESTAMPTZ;

ALTER TABLE replenishment_order
ALTER COLUMN order_date SET DEFAULT CURRENT_TIMESTAMP;
2 changes: 1 addition & 1 deletion backend/Models/ReplenishmentOrder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public class ReplenishmentOrder
{
public Guid OrderId { get; set; }
public string Isbn { get; set; }
public DateOnly OrderDate { get; set; }
public DateTime OrderDate { get; set; }
public int Quantity { get; set; }
public string Status { get; set; }
}
5 changes: 5 additions & 0 deletions backend/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
var builder = WebApplication.CreateBuilder(args);
Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;

// Configure Npgsql to read timestamps as UTC
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", false);

// Load DB Connection
var connectionString = Environment.GetEnvironmentVariable("CONNECTION_STRING");
if (string.IsNullOrEmpty(connectionString))
Expand All @@ -41,6 +44,8 @@
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
// Ensure DateTime values are serialized as UTC with 'Z' suffix
options.JsonSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
});


Expand Down Expand Up @@ -96,7 +101,7 @@
ValidIssuer = cfg["Jwt:Issuer"],
ValidAudience = cfg["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(cfg["Jwt:Key"])

Check warning on line 104 in backend/Program.cs

View workflow job for this annotation

GitHub Actions / Backend Unit Tests

Possible null reference argument for parameter 's' in 'byte[] Encoding.GetBytes(string s)'.

Check warning on line 104 in backend/Program.cs

View workflow job for this annotation

GitHub Actions / Backend Unit Tests

Possible null reference argument for parameter 's' in 'byte[] Encoding.GetBytes(string s)'.
)
};
});
Expand Down
10 changes: 8 additions & 2 deletions backend/Repositories/CustomerOrder/CustomerOrderRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,18 @@ INSERT INTO customer_order_item(order_id, isbn, quantity, price)
public async Task<IEnumerable<CustomerOrder>> GetOrdersAsync(Guid userId)
{
const string sql = @"
SELECT order_id as OrderId, u_id as UserId, order_date::timestamp as OrderDate, total_price as TotalPrice
SELECT order_id as OrderId, u_id as UserId, order_date AT TIME ZONE 'UTC' as OrderDate, total_price as TotalPrice
FROM customer_order
WHERE u_id = @UserId
ORDER BY order_date DESC;
";
return (await _db.QueryAsync<CustomerOrder>(sql, new { UserId = userId })).ToList();
var orders = await _db.QueryAsync<CustomerOrder>(sql, new { UserId = userId });
// Ensure DateTime is marked as UTC
foreach (var order in orders)
{
order.OrderDate = DateTime.SpecifyKind(order.OrderDate, DateTimeKind.Utc);
}
return orders.ToList();
}

public async Task<IEnumerable<CustomerOrderItem>> GetOrderItemsAsync(Guid orderId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,28 @@ public ReplenishmentOrderRepository(IDbConnection db)

public async Task<IEnumerable<ReplenishmentOrder>> GetAllAsync()
{
return await _db.QueryAsync<ReplenishmentOrder>(
var orders = await _db.QueryAsync<ReplenishmentOrder>(
"SELECT * FROM replenishment_order ORDER BY order_date DESC;"
);
// Ensure DateTime is marked as UTC
foreach (var order in orders)
{
order.OrderDate = DateTime.SpecifyKind(order.OrderDate, DateTimeKind.Utc);
}
return orders;
}

public async Task<ReplenishmentOrder?> GetByIdAsync(Guid orderId)
{
return await _db.QuerySingleOrDefaultAsync<ReplenishmentOrder>(
var order = await _db.QuerySingleOrDefaultAsync<ReplenishmentOrder>(
"SELECT * FROM replenishment_order WHERE order_id = @OrderId;",
new { OrderId = orderId }
);
if (order != null)
{
order.OrderDate = DateTime.SpecifyKind(order.OrderDate, DateTimeKind.Utc);
}
return order;
}

public async Task ConfirmAsync(Guid orderId)
Expand Down
6 changes: 5 additions & 1 deletion frontend/app/admin/home/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,14 @@ export default function AdminDashboard() {

const formatDate = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleDateString("en-US", {
return date.toLocaleString(undefined, {
year: "numeric",
month: "short",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
timeZoneName: "short",
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
});
};

Expand Down
6 changes: 5 additions & 1 deletion frontend/app/admin/publisher-orders/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,14 @@ export default function PublisherOrdersPage() {

const formatDate = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleDateString("en-US", {
return date.toLocaleString(undefined, {
year: "numeric",
month: "long",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
timeZoneName: "short",
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
});
};

Expand Down
8 changes: 6 additions & 2 deletions frontend/app/user/orders/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,25 @@ export default function OrdersPage() {

const formatDate = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleDateString("en-US", {
return date.toLocaleDateString(undefined, {
year: "numeric",
month: "long",
day: "numeric",
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
});
};

const formatDateTime = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleString("en-US", {
return date.toLocaleString(undefined, {
year: "numeric",
month: "long",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
timeZoneName: "short",
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
});
};

Expand Down
Loading