Remove paid field from Member resource, database migration, tests, seeds, and UI. This field is no longer needed as payment status is now tracked via membership fee cycles.
367 lines
12 KiB
Elixir
367 lines
12 KiB
Elixir
# Script for populating the database. You can run it as:
|
|
#
|
|
# mix run priv/repo/seeds.exs
|
|
#
|
|
|
|
alias Mv.Membership
|
|
alias Mv.Accounts
|
|
alias Mv.MembershipFees.MembershipFeeType
|
|
|
|
# Create example membership fee types
|
|
for fee_type_attrs <- [
|
|
%{
|
|
name: "Standard (Jährlich)",
|
|
amount: Decimal.new("120.00"),
|
|
interval: :yearly,
|
|
description: "Standard jährlicher Mitgliedsbeitrag"
|
|
},
|
|
%{
|
|
name: "Standard (Halbjährlich)",
|
|
amount: Decimal.new("65.00"),
|
|
interval: :half_yearly,
|
|
description: "Standard halbjährlicher Mitgliedsbeitrag"
|
|
},
|
|
%{
|
|
name: "Standard (Vierteljährlich)",
|
|
amount: Decimal.new("35.00"),
|
|
interval: :quarterly,
|
|
description: "Standard vierteljährlicher Mitgliedsbeitrag"
|
|
},
|
|
%{
|
|
name: "Standard (Monatlich)",
|
|
amount: Decimal.new("12.00"),
|
|
interval: :monthly,
|
|
description: "Standard monatlicher Mitgliedsbeitrag"
|
|
}
|
|
] do
|
|
MembershipFeeType
|
|
|> Ash.Changeset.for_create(:create, fee_type_attrs)
|
|
|> Ash.create!(upsert?: true, upsert_identity: :unique_name)
|
|
end
|
|
|
|
for attrs <- [
|
|
# Basic example fields (for testing)
|
|
%{
|
|
name: "String Field",
|
|
value_type: :string,
|
|
description: "Example for a field of type string",
|
|
required: false
|
|
},
|
|
%{
|
|
name: "Date Field",
|
|
value_type: :date,
|
|
description: "Example for a field of type date",
|
|
required: false
|
|
},
|
|
%{
|
|
name: "Boolean Field",
|
|
value_type: :boolean,
|
|
description: "Example for a field of type boolean",
|
|
required: false
|
|
},
|
|
%{
|
|
name: "Email Field",
|
|
value_type: :email,
|
|
description: "Example for a field of type email",
|
|
required: false
|
|
},
|
|
# Realistic custom fields
|
|
%{
|
|
name: "Membership Number",
|
|
value_type: :string,
|
|
description: "Unique membership identification number",
|
|
required: false
|
|
},
|
|
%{
|
|
name: "Emergency Contact",
|
|
value_type: :string,
|
|
description: "Emergency contact person name and phone",
|
|
required: false
|
|
},
|
|
%{
|
|
name: "T-Shirt Size",
|
|
value_type: :string,
|
|
description: "T-Shirt size for events (XS, S, M, L, XL, XXL)",
|
|
required: false
|
|
},
|
|
%{
|
|
name: "Newsletter Subscription",
|
|
value_type: :boolean,
|
|
description: "Whether member wants to receive newsletter",
|
|
required: false
|
|
},
|
|
%{
|
|
name: "Date of Last Medical Check",
|
|
value_type: :date,
|
|
description: "Date of last medical examination",
|
|
required: false
|
|
},
|
|
%{
|
|
name: "Secondary Email",
|
|
value_type: :email,
|
|
description: "Alternative email address",
|
|
required: false
|
|
},
|
|
%{
|
|
name: "Membership Type",
|
|
value_type: :string,
|
|
description: "Type of membership (e.g., Regular, Student, Senior)",
|
|
required: false
|
|
},
|
|
%{
|
|
name: "Parking Permit",
|
|
value_type: :boolean,
|
|
description: "Whether member has parking permit",
|
|
required: false
|
|
}
|
|
] do
|
|
Membership.create_custom_field!(
|
|
attrs,
|
|
upsert?: true,
|
|
upsert_identity: :unique_name
|
|
)
|
|
end
|
|
|
|
# Create admin user for testing
|
|
Accounts.create_user!(%{email: "admin@mv.local"}, upsert?: true, upsert_identity: :unique_email)
|
|
|> Ash.Changeset.for_update(:admin_set_password, %{password: "testpassword"})
|
|
|> Ash.update!()
|
|
|
|
# Create sample members for testing - use upsert to prevent duplicates
|
|
for member_attrs <- [
|
|
%{
|
|
first_name: "Hans",
|
|
last_name: "Müller",
|
|
email: "hans.mueller@example.de",
|
|
join_date: ~D[2023-01-15],
|
|
phone_number: "+49301234567",
|
|
city: "München",
|
|
street: "Hauptstraße",
|
|
house_number: "42",
|
|
postal_code: "80331"
|
|
},
|
|
%{
|
|
first_name: "Greta",
|
|
last_name: "Schmidt",
|
|
email: "greta.schmidt@example.de",
|
|
join_date: ~D[2023-02-01],
|
|
phone_number: "+49309876543",
|
|
city: "Hamburg",
|
|
street: "Lindenstraße",
|
|
house_number: "17",
|
|
postal_code: "20095",
|
|
notes: "Interessiert an Fortgeschrittenen-Kursen"
|
|
},
|
|
%{
|
|
first_name: "Friedrich",
|
|
last_name: "Wagner",
|
|
email: "friedrich.wagner@example.de",
|
|
join_date: ~D[2022-11-10],
|
|
phone_number: "+49301122334",
|
|
city: "Berlin",
|
|
street: "Kastanienallee",
|
|
house_number: "8"
|
|
},
|
|
%{
|
|
first_name: "Marianne",
|
|
last_name: "Wagner",
|
|
email: "marianne.wagner@example.de",
|
|
join_date: ~D[2022-11-10],
|
|
phone_number: "+49301122334",
|
|
city: "Berlin",
|
|
street: "Kastanienallee",
|
|
house_number: "8"
|
|
}
|
|
] do
|
|
# Use upsert to prevent duplicates based on email
|
|
Membership.create_member!(member_attrs, upsert?: true, upsert_identity: :unique_email)
|
|
end
|
|
|
|
# Create additional users for user-member linking examples
|
|
additional_users = [
|
|
%{email: "hans.mueller@example.de"},
|
|
%{email: "greta.schmidt@example.de"},
|
|
%{email: "maria.weber@example.de"},
|
|
%{email: "thomas.klein@example.de"}
|
|
]
|
|
|
|
created_users =
|
|
Enum.map(additional_users, fn user_attrs ->
|
|
Accounts.create_user!(user_attrs, upsert?: true, upsert_identity: :unique_email)
|
|
|> Ash.Changeset.for_update(:admin_set_password, %{password: "testpassword"})
|
|
|> Ash.update!()
|
|
end)
|
|
|
|
# Create members with linked users to demonstrate the 1:1 relationship
|
|
# Only create if users don't already have members
|
|
linked_members = [
|
|
%{
|
|
first_name: "Maria",
|
|
last_name: "Weber",
|
|
email: "maria.weber@example.de",
|
|
join_date: ~D[2023-03-15],
|
|
phone_number: "+49301357924",
|
|
city: "Frankfurt",
|
|
street: "Goetheplatz",
|
|
house_number: "5",
|
|
postal_code: "60313",
|
|
notes: "Linked to user account",
|
|
# Link to the third user (maria.weber@example.de)
|
|
user: Enum.at(created_users, 2)
|
|
},
|
|
%{
|
|
first_name: "Thomas",
|
|
last_name: "Klein",
|
|
email: "thomas.klein@example.de",
|
|
join_date: ~D[2023-04-01],
|
|
phone_number: "+49302468135",
|
|
city: "Köln",
|
|
street: "Rheinstraße",
|
|
house_number: "23",
|
|
postal_code: "50667",
|
|
notes: "Linked to user account - needs payment follow-up",
|
|
# Link to the fourth user (thomas.klein@example.de)
|
|
user: Enum.at(created_users, 3)
|
|
}
|
|
]
|
|
|
|
# Create the linked members - use upsert to prevent duplicates
|
|
Enum.each(linked_members, fn member_attrs ->
|
|
user = member_attrs.user
|
|
member_attrs_without_user = Map.delete(member_attrs, :user)
|
|
|
|
# Check if user already has a member
|
|
if user.member_id == nil do
|
|
# User is free, create member and link - use upsert to prevent duplicates
|
|
Membership.create_member!(
|
|
Map.put(member_attrs_without_user, :user, %{id: user.id}),
|
|
upsert?: true,
|
|
upsert_identity: :unique_email
|
|
)
|
|
else
|
|
# User already has a member, just create the member without linking - use upsert to prevent duplicates
|
|
Membership.create_member!(member_attrs_without_user,
|
|
upsert?: true,
|
|
upsert_identity: :unique_email
|
|
)
|
|
end
|
|
end)
|
|
|
|
# Create sample custom field values for some members
|
|
all_members = Ash.read!(Membership.Member)
|
|
all_custom_fields = Ash.read!(Membership.CustomField)
|
|
|
|
# Helper function to find custom field by name
|
|
find_field = fn name -> Enum.find(all_custom_fields, &(&1.name == name)) end
|
|
find_member = fn email -> Enum.find(all_members, &(&1.email == email)) end
|
|
|
|
# Add custom field values for Hans Müller
|
|
if hans = find_member.("hans.mueller@example.de") do
|
|
[
|
|
{find_field.("Membership Number"),
|
|
%{"_union_type" => "string", "_union_value" => "M-2023-001"}},
|
|
{find_field.("T-Shirt Size"), %{"_union_type" => "string", "_union_value" => "L"}},
|
|
{find_field.("Newsletter Subscription"),
|
|
%{"_union_type" => "boolean", "_union_value" => true}},
|
|
{find_field.("Membership Type"), %{"_union_type" => "string", "_union_value" => "Regular"}},
|
|
{find_field.("Parking Permit"), %{"_union_type" => "boolean", "_union_value" => true}},
|
|
{find_field.("Secondary Email"),
|
|
%{"_union_type" => "email", "_union_value" => "hans.m@private.de"}}
|
|
]
|
|
|> Enum.each(fn {field, value} ->
|
|
if field do
|
|
Membership.CustomFieldValue
|
|
|> Ash.Changeset.for_create(:create, %{
|
|
member_id: hans.id,
|
|
custom_field_id: field.id,
|
|
value: value
|
|
})
|
|
|> Ash.create!(upsert?: true, upsert_identity: :unique_custom_field_per_member)
|
|
end
|
|
end)
|
|
end
|
|
|
|
# Add custom field values for Greta Schmidt
|
|
if greta = find_member.("greta.schmidt@example.de") do
|
|
[
|
|
{find_field.("Membership Number"),
|
|
%{"_union_type" => "string", "_union_value" => "M-2023-015"}},
|
|
{find_field.("T-Shirt Size"), %{"_union_type" => "string", "_union_value" => "M"}},
|
|
{find_field.("Newsletter Subscription"),
|
|
%{"_union_type" => "boolean", "_union_value" => true}},
|
|
{find_field.("Membership Type"), %{"_union_type" => "string", "_union_value" => "Student"}},
|
|
{find_field.("Emergency Contact"),
|
|
%{"_union_type" => "string", "_union_value" => "Anna Schmidt, +49301234567"}}
|
|
]
|
|
|> Enum.each(fn {field, value} ->
|
|
if field do
|
|
Membership.CustomFieldValue
|
|
|> Ash.Changeset.for_create(:create, %{
|
|
member_id: greta.id,
|
|
custom_field_id: field.id,
|
|
value: value
|
|
})
|
|
|> Ash.create!(upsert?: true, upsert_identity: :unique_custom_field_per_member)
|
|
end
|
|
end)
|
|
end
|
|
|
|
# Add custom field values for Friedrich Wagner
|
|
if friedrich = find_member.("friedrich.wagner@example.de") do
|
|
[
|
|
{find_field.("Membership Number"),
|
|
%{"_union_type" => "string", "_union_value" => "M-2022-042"}},
|
|
{find_field.("T-Shirt Size"), %{"_union_type" => "string", "_union_value" => "XL"}},
|
|
{find_field.("Newsletter Subscription"),
|
|
%{"_union_type" => "boolean", "_union_value" => false}},
|
|
{find_field.("Membership Type"), %{"_union_type" => "string", "_union_value" => "Senior"}},
|
|
{find_field.("Parking Permit"), %{"_union_type" => "boolean", "_union_value" => false}},
|
|
{find_field.("Date of Last Medical Check"),
|
|
%{"_union_type" => "date", "_union_value" => ~D[2024-03-15]}}
|
|
]
|
|
|> Enum.each(fn {field, value} ->
|
|
if field do
|
|
Membership.CustomFieldValue
|
|
|> Ash.Changeset.for_create(:create, %{
|
|
member_id: friedrich.id,
|
|
custom_field_id: field.id,
|
|
value: value
|
|
})
|
|
|> Ash.create!(upsert?: true, upsert_identity: :unique_custom_field_per_member)
|
|
end
|
|
end)
|
|
end
|
|
|
|
# Create or update global settings (singleton)
|
|
default_club_name = System.get_env("ASSOCIATION_NAME") || "Club Name"
|
|
|
|
case Membership.get_settings() do
|
|
{:ok, existing_settings} ->
|
|
# Settings exist, update if club_name is different from env var
|
|
if existing_settings.club_name != default_club_name do
|
|
{:ok, _updated} =
|
|
Membership.update_settings(existing_settings, %{club_name: default_club_name})
|
|
end
|
|
end
|
|
|
|
IO.puts("✅ Seeds completed successfully!")
|
|
IO.puts("📝 Created sample data:")
|
|
IO.puts(" - Global settings: club_name = #{default_club_name}")
|
|
IO.puts(" - Membership fee types: 4 types (Yearly, Half-yearly, Quarterly, Monthly)")
|
|
IO.puts(" - Custom fields: 12 fields (String, Date, Boolean, Email, + 8 realistic fields)")
|
|
IO.puts(" - Admin user: admin@mv.local (password: testpassword)")
|
|
IO.puts(" - Sample members: Hans, Greta, Friedrich")
|
|
|
|
IO.puts(
|
|
" - Additional users: hans.mueller@example.de, greta.schmidt@example.de, maria.weber@example.de, thomas.klein@example.de"
|
|
)
|
|
|
|
IO.puts(
|
|
" - Linked members: Maria Weber ↔ maria.weber@example.de, Thomas Klein ↔ thomas.klein@example.de"
|
|
)
|
|
|
|
IO.puts(
|
|
" - Custom field values: Sample data for Hans (6 fields), Greta (5 fields), Friedrich (6 fields)"
|
|
)
|
|
|
|
IO.puts("🔗 Visit the application to see user-member relationships and custom fields in action!")
|