ImplementsCSV Import UI closes #335 #359
4 changed files with 54 additions and 307 deletions
|
|
@ -528,7 +528,9 @@ defmodule Mv.Membership.Import.MemberCSV do
|
||||||
{:ok, member}
|
{:ok, member}
|
||||||
|
|
||||||
{:error, %Ash.Error.Invalid{} = error} ->
|
{:error, %Ash.Error.Invalid{} = error} ->
|
||||||
{:error, format_ash_error(error, line_number)}
|
# Extract email from final_attrs for better error messages
|
||||||
|
email = Map.get(final_attrs, :email) || Map.get(trimmed_member_attrs, :email)
|
||||||
|
{:error, format_ash_error(error, line_number, email)}
|
||||||
|
|
||||||
{:error, error} ->
|
{:error, error} ->
|
||||||
{:error, %Error{csv_line_number: line_number, field: nil, message: inspect(error)}}
|
{:error, %Error{csv_line_number: line_number, field: nil, message: inspect(error)}}
|
||||||
|
|
@ -621,7 +623,7 @@ defmodule Mv.Membership.Import.MemberCSV do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Formats Ash errors into MemberCSV.Error structs
|
# Formats Ash errors into MemberCSV.Error structs
|
||||||
defp format_ash_error(%Ash.Error.Invalid{errors: errors}, line_number) do
|
defp format_ash_error(%Ash.Error.Invalid{errors: errors}, line_number, email) do
|
||||||
# Try to find email-related errors first (for better error messages)
|
# Try to find email-related errors first (for better error messages)
|
||||||
email_error =
|
email_error =
|
||||||
Enum.find(errors, fn error ->
|
Enum.find(errors, fn error ->
|
||||||
|
|
@ -636,35 +638,37 @@ defmodule Mv.Membership.Import.MemberCSV do
|
||||||
%Error{
|
%Error{
|
||||||
csv_line_number: line_number,
|
csv_line_number: line_number,
|
||||||
field: field,
|
field: field,
|
||||||
message: format_error_message(message, field)
|
message: format_error_message(message, field, email)
|
||||||
}
|
}
|
||||||
|
|
||||||
%{message: message} ->
|
%{message: message} ->
|
||||||
%Error{
|
%Error{
|
||||||
csv_line_number: line_number,
|
csv_line_number: line_number,
|
||||||
field: nil,
|
field: nil,
|
||||||
message: format_error_message(message, nil)
|
message: format_error_message(message, nil, email)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
%Error{
|
%Error{
|
||||||
csv_line_number: line_number,
|
csv_line_number: line_number,
|
||||||
field: nil,
|
field: nil,
|
||||||
message: "Validation failed"
|
message: gettext("Validation failed")
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Formats error messages, handling common cases like email uniqueness
|
# Formats error messages, handling common cases like email uniqueness
|
||||||
defp format_error_message(message, field) when is_binary(message) do
|
defp format_error_message(message, field, email) when is_binary(message) do
|
||||||
if email_uniqueness_error?(message, field) do
|
if email_uniqueness_error?(message, field) do
|
||||||
"email has already been taken"
|
# Include email in error message for better user feedback
|
||||||
|
email_str = if email, do: to_string(email), else: gettext("email")
|
||||||
|
gettext("email %{email} has already been taken", email: email_str)
|
||||||
else
|
else
|
||||||
message
|
message
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_error_message(message, _field), do: to_string(message)
|
defp format_error_message(message, _field, _email), do: to_string(message)
|
||||||
|
|
||||||
# Checks if error message indicates email uniqueness constraint violation
|
# Checks if error message indicates email uniqueness constraint violation
|
||||||
defp email_uniqueness_error?(message, :email) do
|
defp email_uniqueness_error?(message, :email) do
|
||||||
|
|
|
||||||
|
|
@ -2110,3 +2110,18 @@ msgstr "Verwenden Sie den Namen des benutzerdefinierten Feldes als CSV-Spaltenü
|
||||||
#, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
msgid "Warnings"
|
msgid "Warnings"
|
||||||
msgstr "Warnungen"
|
msgstr "Warnungen"
|
||||||
|
|
||||||
|
#: lib/mv/membership/import/member_csv.ex
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "Validation failed"
|
||||||
|
msgstr "Validierung fehlgeschlagen: %{message}"
|
||||||
|
|
||||||
|
#: lib/mv/membership/import/member_csv.ex
|
||||||
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
|
msgid "email"
|
||||||
|
msgstr "E-Mail"
|
||||||
|
|
||||||
|
#: lib/mv/membership/import/member_csv.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "email %{email} has already been taken"
|
||||||
|
msgstr "E-Mail %{email} wurde bereits verwendet"
|
||||||
|
|
|
||||||
|
|
@ -2111,3 +2111,18 @@ msgstr ""
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgid "Warnings"
|
msgid "Warnings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv/membership/import/member_csv.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "Validation failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv/membership/import/member_csv.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "email"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/mv/membership/import/member_csv.ex
|
||||||
|
#, elixir-autogen, elixir-format
|
||||||
|
msgid "email %{email} has already been taken"
|
||||||
|
msgstr ""
|
||||||
|
|
|
||||||
|
|
@ -2112,304 +2112,17 @@ msgstr ""
|
||||||
msgid "Warnings"
|
msgid "Warnings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/form.ex
|
#: lib/mv/membership/import/member_csv.ex
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
#~ msgid "Use this form to manage Custom Field Value records in your database."
|
msgid "Validation failed"
|
||||||
#~ msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/form.ex
|
#: lib/mv/membership/import/member_csv.ex
|
||||||
#~ #, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format, fuzzy
|
||||||
#~ msgid "Choose a custom field"
|
msgid "email"
|
||||||
#~ msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
#: lib/mv/membership/import/member_csv.ex
|
||||||
#~ #, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
#~ msgid "Joining year - reduced to 0"
|
msgid "email %{email} has already been taken"
|
||||||
#~ msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#~ #: lib/mv_web/components/layouts/sidebar.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
|
||||||
#~ msgid "Admin"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Regular"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/components/member_filter_component.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
|
||||||
#~ msgid "Payment"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Current"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Paid via bank transfer"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Mark as Unpaid"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Half-yearly contribution for supporting members"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Reduced fee for unemployed, pensioners, or low income"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
|
||||||
#~ msgid "Custom field value not found"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Supporting Member"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Monthly fee for students and trainees"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/components/payment_filter_component.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Filter by payment status"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/form.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Custom field value %{action} successfully"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Total Contributions"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Manage contribution types for membership fees."
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Change Contribution Type"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "New Contribution Type"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Time Period"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
|
||||||
#~ msgid "Custom field value deleted successfully"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
|
||||||
#~ msgid "You do not have permission to access this custom field value"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Cannot delete - members assigned"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Preview Mockup"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Contribution Types"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "This page is not functional and only displays the planned features."
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
|
||||||
#~ msgid "Member since"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/form.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Unsupported value type: %{type}"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/form.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Custom field"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Mark as Paid"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Contribution type"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/components/layouts/sidebar.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Contributions"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Reduced"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "No fee for honorary members"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
|
||||||
#~ msgid "You do not have permission to delete this custom field value"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "%{count} period selected"
|
|
||||||
#~ msgid_plural "%{count} periods selected"
|
|
||||||
#~ msgstr[0] ""
|
|
||||||
#~ msgstr[1] ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Mark as Suspended"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
|
||||||
#~ msgid "Contribution types define different membership fee structures. Each type has a fixed cycle (monthly, quarterly, half-yearly, yearly) that cannot be changed after creation."
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/form.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Choose a member"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Suspend"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Reopen"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/form.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Value"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Why are not all contribution types shown?"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Contribution Start"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Standard membership fee for regular members"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/form.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
|
||||||
#~ msgid "Save Custom Field Value"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Honorary"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Contributions for %{name}"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/components/member_filter_component.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
|
||||||
#~ msgid "Payment status filter"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Family"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/custom_field_value_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format, fuzzy
|
|
||||||
#~ msgid "You do not have permission to view custom field values"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Student"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Quarterly fee for family memberships"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Members can only switch between contribution types with the same payment interval (e.g., yearly to yearly). This prevents complex period overlaps."
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Open Contributions"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_period_live/show.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Member Contributions"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/contribution_type_live/index.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "About Contribution Types"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
||||||
#~ #: lib/mv_web/live/components/member_filter_component.ex
|
|
||||||
#~ #, elixir-autogen, elixir-format
|
|
||||||
#~ msgid "Filter by %{name}"
|
|
||||||
#~ msgstr ""
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue