136 lines
4.2 KiB
Elixir
136 lines
4.2 KiB
Elixir
# Optional BULK member seed for load / infinite-scroll testing.
|
|
#
|
|
# This is NOT part of the default dev seed (`mix run priv/repo/seeds.exs`), so the
|
|
# normal dev database stays small. Run it explicitly when you need many members:
|
|
#
|
|
# just seed-members-bulk
|
|
# BULK_MEMBER_COUNT=500 mix run priv/repo/seeds_bulk_members.exs
|
|
#
|
|
# Requires the bootstrap seeds (admin user + fee types) to have run first. Members
|
|
# are upserted by email ("bulk-member-<n>@example.de"), so re-running is idempotent
|
|
# and does not duplicate members or their fee cycles.
|
|
|
|
alias Mv.Accounts
|
|
alias Mv.Membership
|
|
alias Mv.MembershipFees.CycleGenerator
|
|
alias Mv.MembershipFees.MembershipFeeType
|
|
|
|
require Ash.Query
|
|
|
|
admin_email = System.get_env("ADMIN_EMAIL") || "admin@localhost"
|
|
|
|
admin_user_with_role =
|
|
case Accounts.User
|
|
|> Ash.Query.filter(email == ^admin_email)
|
|
|> Ash.read_one(domain: Mv.Accounts, authorize?: false) do
|
|
{:ok, user} when not is_nil(user) ->
|
|
user |> Ash.load!(:role, authorize?: false)
|
|
|
|
_ ->
|
|
raise "Bulk seed requires bootstrap: admin user not found (#{admin_email})"
|
|
end
|
|
|
|
all_fee_types =
|
|
MembershipFeeType
|
|
|> Ash.Query.sort(name: :asc)
|
|
|> Ash.read!(actor: admin_user_with_role, domain: Mv.MembershipFees)
|
|
|> Enum.to_list()
|
|
|
|
count =
|
|
case Integer.parse(System.get_env("BULK_MEMBER_COUNT") || "300") do
|
|
{n, _} when n > 0 -> n
|
|
_ -> 300
|
|
end
|
|
|
|
first_names =
|
|
~w(Anna Bruno Clara David Elena Felix Greta Henrik Ines Jakob Laura Max Nina
|
|
Oliver Paula Quirin Rosa Stefan Thea Uwe Vera Wolf Xenia Yannick Zoe Ada
|
|
Ben Carl Dora Emil)
|
|
|
|
last_names =
|
|
~w(Schmidt Müller Fischer Weber Wagner Becker Schulz Hoffmann Koch Richter Klein
|
|
Wolf Neumann Schwarz Zimmermann Braun Krüger Hartmann Lange Werner Krause
|
|
Lehmann Köhler Herrmann Walter)
|
|
|
|
cities = [
|
|
{"München", "80331"},
|
|
{"Hamburg", "20095"},
|
|
{"Berlin", "10435"},
|
|
{"Köln", "50667"},
|
|
{"Frankfurt", "60313"},
|
|
{"Stuttgart", "70173"},
|
|
{"Düsseldorf", "40212"},
|
|
{"Dortmund", "44137"},
|
|
{"Essen", "45127"},
|
|
{"Dresden", "01069"},
|
|
{"Nürnberg", "90402"},
|
|
{"Bremen", "28195"}
|
|
]
|
|
|
|
statuses = [:paid, :unpaid, :suspended]
|
|
|
|
IO.puts("Seeding #{count} bulk members (set BULK_MEMBER_COUNT to change)…")
|
|
|
|
Enum.each(1..count, fn i ->
|
|
{city, postal_code} = Enum.at(cities, rem(i, length(cities)))
|
|
|
|
attrs = %{
|
|
first_name: Enum.at(first_names, rem(i, length(first_names))),
|
|
last_name: Enum.at(last_names, rem(div(i, length(first_names)) + i, length(last_names))),
|
|
email: "bulk-member-#{i}@example.de",
|
|
join_date: Date.add(~D[2020-01-01], rem(i * 7, 2000)),
|
|
city: city,
|
|
street: "Teststraße",
|
|
house_number: Integer.to_string(rem(i, 200) + 1),
|
|
postal_code: postal_code,
|
|
country: "Deutschland"
|
|
}
|
|
|
|
attrs =
|
|
case all_fee_types do
|
|
[] -> attrs
|
|
types -> Map.put(attrs, :membership_fee_type_id, Enum.at(types, rem(i, length(types))).id)
|
|
end
|
|
|
|
member =
|
|
Membership.create_member!(attrs,
|
|
upsert?: true,
|
|
upsert_identity: :unique_email,
|
|
actor: admin_user_with_role
|
|
)
|
|
|
|
# Give the member fee cycles + a round-robin status so the fee-status column is
|
|
# populated at scale. Cycles are only generated when none exist yet; the status
|
|
# is (re-)applied on every run so a run interrupted between generation and the
|
|
# status update still converges (idempotent — the update is a no-op once set).
|
|
if not is_nil(member.membership_fee_type_id) do
|
|
member = Ash.load!(member, :membership_fee_cycles, actor: admin_user_with_role)
|
|
|
|
cycles =
|
|
if Enum.empty?(member.membership_fee_cycles) do
|
|
{:ok, generated, _} =
|
|
CycleGenerator.generate_cycles_for_member(member.id,
|
|
skip_lock?: true,
|
|
actor: admin_user_with_role
|
|
)
|
|
|
|
generated
|
|
else
|
|
member.membership_fee_cycles
|
|
end
|
|
|
|
status = Enum.at(statuses, rem(i, length(statuses)))
|
|
|
|
Enum.each(cycles, fn cycle ->
|
|
if cycle.status != status do
|
|
cycle
|
|
|> Ash.Changeset.for_update(:update, %{status: status})
|
|
|> Ash.update!(actor: admin_user_with_role, domain: Mv.MembershipFees)
|
|
end
|
|
end)
|
|
end
|
|
|
|
if rem(i, 50) == 0, do: IO.puts(" … #{i}/#{count}")
|
|
end)
|
|
|
|
IO.puts("✅ Bulk seed complete: #{count} members.")
|