Files
raven/server/AyaNova/util/Seeder.cs
2018-11-12 23:34:47 +00:00

451 lines
22 KiB
C#

using System;
using System.Collections.Generic;
using AyaNova.Models;
using AyaNova.Biz;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using Bogus;
using AyaNova.Api.ControllerHelpers;
using System.Diagnostics;
namespace AyaNova.Util
{
public static class Seeder
{
public enum SeedLevel { SmallOneManShopTrialDataSet, MediumLocalServiceCompanyTrialDataSet, LargeCorporateMultiRegionalTrialDataSet, HugeForLoadTest };
//////////////////////////////////////////////////////
//Seed database for trial and testing purposes
//
public static void SeedDatabase(SeedLevel slevel)
{
SeedDatabase(slevel, Guid.Empty);
}
public static void SeedDatabase(SeedLevel slevel, Guid JobId)
{
bool LogJob = JobId != Guid.Empty;
ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("Seeder");
ApiServerState apiServerState = (ApiServerState)ServiceProviderProvider.Provider.GetService(typeof(ApiServerState));
//get the current server state so can set back to it later
ApiServerState.ServerState wasServerState = apiServerState.GetState();
string wasReason = apiServerState.Reason;
//START SERIAL NUMBER GENERATORS
if (ServerBootConfig.WIDGET_SERIAL == null)
ServerBootConfig.WIDGET_SERIAL = new AutoId(0);
try
{
LogStatus(JobId, LogJob, log, $"SEEDER: Seed data level - {slevel.ToString()}");
//Only allow this in a trial database
if (!AyaNova.Core.License.ActiveKey.TrialLicense)
{
var msg = "This database has a registered license key so it can't be seeded";
LogStatus(JobId, LogJob, log, msg);
throw new System.NotSupportedException(msg);
}
apiServerState.SetOpsOnly("Seeding database");
//Erase all the data except for the license, schema and the manager user
DbUtil.PrepareDatabaseForSeeding(log);
//Seed special test data for integration testing
//log.LogInformation("Seeding known users");
SeedKnownUsers(log);
//log.LogInformation("Seeding all other data");
switch (slevel)
{
case SeedLevel.SmallOneManShopTrialDataSet:
{
#region GenSmall
//This is for a busy but one man shop with a single office person handling stuff back at the shop
//Generate owner and lead tech
GenSeedUser(log, 1, AuthorizationRoles.BizAdminFull | AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryFull | AuthorizationRoles.OpsAdminFull, UserType.Schedulable);
//Generate one office person / secretary
GenSeedUser(log, 1, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryFull | AuthorizationRoles.AccountingFull, UserType.NonSchedulable);
//100 widgets
GenSeedWidget(log, 100);
#endregion gensmall
}
break;
case SeedLevel.MediumLocalServiceCompanyTrialDataSet:
{
#region GenMedium
//This is for a typical AyaNova medium busy shop
//has one location, many techs and full staff for each department
//One IT administrator, can change ops but nothing else
GenSeedUser(log, 1, AuthorizationRoles.OpsAdminFull, UserType.NonSchedulable);
//One business administrator, can view ops issues
GenSeedUser(log, 1, AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable);
//One owner who doesn't control anything but views stuff
GenSeedUser(log, 1, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited | AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable);
//20 techs
GenSeedUser(log, 20, AuthorizationRoles.TechFull | AuthorizationRoles.DispatchLimited, UserType.Schedulable);
//2 subcontractors
GenSeedUser(log, 2, AuthorizationRoles.SubContractorFull, UserType.Subcontractor);
//3 sales / generic office people people
GenSeedUser(log, 3, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited, UserType.NonSchedulable);
//1 dispatch manager
GenSeedUser(log, 1, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryLimited, UserType.NonSchedulable);
//1 Inventory manager
GenSeedUser(log, 1, AuthorizationRoles.InventoryFull | AuthorizationRoles.DispatchLimited, UserType.NonSchedulable);
//1 accountant / bookkeeper
GenSeedUser(log, 1, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NonSchedulable);
//10 full on client users
GenSeedUser(log, 10, AuthorizationRoles.ClientLimited, UserType.Client);
//10 limited client users
GenSeedUser(log, 10, AuthorizationRoles.ClientLimited, UserType.Client);
//500 widgets
GenSeedWidget(log, 500);
#endregion genmedium
}
break;
case SeedLevel.LargeCorporateMultiRegionalTrialDataSet:
{
#region GenLarge
//this is a large corporation with multiple branches in multiple locations all in the same country
//Each location has a full staff and corporate head office has an overarching staff member in charge of each location
//PERF
LogStatus(JobId, LogJob, log, $"Seeding 279 user(s)....");
var watch = new Stopwatch();
watch.Start();
//IT administrator, can change ops but nothing else
GenSeedUser(log, 2, AuthorizationRoles.OpsAdminFull, UserType.NonSchedulable);
//business administrator, can view ops issues
GenSeedUser(log, 2, AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable);
//owner / upper management who doesn't control anything but views stuff
GenSeedUser(log, 5, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited | AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable);
//100 techs
GenSeedUser(log, 100, AuthorizationRoles.TechFull | AuthorizationRoles.DispatchLimited, UserType.Schedulable);
//limited techs
GenSeedUser(log, 50, AuthorizationRoles.TechLimited | AuthorizationRoles.DispatchLimited, UserType.Schedulable);
//20 subcontractors
GenSeedUser(log, 20, AuthorizationRoles.SubContractorFull, UserType.Subcontractor);
//10 limited subcontractors
GenSeedUser(log, 10, AuthorizationRoles.SubContractorLimited, UserType.Subcontractor);
//30 sales / generic office people people
GenSeedUser(log, 30, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited, UserType.NonSchedulable);
//5 dispatch manager
GenSeedUser(log, 5, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryLimited, UserType.NonSchedulable);
//5 Inventory manager
GenSeedUser(log, 5, AuthorizationRoles.InventoryFull | AuthorizationRoles.DispatchLimited, UserType.NonSchedulable);
//10 Inventory manager assistants
GenSeedUser(log, 5, AuthorizationRoles.InventoryLimited, UserType.NonSchedulable);
//5 accountant / bookkeeper
GenSeedUser(log, 5, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NonSchedulable);
//100 full on client users
GenSeedUser(log, 20, AuthorizationRoles.ClientFull, UserType.Client);
//100 limited client users
GenSeedUser(log, 20, AuthorizationRoles.ClientLimited, UserType.Client);
//PERF
watch.Stop();
LogStatus(JobId, LogJob, log, $"279 Users seeded in {watch.ElapsedMilliseconds} ms");
//5000 widgets
LogStatus(JobId, LogJob, log, $"Seeding 5,000 Widgets....");
watch = new Stopwatch();
watch.Start();
GenSeedWidget(log, 5000);
//PERF
watch.Stop();
LogStatus(JobId, LogJob, log, $"5k Widgets seeded in {watch.ElapsedMilliseconds} ms");
#endregion genlarge
}
break;
case SeedLevel.HugeForLoadTest:
{
#region GenHuge
//this is the HUGE dataset for load and other testing
//It is acceptable for this seeding to take many hours as it would normally be used rarely
//PERF
LogStatus(JobId, LogJob, log, $"Seeding 1,410 user(s)....");
var watch = new Stopwatch();
watch.Start();
//IT administrator, can change ops but nothing else
GenSeedUser(log, 10, AuthorizationRoles.OpsAdminFull, UserType.NonSchedulable);
//business administrator, can view ops issues
GenSeedUser(log, 10, AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable);
//owner / upper management who doesn't control anything but views stuff
GenSeedUser(log, 20, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited | AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable);
//regular techs
GenSeedUser(log, 500, AuthorizationRoles.TechFull | AuthorizationRoles.DispatchLimited, UserType.Schedulable);
//limited techs
GenSeedUser(log, 200, AuthorizationRoles.TechLimited | AuthorizationRoles.DispatchLimited, UserType.Schedulable);
//subcontractors
GenSeedUser(log, 80, AuthorizationRoles.SubContractorFull, UserType.Subcontractor);
//limited subcontractors
GenSeedUser(log, 40, AuthorizationRoles.SubContractorLimited, UserType.Subcontractor);
//sales / generic office people people
GenSeedUser(log, 200, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited, UserType.NonSchedulable);
//dispatch manager
GenSeedUser(log, 20, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryLimited, UserType.NonSchedulable);
//Inventory manager
GenSeedUser(log, 40, AuthorizationRoles.InventoryFull | AuthorizationRoles.DispatchLimited, UserType.NonSchedulable);
//Inventory manager assistants
GenSeedUser(log, 20, AuthorizationRoles.InventoryLimited, UserType.NonSchedulable);
//accountant / bookkeeper
GenSeedUser(log, 20, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NonSchedulable);
//full on client users
GenSeedUser(log, 200, AuthorizationRoles.ClientFull, UserType.Client);
//limited client users
GenSeedUser(log, 50, AuthorizationRoles.ClientLimited, UserType.Client);
//PERF
watch.Stop();
LogStatus(JobId, LogJob, log, $"1,410 Users seeded in {watch.ElapsedMilliseconds} ms");
//20000 widgets
LogStatus(JobId, LogJob, log, $"Seeding 20,000 Widgets....");
watch = new Stopwatch();
watch.Start();
GenSeedWidget(log, 20000);
watch.Stop();
LogStatus(JobId, LogJob, log, $"20k Widgets seeded in {watch.ElapsedMilliseconds} ms");
#endregion genhuge
}
break;
}
LogStatus(JobId, LogJob, log, "Seeding completed successfully");
}
catch (Exception ex)
{
log.LogError(ex, "Seeder:SeedDatabase error during ops");
if (LogJob)
JobsBiz.LogJob(JobId, $"Seeder:SeedDatabase error during ops\r\n{ex.Message}");
throw ex;
}
finally
{
log.LogInformation($"Seeder: setting server state back to {wasServerState.ToString()}");
apiServerState.SetState(wasServerState, wasReason);
}
}
//Log the status and also job if it's run via job
private static void LogStatus(Guid JobId, bool LogJob, ILogger log, string msg)
{
log.LogInformation(msg);
if (LogJob)
JobsBiz.LogJob(JobId, msg);
}
public static long RUNNING_COUNT = 0;
public static string Uniquify(string s)
{
return s + " " + (++RUNNING_COUNT).ToString();
}
//////////////////////////////////////////////////////
//Seed test data for integration tests
//
public static void SeedKnownUsers(ILogger log)
{
try
{
//TEST USERS
//one of each role type
GenSeedUser(log, 1, AuthorizationRoles.BizAdminLimited, UserType.NonSchedulable, "BizAdminLimited", "BizAdminLimited");
GenSeedUser(log, 1, AuthorizationRoles.BizAdminFull, UserType.NonSchedulable, "BizAdminFull", "BizAdminFull");
GenSeedUser(log, 1, AuthorizationRoles.DispatchLimited, UserType.NonSchedulable, "DispatchLimited", "DispatchLimited");
GenSeedUser(log, 1, AuthorizationRoles.DispatchFull, UserType.NonSchedulable, "DispatchFull", "DispatchFull");
GenSeedUser(log, 1, AuthorizationRoles.InventoryLimited, UserType.NonSchedulable, "InventoryLimited", "InventoryLimited");
GenSeedUser(log, 1, AuthorizationRoles.InventoryFull, UserType.NonSchedulable, "InventoryFull", "InventoryFull");
GenSeedUser(log, 1, AuthorizationRoles.AccountingFull, UserType.NonSchedulable, "Accounting", "Accounting");
GenSeedUser(log, 1, AuthorizationRoles.TechLimited, UserType.Schedulable, "TechLimited", "TechLimited");
GenSeedUser(log, 1, AuthorizationRoles.TechFull, UserType.Schedulable, "TechFull", "TechFull");
GenSeedUser(log, 1, AuthorizationRoles.SubContractorLimited, UserType.Subcontractor, "SubContractorLimited", "SubContractorLimited");
GenSeedUser(log, 1, AuthorizationRoles.SubContractorFull, UserType.Subcontractor, "SubContractorFull", "SubContractorFull");
GenSeedUser(log, 1, AuthorizationRoles.ClientLimited, UserType.Client, "ClientLimited", "ClientLimited");
GenSeedUser(log, 1, AuthorizationRoles.ClientFull, UserType.Client, "ClientFull", "ClientFull");
GenSeedUser(log, 1, AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable, "OpsAdminLimited", "OpsAdminLimited");
GenSeedUser(log, 1, AuthorizationRoles.OpsAdminFull, UserType.NonSchedulable, "OpsAdminFull", "OpsAdminFull");
//PRIVACY TEST USER - this is used for a test to see if user info leaks into the logs
GenSeedUser(log, 1, AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable, "TEST_PRIVACY_USER_ACCOUNT", "TEST_PRIVACY_USER_ACCOUNT");
//TEST NOT ACTIVE - this is used for a test to see if inactive user can login
GenSeedUser(log, 1, AuthorizationRoles.OpsAdminLimited, UserType.NonSchedulable, false, "TEST_INACTIVE", "TEST_INACTIVE");
//Alternate locale users for each stock locale
GenSeedUser(log, 1, AuthorizationRoles.BizAdminFull, UserType.Administrator, true, "de", "de", LocaleBiz.LocaleNameToIdStatic("de"));
GenSeedUser(log, 1, AuthorizationRoles.BizAdminFull, UserType.Administrator, true, "es", "es", LocaleBiz.LocaleNameToIdStatic("es"));
GenSeedUser(log, 1, AuthorizationRoles.BizAdminFull, UserType.Administrator, true, "fr", "fr", LocaleBiz.LocaleNameToIdStatic("fr"));
}
catch
{
throw;
}
}
/// <summary>
/// Generate seed user with active=true
/// (override to save typing)
/// </summary>
/// <param name="log"></param>
/// <param name="count"></param>
/// <param name="roles"></param>
/// <param name="userType"></param>
/// <param name="login"></param>
/// <param name="password"></param>
public static void GenSeedUser(ILogger log, int count, AuthorizationRoles roles, UserType userType, string login, string password)
{
try
{
GenSeedUser(log, count, roles, userType, true, login, password);
}
catch
{
throw;
}
}
public static void GenSeedUser(ILogger log, int count, AuthorizationRoles roles, UserType userType, bool active = true, string login = null, string password = null, long localeId = 0)
{
UserBiz Biz = UserBiz.GetBizInternal(ServiceProviderProvider.DBContext);
//allow creation of not entirely ready users (missing client id or subcontractor vendor id etc)
Biz.SeedOrImportRelaxedRulesMode = true;
for (int x = 0; x < count; x++)
{
User u = new User();
u.Active = active;
u.OwnerId = 1;
var p = new Bogus.Person();
u.Name = Uniquify(p.FullName);
if (login != null)
{
u.Login = login;
u.Name += " - " + login;
}
else
u.Login = p.FirstName;
if (password != null)
u.Password = password;
else
u.Password = u.Login;
u.Roles = roles;
u.LocaleId = localeId == 0 ? ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID : localeId;
u.UserType = userType;
//TODO: After have USER and HEADOFFICE and VENDOR, if usertype is subcontractor or client or headoffice it needs to set a corresponding user's parent org record id to go with it
//Children and relations
u.UserOptions = new UserOptions(1);
u.UserOptions.EmailAddress = p.Email.Replace("gmail.com", "helloayanova.com").Replace("hotmail.com", "helloayanova.com").Replace("yahoo.com", "helloayanova.com");
var NewObject = Biz.Create(ServiceProviderProvider.DBContext, u);
if (NewObject == null)
{
log.LogError($"Seeder::GenSeedUser error creating user {u.Name}\r\n" + Biz.GetErrorsAsString());
throw new System.Exception("Seeder::GenSeedUser error creating user\r\n" + Biz.GetErrorsAsString());
}
}
}
//////////////////////////////////////////////////////
//Seed widget for testing
//
public static void GenSeedWidget(ILogger log, int count)
{
WidgetBiz Biz = WidgetBiz.GetBizInternal(ServiceProviderProvider.DBContext);
var f = new Bogus.Faker();
for (int x = 0; x < count; x++)
{
Widget o = new Widget();
o.Name = Uniquify(f.Commerce.ProductName());
o.Active = true;
o.StartDate = f.Date.Between(DateTime.Now, DateTime.Now.AddMinutes(60));
o.EndDate = f.Date.Between(DateTime.Now.AddMinutes(90), DateTime.Now.AddHours(5));
o.DollarAmount = Convert.ToDecimal(f.Commerce.Price());
o.OwnerId = 1;
//this is nonsense but just to test an enum
o.Roles = AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited | AuthorizationRoles.OpsAdminLimited;
o.Notes = f.Lorem.Paragraph();
var NewObject = Biz.Create(ServiceProviderProvider.DBContext, o);
if (NewObject == null)
{
log.LogError($"Seeder::GenSeedWidget error creating widget {o.Name}\r\n" + Biz.GetErrorsAsString());
throw new System.Exception("Seeder::GenSeedWidget error creating widget\r\n" + Biz.GetErrorsAsString());
}
}
}
}//eoc
}//eons