# 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 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!")