module util.sample_data; import slf4d; import handy_httpd.components.optional; import auth; import profile; import account; import transaction; import util.money; import std.random; import std.conv; import std.array; import std.datetime; void generateSampleData() { UserRepository userRepo = new FileSystemUserRepository; // Remove all existing user data. foreach (User user; userRepo.findAll()) { userRepo.deleteByUsername(user.username); } const int userCount = uniform(5, 10); for (int i = 0; i < userCount; i++) { try { generateRandomUser(i, userRepo); } catch (Throwable t) { import std.stdio; stderr.writeln(t); throw t; } } info("Random sample data generation complete."); } void generateRandomUser(int idx, UserRepository userRepo) { string username = "testuser" ~ idx.to!string; string password = "testpass"; infoF!"Generating random user %s, password: %s."(username, password); User user = createNewUser(userRepo, username, password); ProfileRepository profileRepo = new FileSystemProfileRepository(username); const int profileCount = uniform(1, 5); for (int i = 0; i < profileCount; i++) { generateRandomProfile(i, profileRepo); } } void generateRandomProfile(int idx, ProfileRepository profileRepo) { string profileName = "test-profile-" ~ idx.to!string; infoF!" Generating random profile %s."(profileName); Profile profile = profileRepo.createProfile(profileName); ProfileDataSource ds = profileRepo.getDataSource(profile); ds.getPropertiesRepository().setProperty("sample-data-idx", idx.to!string); const int accountCount = uniform(1, 10); for (int i = 0; i < accountCount; i++) { generateRandomAccount(i, ds); } auto vendorRepo = ds.getTransactionVendorRepository(); const int vendorCount = uniform(5, 30); for (int i = 0; i < vendorCount; i++) { vendorRepo.insert("Test Vendor " ~ to!string(i), "Testing vendor for sample data."); } infoF!" Generated %d random vendors."(vendorCount); auto tagRepo = ds.getTransactionTagRepository(); const int tagCount = uniform(5, 30); for (int i = 0; i < tagCount; i++) { tagRepo.insert("test-tag-" ~ to!string(i)); } infoF!" Generated %d random tags."(tagCount); auto categoryRepo = ds.getTransactionCategoryRepository(); const int categoryCount = uniform(5, 30); for (int i = 0; i < categoryCount; i++) { categoryRepo.insert(Optional!ulong.empty, "Test Category " ~ to!string(i), "Testing category.", "FFFFFF"); } infoF!" Generated %d random categories."(categoryCount); generateRandomTransactions(ds); } void generateRandomAccount(int idx, ProfileDataSource ds) { AccountRepository accountRepo = ds.getAccountRepository(); string idxStr = idx.to!string; string numberSuffix = "0".replicate(4 - idxStr.length) ~ idxStr; string name = "Test Account " ~ idxStr; AccountType type = choice(ALL_ACCOUNT_TYPES); Currency currency = choice(ALL_CURRENCIES); string description = "This is a testing account generated by util.sample_data.generateRandomAccount()."; Account account = accountRepo.insert( type, numberSuffix, name, currency, description ); infoF!" Generated random account: %s, #%s"(name, numberSuffix); } void generateRandomTransactions(ProfileDataSource ds) { const bool hasVendor = uniform01() > 0.3; const bool hasCategory = uniform01() > 0.2; const TransactionVendor[] vendors = ds.getTransactionVendorRepository.findAll(); const TransactionCategory[] categories = ds.getTransactionCategoryRepository() .findAllByParentId(Optional!ulong.empty); const TransactionTag[] tags = ds.getTransactionTagRepository().findAll(); const Account[] accounts = ds.getAccountRepository().findAll(); SysTime now = Clock.currTime(UTC()); SysTime timestamp = Clock.currTime(UTC()) - seconds(1); for (int i = 0; i < 1000; i++) { Optional!ulong vendorId; if (hasVendor) { vendorId = Optional!ulong.of(choice(vendors).id); } Optional!ulong categoryId; if (hasCategory) { categoryId = Optional!ulong.of(choice(categories).id); } Optional!ulong creditedAccountId; Optional!ulong debitedAccountId; Account primaryAccount = choice(accounts); Optional!ulong secondaryAccount; if (uniform01() < 0.25) { foreach (acc; accounts) { if (acc.id != primaryAccount.id && acc.currency == primaryAccount.currency) { secondaryAccount.value = acc.id; break; } } } if (uniform01() > 0.5) { creditedAccountId = Optional!ulong.of(primaryAccount.id); if (secondaryAccount) debitedAccountId = secondaryAccount; } else { debitedAccountId = Optional!ulong.of(primaryAccount.id); if (secondaryAccount) creditedAccountId = secondaryAccount; } ulong value = uniform(0, 1_000_000); addTransaction( ds, timestamp, now, value, primaryAccount.currency, "Test transaction " ~ to!string(i), vendorId, categoryId, creditedAccountId, debitedAccountId, [] ); infoF!" Generated transaction %d"(i); timestamp -= seconds(uniform(10, 1_000_000)); } }