1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-21 14:19:39 +02:00
Maybe/app/models/demo/generator.rb
Zach Gollwitzer 5a4c955522
Realistic demo data for performance testing (#2361)
* Realistic demo data for performance testing

* Add note about performance testing

* Fix bugbot issues

* More realistic account values
2025-06-11 18:48:39 -04:00

134 lines
4.5 KiB
Ruby

class Demo::Generator
include Demo::DataHelper
# Public API - these methods are called by rake tasks and must be preserved
def reset_and_clear_data!(family_names, require_onboarding: false)
generate_for_scenario(:clean_slate, family_names, require_onboarding: require_onboarding)
end
def reset_data!(family_names)
generate_for_scenario(:default, family_names)
end
def generate_performance_testing_data!(family_names)
generate_for_scenario(:performance_testing, family_names)
end
def generate_basic_budget_data!(family_names)
generate_for_scenario(:basic_budget, family_names)
end
def generate_multi_currency_data!(family_names)
generate_for_scenario(:multi_currency, family_names)
end
private
# Registry pattern for clean scenario lookup and easy extensibility
def scenario_registry
@scenario_registry ||= {
clean_slate: Demo::Scenarios::CleanSlate,
default: Demo::Scenarios::Default,
basic_budget: Demo::Scenarios::BasicBudget,
multi_currency: Demo::Scenarios::MultiCurrency,
performance_testing: Demo::Scenarios::PerformanceTesting
}.freeze
end
def generators
@generators ||= {
data_cleaner: Demo::DataCleaner.new,
rule_generator: Demo::RuleGenerator.new,
account_generator: Demo::AccountGenerator.new,
transaction_generator: Demo::TransactionGenerator.new,
security_generator: Demo::SecurityGenerator.new,
transfer_generator: Demo::TransferGenerator.new
}
end
def generate_for_scenario(scenario_key, family_names, **options)
raise ArgumentError, "Scenario key is required" if scenario_key.nil?
raise ArgumentError, "Family names must be provided" if family_names.nil? || family_names.empty?
scenario_class = scenario_registry[scenario_key]
unless scenario_class
raise ArgumentError, "Unknown scenario: #{scenario_key}. Available: #{scenario_registry.keys.join(', ')}"
end
puts "Starting #{scenario_key} scenario generation for #{family_names.length} families..."
clear_all_data!
create_families_and_users!(family_names, **options)
families = family_names.map { |name| Family.find_by(name: name) }
scenario = scenario_class.new(generators)
scenario.generate!(families, **options)
# Sync families after generation (except for performance testing)
unless scenario_key == :performance_testing
puts "Running account sync for generated data..."
families.each do |family|
family.accounts.each do |account|
sync = Sync.create!(syncable: account)
sync.perform
end
puts " - #{family.name} accounts synced (#{family.accounts.count} accounts)"
end
end
puts "Demo data loaded successfully!"
end
def clear_all_data!
family_count = Family.count
if family_count > 200
raise "Too much data to clear efficiently (#{family_count} families found). " \
"Please run 'bundle exec rails db:reset' instead to quickly reset the database, " \
"then re-run your demo data task."
end
generators[:data_cleaner].destroy_everything!
end
def create_families_and_users!(family_names, require_onboarding: false, currency: "USD")
family_names.each_with_index do |family_name, index|
create_family_and_user!(family_name, "user#{index == 0 ? "" : index + 1}@maybe.local",
currency: currency, require_onboarding: require_onboarding)
end
puts "Users reset"
end
def create_family_and_user!(family_name, user_email, currency: "USD", require_onboarding: false)
base_uuid = "d99e3c6e-d513-4452-8f24-dc263f8528c0"
id = Digest::UUID.uuid_v5(base_uuid, family_name)
family = Family.create!(
id: id,
name: family_name,
currency: currency,
locale: "en",
country: "US",
timezone: "America/New_York",
date_format: "%m-%d-%Y"
)
family.start_subscription!("sub_1234567890")
family.users.create! \
email: user_email,
first_name: "Demo",
last_name: "User",
role: "admin",
password: "password",
onboarded_at: require_onboarding ? nil : Time.current
family.users.create! \
email: "member_#{user_email}",
first_name: "Demo (member user)",
last_name: "User",
role: "member",
password: "password",
onboarded_at: require_onboarding ? nil : Time.current
end
end