fix(pdf-export): match DateTime.from_iso8601 three-tuple when formatting cells

DateTime.from_iso8601/1 returns {:ok, datetime, offset}, so the two-tuple clauses never matched and datetime cells fell through to the naive-parse fallback. Matching the real shape routes them through the intended DateTime path; UTC values render identically.
This commit is contained in:
Moritz 2026-06-02 12:04:37 +02:00
parent c41d24113f
commit 2db467d5d1
2 changed files with 25 additions and 7 deletions

View file

@ -143,7 +143,7 @@ defmodule Mv.Membership.MembersPDF do
defp convert_to_template_format(export_data, locale, club_name) do defp convert_to_template_format(export_data, locale, club_name) do
# Set locale for translations # Set locale for translations
Gettext.put_locale(MvWeb.Gettext, locale) _ = Gettext.put_locale(MvWeb.Gettext, locale)
headers = Enum.map(export_data.columns, & &1.label) headers = Enum.map(export_data.columns, & &1.label)
column_count = length(export_data.columns) column_count = length(export_data.columns)
@ -211,9 +211,6 @@ defmodule Mv.Membership.MembersPDF do
{:ok, datetime, _offset} -> {:ok, datetime, _offset} ->
format_datetime(datetime, locale) format_datetime(datetime, locale)
{:ok, datetime} ->
format_datetime(datetime, locale)
{:error, _} -> {:error, _} ->
# Try NaiveDateTime if DateTime parsing fails # Try NaiveDateTime if DateTime parsing fails
case NaiveDateTime.from_iso8601(iso8601_string) do case NaiveDateTime.from_iso8601(iso8601_string) do
@ -257,8 +254,6 @@ defmodule Mv.Membership.MembersPDF do
end end
end end
defp format_date(_, _), do: ""
defp format_dates_in_rows(rows, columns, locale) do defp format_dates_in_rows(rows, columns, locale) do
date_indices = find_date_column_indices(columns) date_indices = find_date_column_indices(columns)
@ -321,7 +316,7 @@ defmodule Mv.Membership.MembersPDF do
defp format_cell_date_datetime(cell_value, locale) do defp format_cell_date_datetime(cell_value, locale) do
case DateTime.from_iso8601(cell_value) do case DateTime.from_iso8601(cell_value) do
{:ok, datetime} -> format_datetime(datetime, locale) {:ok, datetime, _offset} -> format_datetime(datetime, locale)
_ -> format_cell_date_naive(cell_value, locale) _ -> format_cell_date_naive(cell_value, locale)
end end
end end

View file

@ -101,6 +101,29 @@ defmodule Mv.Membership.MembersPDFTest do
assert byte_size(pdf_binary) > 1000 assert byte_size(pdf_binary) > 1000
end end
test "renders date column holding an ISO8601 datetime value" do
# Regression: a date column whose value is a full datetime string must be
# parsed via DateTime.from_iso8601/1 (which returns a 3-tuple) and rendered,
# not silently dropped.
export_data = %{
columns: [
%{key: "first_name", kind: :member_field, label: "Vorname"},
%{key: "join_date", kind: :member_field, label: "Eintritt"}
],
rows: [
["Max", "2024-01-15T14:30:00Z"]
],
meta: %{
generated_at: "2024-01-15T14:30:00Z",
member_count: 1
}
}
assert {:ok, pdf_binary} = MembersPDF.render(export_data)
assert String.starts_with?(pdf_binary, "%PDF")
assert byte_size(pdf_binary) > 1000
end
test "generates valid PDF with custom fields and computed fields" do test "generates valid PDF with custom fields and computed fields" do
export_data = %{ export_data = %{
columns: [ columns: [