mitgliederverwaltung/priv/repo/seeds.exs

363 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
for attrs <- [
# Basic example fields (for testing)
%{
name: "String Field",
value_type: :string,
description: "Example for a field of type string",
immutable: true,
required: false
},
%{
name: "Date Field",
value_type: :date,
description: "Example for a field of type date",
immutable: true,
required: false
},
%{
name: "Boolean Field",
value_type: :boolean,
description: "Example for a field of type boolean",
immutable: true,
required: false
},
%{
name: "Email Field",
value_type: :email,
description: "Example for a field of type email",
immutable: true,
required: false
},
# Realistic custom fields
%{
name: "Membership Number",
value_type: :string,
description: "Unique membership identification number",
immutable: false,
required: false
},
%{
name: "Emergency Contact",
value_type: :string,
description: "Emergency contact person name and phone",
immutable: false,
required: false
},
%{
name: "T-Shirt Size",
value_type: :string,
description: "T-Shirt size for events (XS, S, M, L, XL, XXL)",
immutable: false,
required: false
},
%{
name: "Newsletter Subscription",
value_type: :boolean,
description: "Whether member wants to receive newsletter",
immutable: false,
required: false
},
%{
name: "Date of Last Medical Check",
value_type: :date,
description: "Date of last medical examination",
immutable: false,
required: false
},
%{
name: "Secondary Email",
value_type: :email,
description: "Alternative email address",
immutable: false,
required: false
},
%{
name: "Membership Type",
value_type: :string,
description: "Type of membership (e.g., Regular, Student, Senior)",
immutable: false,
required: false
},
%{
name: "Parking Permit",
value_type: :boolean,
description: "Whether member has parking permit",
immutable: false,
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",
birth_date: ~D[1985-06-15],
join_date: ~D[2023-01-15],
paid: true,
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",
birth_date: ~D[1990-03-22],
join_date: ~D[2023-02-01],
paid: false,
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",
birth_date: ~D[1978-11-08],
join_date: ~D[2022-11-10],
paid: true,
phone_number: "+49301122334",
city: "Berlin",
street: "Kastanienallee",
house_number: "8"
},
%{
first_name: "Marianne",
last_name: "Wagner",
email: "marianne.wagner@example.de",
birth_date: ~D[1978-11-08],
join_date: ~D[2022-11-10],
paid: true,
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",
birth_date: ~D[1992-07-14],
join_date: ~D[2023-03-15],
paid: true,
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",
birth_date: ~D[1988-12-03],
join_date: ~D[2023-04-01],
paid: false,
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
{:ok, nil} ->
# Settings don't exist, create them
Mv.Membership.Setting
|> Ash.Changeset.for_create(:create, %{club_name: default_club_name})
|> Ash.create!(domain: Mv.Membership)
end
IO.puts("✅ Seeds completed successfully!")
IO.puts("📝 Created sample data:")
IO.puts(" - Global settings: club_name = #{default_club_name}")
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!")