Files
raven/server/AyaNova/util/Seeder.cs
2020-07-01 18:14:57 +00:00

810 lines
40 KiB
C#

using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using AyaNova.Models;
using AyaNova.Biz;
using Microsoft.Extensions.Logging;
using Bogus;
using AyaNova.Api.ControllerHelpers;
using System.Diagnostics;
namespace AyaNova.Util
{
public class Seeder
{
public int SeededUserCount = 0;
public Faker Fake;
public Seeder()
{
Fake = new Faker();
}
public static class Level
{
public enum SeedLevel { NotValid, Small, Medium, Large, Huge };
public static SeedLevel StringToSeedLevel(string size)
{
switch (size.ToLowerInvariant())
{
case "small":
return SeedLevel.Small;
case "medium":
return SeedLevel.Medium;
case "large":
return SeedLevel.Large;
case "huge":
return SeedLevel.Huge;
default:
return SeedLevel.NotValid;
}
}
}
//////////////////////////////////////////////////////
//Seed database for trial and testing purposes
//
public async Task SeedDatabaseAsync(Level.SeedLevel slevel, Decimal timeZoneOffset)
{
await SeedDatabaseAsync(slevel, Guid.Empty, timeZoneOffset);
}
public async Task SeedDatabaseAsync(Level.SeedLevel slevel, Guid JobId, Decimal timeZoneOffset)
{
bool LogJob = JobId != Guid.Empty;
SeededUserCount = 0;
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;
try
{
var StatusMsg = $"Seeding data, level {slevel.ToString()}, time zone offset {timeZoneOffset.ToString()}";
await LogStatusAsync(JobId, LogJob, log, StatusMsg);
//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: {AyaNova.Core.License.LicenseInfoLogFormat}";
await LogStatusAsync(JobId, LogJob, log, msg);
throw new System.NotSupportedException(msg);
}
//validate timezone offset
if (timeZoneOffset > 14 || timeZoneOffset < (-12))
{
var msg = $"Time zone offset \"{timeZoneOffset.ToString()}\" is not valid";
await LogStatusAsync(JobId, LogJob, log, msg);
throw new System.NotSupportedException(msg);
}
apiServerState.SetOpsOnly("Seeding database");
//Erase all the data except for the license, schema and the SuperUser
await DbUtil.EmptyBizDataFromDatabaseForSeedingOrImportingAsync(log);
//Event log erase and seeding
using (var ct = ServiceProviderProvider.DBContext)
{
await EventLogProcessor.LogEventToDatabaseAsync(new Event(1, 0, AyaType.Global, AyaEvent.EraseAllData, "(seeding preparation)"), ct);
await EventLogProcessor.LogEventToDatabaseAsync(new Event(1, 0, AyaType.Global, AyaEvent.SeedDatabase, StatusMsg), ct);
}
apiServerState.SetOpsOnly("Seeding database with sample data");
//WIDGET sample form customization
{
var fc = new FormCustom()
{
FormKey = AyaType.Widget.ToString(),
Template = @"[
{
""fld"": ""Notes"",
""required"": true
},
{
""fld"": ""WidgetCustom1"",
""required"": false,
""type"": 1
},
{
""fld"": ""WidgetCustom2"",
""required"": true,
""type"": 4
},
{
""fld"": ""WidgetCustom3"",
""required"": false,
""type"": 5
},
{
""fld"": ""WidgetCustom4"",
""required"": false,
""type"": 6
},
{
""fld"": ""WidgetCustom5"",
""required"": false,
""type"": 8
},
{
""fld"": ""WidgetCustom6"",
""required"": false,
""type"": 2
},
{
""fld"": ""WidgetCustom7"",
""required"": false,
""type"": 3
}
]"
};
//Create and save to db
using (var ct = ServiceProviderProvider.DBContext)
await FormCustomBiz.GetBiz(ct).CreateAsync(fc);
}
//Create a couple of DataListView's for development and testing
{
var dlv = new DataListView()
{
Name = "Name starts with generic",
UserId = 1,
ListKey = "TestWidgetDataList",
Public = true,
ListView = @"[{""fld"": ""widgetname"",""filter"": {""any"":false,""items"": [{""op"": ""%-"",""value"": ""Generic""}]}}]"
};
//Create and save to db
using (var ct = ServiceProviderProvider.DBContext)
await DataListViewBiz.GetBiz(ct).CreateAsync(dlv);
dlv = new DataListView()
{
Name = "Awesome (lots of fields)",
UserId = 1,
ListKey = "TestWidgetDataList",
Public = true,
ListView = @"[{""fld"": ""widgetname"",""filter"": {""any"":false,""items"": [{""op"": ""%-"",""value"": ""Awesome""}]}},{""fld"":""widgetserial""},{""fld"":""widgetdollaramount""},{""fld"":""widgetusertype""},{""fld"":""widgetstartdate""},{""fld"":""widgetactive""},{""fld"":""username""},{""fld"":""widgettags""},{""fld"":""widgetcustom1""},{""fld"":""widgetcustom2""}]"
};
//Create and save to db
using (var ct = ServiceProviderProvider.DBContext)
await DataListViewBiz.GetBiz(ct).CreateAsync(dlv);
}
//Seed special test data for integration testing
//log.LogInformation("Seeding known users");
await SeedKnownUsersAsync(log);
//log.LogInformation("Seeding all other data");
switch (slevel)
{
case Level.SeedLevel.Small:
{
#region GenSmall
//This is for a busy but one man shop with a single office person handling stuff back at the shop
//PERF
await LogStatusAsync(JobId, LogJob, log, $"Seeding SMALL number of user(s)....");
var watch = new Stopwatch();
watch.Start();
//Generate owner and lead tech
await GenSeedUserAsync(log, 1, AuthorizationRoles.BizAdminFull | AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryFull | AuthorizationRoles.OpsAdminFull, UserType.Service);
//Generate one office person / secretary
await GenSeedUserAsync(log, 1, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryFull | AuthorizationRoles.AccountingFull, UserType.NotService);
//PERF
watch.Stop();
await LogStatusAsync(JobId, LogJob, log, $"{SeededUserCount} Users seeded in {watch.ElapsedMilliseconds} ms");
//100 widgets
watch = new Stopwatch();
watch.Start();
await GenSeedWidgetAsync(log, 100);
//PERF
watch.Stop();
await LogStatusAsync(JobId, LogJob, log, $"100 Widgets seeded in {watch.ElapsedMilliseconds} ms");
#endregion gensmall
}
break;
case Level.SeedLevel.Medium:
{
#region GenMedium
//This is for a typical AyaNova medium busy shop
//has one location, many techs and full staff for each department
//PERF
await LogStatusAsync(JobId, LogJob, log, $"Seeding MEDIUM number of user(s)....");
var watch = new Stopwatch();
watch.Start();
//One IT administrator, can change ops but nothing else
await GenSeedUserAsync(log, 1, AuthorizationRoles.OpsAdminFull, UserType.NotService);
//One business administrator, can view ops issues
await GenSeedUserAsync(log, 1, AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminLimited, UserType.NotService);
//One owner who doesn't control anything but views stuff
await GenSeedUserAsync(log, 1, AuthorizationRoles.BizAdminLimited | AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited | AuthorizationRoles.OpsAdminLimited | AuthorizationRoles.SalesLimited, UserType.NotService);
//20 techs
await GenSeedUserAsync(log, 20, AuthorizationRoles.TechFull | AuthorizationRoles.DispatchLimited, UserType.Service);
//2 subcontractors
await GenSeedUserAsync(log, 2, AuthorizationRoles.SubContractorFull, UserType.ServiceContractor);
//3 generic office people people
await GenSeedUserAsync(log, 3, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited, UserType.NotService);
//2 Full sales people
await GenSeedUserAsync(log, 2, AuthorizationRoles.SalesFull, UserType.NotService);
//1 dispatch manager
await GenSeedUserAsync(log, 1, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryLimited, UserType.NotService);
//1 Inventory manager
await GenSeedUserAsync(log, 1, AuthorizationRoles.InventoryFull | AuthorizationRoles.DispatchLimited, UserType.NotService);
//1 accountant / bookkeeper
await GenSeedUserAsync(log, 1, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NotService);
//10 full on customer users
await GenSeedUserAsync(log, 10, AuthorizationRoles.CustomerLimited, UserType.Customer);
//10 limited customer users
await GenSeedUserAsync(log, 10, AuthorizationRoles.CustomerLimited, UserType.Customer);
//PERF
watch.Stop();
await LogStatusAsync(JobId, LogJob, log, $"{SeededUserCount} Users seeded in {watch.ElapsedMilliseconds} ms");
//500 widgets
await LogStatusAsync(JobId, LogJob, log, $"Seeding 500 Widgets....");
watch = new Stopwatch();
watch.Start();
//await GenSeedWidgetAsync(log, 500);
await GenSeedWidgetAsync(log, 500);
//PERF
watch.Stop();
await LogStatusAsync(JobId, LogJob, log, $"500 Widgets seeded in {watch.ElapsedMilliseconds} ms");
#endregion genmedium
}
break;
case Level.SeedLevel.Large:
{
#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
await LogStatusAsync(JobId, LogJob, log, $"Seeding LARGE number of user(s)....");
var watch = new Stopwatch();
watch.Start();
//IT administrator, can change ops but nothing else
await GenSeedUserAsync(log, 2, AuthorizationRoles.OpsAdminFull, UserType.NotService);
//business administrator, can view ops issues
await GenSeedUserAsync(log, 2, AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminLimited, UserType.NotService);
//owner / upper management who doesn't control anything but views stuff
await GenSeedUserAsync(log, 5, AuthorizationRoles.BizAdminLimited | AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited | AuthorizationRoles.OpsAdminLimited, UserType.NotService);
//100 techs
await GenSeedUserAsync(log, 100, AuthorizationRoles.TechFull | AuthorizationRoles.DispatchLimited, UserType.Service);
//limited techs
await GenSeedUserAsync(log, 50, AuthorizationRoles.TechLimited | AuthorizationRoles.DispatchLimited, UserType.Service);
//20 subcontractors
await GenSeedUserAsync(log, 20, AuthorizationRoles.SubContractorFull, UserType.ServiceContractor);
//10 limited subcontractors
await GenSeedUserAsync(log, 10, AuthorizationRoles.SubContractorLimited, UserType.ServiceContractor);
//30 generic office people people
await GenSeedUserAsync(log, 30, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited, UserType.NotService);
//10 Full sales people
await GenSeedUserAsync(log, 10, AuthorizationRoles.SalesFull, UserType.NotService);
//5 Limited sales people
await GenSeedUserAsync(log, 5, AuthorizationRoles.SalesLimited, UserType.NotService);
//5 dispatch manager
await GenSeedUserAsync(log, 5, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryLimited, UserType.NotService);
//5 Inventory manager
await GenSeedUserAsync(log, 5, AuthorizationRoles.InventoryFull | AuthorizationRoles.DispatchLimited, UserType.NotService);
//10 Inventory manager assistants
await GenSeedUserAsync(log, 5, AuthorizationRoles.InventoryLimited, UserType.NotService);
//5 accountant / bookkeeper
await GenSeedUserAsync(log, 5, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NotService);
//100 full on customer users
await GenSeedUserAsync(log, 20, AuthorizationRoles.CustomerFull, UserType.Customer);
//100 limited customer users
await GenSeedUserAsync(log, 20, AuthorizationRoles.CustomerLimited, UserType.Customer);
//PERF
watch.Stop();
await LogStatusAsync(JobId, LogJob, log, $"{SeededUserCount} Users seeded in {watch.ElapsedMilliseconds} ms");
//5000 widgets
await LogStatusAsync(JobId, LogJob, log, $"Seeding 5,000 Widgets....");
watch = new Stopwatch();
watch.Start();
//await GenSeedWidgetAsync(log, 5000);
await GenSeedWidgetAsync(log, 5000);
//PERF
watch.Stop();
await LogStatusAsync(JobId, LogJob, log, $"5k Widgets seeded in {watch.ElapsedMilliseconds} ms");
#endregion genlarge
}
break;
case Level.SeedLevel.Huge:
{
#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
await LogStatusAsync(JobId, LogJob, log, $"Seeding HUGE number of user(s)....");
var watch = new Stopwatch();
watch.Start();
//IT administrator, can change ops but nothing else
await GenSeedUserAsync(log, 10, AuthorizationRoles.OpsAdminFull, UserType.NotService);
//business administrator, can view ops issues
await GenSeedUserAsync(log, 10, AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminLimited, UserType.NotService);
//owner / upper management who doesn't control anything but views stuff
await GenSeedUserAsync(log, 20, AuthorizationRoles.BizAdminLimited | AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited | AuthorizationRoles.OpsAdminLimited, UserType.NotService);
//regular techs
await GenSeedUserAsync(log, 500, AuthorizationRoles.TechFull | AuthorizationRoles.DispatchLimited, UserType.Service);
//limited techs
await GenSeedUserAsync(log, 200, AuthorizationRoles.TechLimited | AuthorizationRoles.DispatchLimited, UserType.Service);
//subcontractors
await GenSeedUserAsync(log, 80, AuthorizationRoles.SubContractorFull, UserType.ServiceContractor);
//limited subcontractors
await GenSeedUserAsync(log, 40, AuthorizationRoles.SubContractorLimited, UserType.ServiceContractor);
//generic office people people
await GenSeedUserAsync(log, 200, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited, UserType.NotService);
//20 Full sales people
await GenSeedUserAsync(log, 20, AuthorizationRoles.SalesFull, UserType.NotService);
//10 Limited sales people
await GenSeedUserAsync(log, 10, AuthorizationRoles.SalesLimited, UserType.NotService);
//dispatch manager
await GenSeedUserAsync(log, 20, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryLimited, UserType.NotService);
//Inventory manager
await GenSeedUserAsync(log, 40, AuthorizationRoles.InventoryFull | AuthorizationRoles.DispatchLimited, UserType.NotService);
//Inventory manager assistants
await GenSeedUserAsync(log, 20, AuthorizationRoles.InventoryLimited, UserType.NotService);
//accountant / bookkeeper
await GenSeedUserAsync(log, 20, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NotService);
//full on customer users
await GenSeedUserAsync(log, 200, AuthorizationRoles.CustomerFull, UserType.Customer);
//limited customer users
await GenSeedUserAsync(log, 50, AuthorizationRoles.CustomerLimited, UserType.Customer);
//PERF
watch.Stop();
await LogStatusAsync(JobId, LogJob, log, $"{SeededUserCount} Users seeded in {watch.ElapsedMilliseconds} ms");
//20000 widgets
await LogStatusAsync(JobId, LogJob, log, $"Seeding 20,000 Widgets....");
watch = new Stopwatch();
watch.Start();
//await GenSeedWidgetAsync(log, 20000);
await GenSeedWidgetAsync(log, 20000);
watch.Stop();
await LogStatusAsync(JobId, LogJob, log, $"20k Widgets seeded in {watch.ElapsedMilliseconds} ms");
#endregion genhuge
}
break;
}
await LogStatusAsync(JobId, LogJob, log, "Seeding completed successfully");
}
catch (Exception ex)
{
log.LogError(ex, "Seeder:SeedDatabase error during ops");
if (LogJob)
await JobsBiz.LogJobAsync(JobId, $"Seeder:SeedDatabase error during ops\r\n{ex.Message}");
throw ex;
}
finally
{
//TODO: fully async: watch the job and don't turn the state back until the job is done?
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 async Task LogStatusAsync(Guid JobId, bool LogJob, ILogger log, string msg)
{
log.LogInformation(msg);
if (LogJob)
await JobsBiz.LogJobAsync(JobId, msg);
}
public long RUNNING_COUNT = 0;
public string Uniquify(string s)
{
return s + " " + (++RUNNING_COUNT).ToString();
}
private string[] TagSet = new[] { "red", "orange", "yellow", "green", "blue", "indigo", "violet", "brown", "black", "white", "silver", "gold", "fuchsia", "jade", "mauve", "purple", "quince", "xanthic", "zebra", "zone0", "zone1", "zone2", "zone3", "zone4", "zone5", "zone6", "zone7", "zone8", "zone9" };
private List<string> RandomTags()
{
var t = Fake.PickRandom(TagSet, Fake.Random.Int(1, 5));//pick up to 5 tags to apply
return new List<string>(t);
}
//////////////////////////////////////////////////////
//Seed test data for integration tests
//
public async Task SeedKnownUsersAsync(ILogger log)
{
try
{
var KnownUserTags = new List<string>();
KnownUserTags.Add("known-user");
KnownUserTags.Add("test-role-user");
//TEST USERS
//one of each role type
await GenSeedUserAsync(log, 1, AuthorizationRoles.BizAdminLimited, UserType.NotService, "BizAdminLimited", "BizAdminLimited", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.BizAdminFull, UserType.NotService, "BizAdminFull", "BizAdminFull", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.DispatchLimited, UserType.NotService, "DispatchLimited", "DispatchLimited", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.DispatchFull, UserType.NotService, "DispatchFull", "DispatchFull", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.InventoryLimited, UserType.NotService, "InventoryLimited", "InventoryLimited", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.InventoryFull, UserType.NotService, "InventoryFull", "InventoryFull", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.AccountingFull, UserType.NotService, "Accounting", "Accounting", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.TechLimited, UserType.Service, "TechLimited", "TechLimited", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.TechFull, UserType.Service, "TechFull", "TechFull", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.SalesLimited, UserType.NotService, "SalesLimited", "SalesLimited", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.SalesFull, UserType.NotService, "SalesFull", "SalesFull", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.SubContractorLimited, UserType.ServiceContractor, "SubContractorLimited", "SubContractorLimited", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.SubContractorFull, UserType.ServiceContractor, "SubContractorFull", "SubContractorFull", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.CustomerLimited, UserType.Customer, "CustomerLimited", "CustomerLimited", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.CustomerFull, UserType.Customer, "CustomerFull", "CustomerFull", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.CustomerFull, UserType.HeadOffice, "HeadOffice", "HeadOffice", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.OpsAdminLimited, UserType.NotService, "OpsAdminLimited", "OpsAdminLimited", KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.OpsAdminFull, UserType.NotService, "OpsAdminFull", "OpsAdminFull", KnownUserTags);
//PRIVACY TEST USER - this is used for a test to see if user info leaks into the logs
await GenSeedUserAsync(log, 1, AuthorizationRoles.OpsAdminLimited, UserType.NotService, "TEST_PRIVACY_USER_ACCOUNT", "TEST_PRIVACY_USER_ACCOUNT", KnownUserTags);
//TEST NOT ACTIVE - this is used for a test to see if inactive user can login
await GenSeedUserAsync(log, 1, AuthorizationRoles.OpsAdminLimited, UserType.NotService, false, "TEST_INACTIVE", "TEST_INACTIVE", 0, KnownUserTags);
//Alternate translation users for each stock translation
await GenSeedUserAsync(log, 1, AuthorizationRoles.All, UserType.Administrator, true, "de", "de", await TranslationBiz.TranslationNameToIdStaticAsync("de"), KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.All, UserType.Administrator, true, "es", "es", await TranslationBiz.TranslationNameToIdStaticAsync("es"), KnownUserTags);
await GenSeedUserAsync(log, 1, AuthorizationRoles.All, UserType.Administrator, true, "fr", "fr", await TranslationBiz.TranslationNameToIdStaticAsync("fr"), KnownUserTags);
}
catch
{
throw;
}
}
/// <summary>
/// Generate seed user with active=true
/// (override to save typing)
/// </summary>
public async Task GenSeedUserAsync(ILogger log, int count, AuthorizationRoles roles, UserType userType, string login, string password, List<string> tags = null)
{
try
{
await GenSeedUserAsync(log, count, roles, userType, true, login, password, 0, tags);
}
catch
{
throw;
}
}
public async Task GenSeedUserAsync(ILogger log, int count, AuthorizationRoles roles, UserType userType,
bool active = true, string login = null, string password = null, long translationId = 0, List<string> tags = null)
{
if (translationId == 0)
translationId = ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID;
for (int x = 0; x < count; x++)
{
User u = new User();
u.Active = active;
var p = new Bogus.Person();
u.Name = Uniquify(p.FullName);
if (login != null)
{
u.Login = login;
u.Name += " - " + login;
}
else
u.Login = u.Name;//must be unique, name is unique
if (password != null)
u.Password = password;
else
u.Password = u.Login;
u.Roles = roles;
u.UserType = userType;
u.EmployeeNumber = "A-" + (454 + SeededUserCount).ToString() + "-Y";
u.Notes = Fake.Lorem.Sentence(null, 5);//Fake.Lorem.Paragraph(2);
//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
//use provided tags or generate them
if (tags == null)
u.Tags = RandomTags();
else
u.Tags = tags;
//Children and relations
u.UserOptions = new UserOptions();
u.UserOptions.TranslationId = translationId;
u.UserOptions.EmailAddress = p.Email.Replace("gmail.com", "helloayanova.com").Replace("hotmail.com", "helloayanova.com").Replace("yahoo.com", "helloayanova.com");
u.UserOptions.Hour12 = true;
u.UserOptions.CurrencyName = "USD";
u.UserOptions.UiColor = Fake.Internet.Color();
// u.Wiki = @"
// # Markdown quick reference for Wiki pages
// ***
// ***
// <br>
// ## Markdown and Wiki documents
// Wiki's are formatted using **[Markdown](https://en.wikipedia.org/wiki/Markdown)** a plain text formatting language.
// This document is a quick reference guide and at the bottom is a link to a more comprehensive guide online.
// You can also use the formatting toolbar above to perform the same tasks.
// # Headings
// # Heading 1st level
// ## Heading 2nd level
// ### Heading 3rd level
// #### Heading 4th level
// ##### Heading 5th level
// ###### Heading 6th level
// ***
// # Emphasis text styles
// *Italic*
// **Bold**
// ~~Strike-through~~
// ***Bold And Italic***
// # Quote blocks
// > ""Morbi eget dapibus felis. Vivamus venenatis porttitor tortor sit amet rutrum.
// Pellentesque aliquet quam enim, eu volutpat urna rutrum a. Nam vehicula nunc
// >
// > mauris, a ultricies libero efficitur sed. *Class aptent* taciti sociosqu ad
// litora torquent per conubia nostra, per inceptos himenaeos. Sed molestie
// imperdiet consectetur.""
// # Lists
// ### Unordered list
// * List
// * List
// * List
// ### Ordered list
// 1. One
// 2. Two
// 3. Three
// ### Auto number ordered list
// Ordered lists don't need the numbers to be in order, just that they start with 1:
// 1. Item
// 1. another item
// 1. more item
// ### Nested lists
// * First
// * subitem One
// * subitem Two
// * Second
// 1. sub one
// 2. sub two
// # Blank lines
// You can force extra blank lines by entering `<br>` here are two blank ...
// <br>
// <br>
// ...lines.
// # Horizontal rules
// ***
// # Blocks
// `Inline block` with backticks
// ```
// Multi-line block
// print '3 backticks or'
// print 'indent 4 spaces'
// ```
// # Task lists
// - [ ] task one
// - [x] task two (completed)
// # TABLES
// | First | Last | Year |
// | -------- | -------- | -------- |
// | John | Doe | 2000 |
// | Mary | Smith | 2001 |
// | T. | Persson | 2010 |
// # Hyperlinks
// Inline text link and and optional tooltip:
// Link to [our website](https://ayanova.com ""Hover text tooltip"") example
// If you don't need an inline link you can simply enter it in angle brackets:
// <https://ayanova.com>
// Even email links work:
// <support@ayanova.com>
// <br>
// You can also use emphasis characters with links:
// Link to **[our website](https://ayanova.com)** example
// # Image
// This is how you insert an image into a wiki
// ![Image](https://www.ayanova.com/images/AyaNovaIcon256.png)
// # Emojis
// As with all areas of AyaNova where you can enter text, you can also use emoji characters:
// # 😀⚽🏒🍕🚗☀❤😎
// <br>
// # Markdown guide
// A more detailed markdown guide is available here:
// <https://www.markdownguide.org/>
// ***
// ";
//this seems wrong to get a new context inside a loop but in testing is actually faster!?
using (AyContext ct = ServiceProviderProvider.DBContext)
{
UserBiz Biz = UserBiz.GetBiz(ct);
//allow creation of not entirely ready users (missing client id or subcontractor vendor id etc)
Biz.SeedOrImportRelaxedRulesMode = true;
var NewObject = await Biz.CreateAsync(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());
}
}
}
SeededUserCount += count;
}
//////////////////////////////////////////////////////
//Seed widget for testing
//
public async Task GenSeedWidgetAsync(ILogger log, int count)
{
//this is 4 times slower than doing it inside the loop below
//seems counterintuitive but maybe it's to do with the db context not being refreshed?
//RANDOM ROLES
Array values = Enum.GetValues(typeof(UserType));
Random random = new Random();
DateTime seedStartWindow = DateTime.Now.AddYears(-1);
DateTime seedEndWindow = DateTime.Now.AddYears(1);
for (int x = 0; x < count; x++)
{
Widget o = new Widget();
o.Name = Uniquify(Fake.Commerce.ProductName());
o.Active = true;
DateTime dtSeed = Fake.Date.Between(seedStartWindow, seedEndWindow).ToUniversalTime();
o.StartDate = dtSeed;
o.EndDate = dtSeed.AddMinutes(60).ToUniversalTime();
o.DollarAmount = Convert.ToDecimal(Fake.Commerce.Price());
//Random but valid enum
UserType randomUserType = (UserType)values.GetValue(random.Next(values.Length));
o.UserType = randomUserType;
o.Notes = Fake.Lorem.Sentence(null, 5);
o.Tags = RandomTags();
o.UserId = Fake.Random.Int(1, SeededUserCount);
//RANDOM CUSTOM FIELD DATA
var c1 = DateUtil.UniversalISO8661Format(Fake.Date.Between(DateTime.Now.AddYears(-1), DateTime.Now.AddYears(1)));
var c2 = Fake.Lorem.Sentence(null, 5);
var c3 = Fake.Random.Int(1, 99999999);
var c4 = Fake.Random.Bool().ToString().ToLowerInvariant();
var c5 = Fake.Random.Decimal();
o.CustomFields = $@"{{c1:""{c1}"",c2:""{c2}"",c3:{c3},c4:{c4},c5:{c5}}}";
//This seems wrong to do in a loop but is 4 times faster this way ?!?
using (AyContext ct = ServiceProviderProvider.DBContext)
{
WidgetBiz biz = WidgetBiz.GetBiz(ct);
var NewObject = await biz.CreateAsync(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