923 lines
42 KiB
C#
923 lines
42 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;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
|
|
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");
|
|
ServerBootConfig.SEEDING = true;
|
|
|
|
//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 SeedKnownObjectsAsync(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 sample data....");
|
|
var watch = new Stopwatch();
|
|
watch.Start();
|
|
|
|
//USERS
|
|
//Generate owner and lead tech
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.BizAdminFull | AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryFull | AuthorizationRoles.OpsAdminFull, UserType.Service);
|
|
|
|
//Generate one office person / secretary
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryFull | AuthorizationRoles.AccountingFull, UserType.NotService);
|
|
|
|
//WIDGET
|
|
await SeedWidgetAsync(log, 100);
|
|
|
|
//CUSTOMERS
|
|
await SeedCustomerAsync(log, 100);
|
|
|
|
//HEAD-OFFICES
|
|
await SeedHeadOfficeAsync(log, 10);
|
|
|
|
//VENDORS
|
|
await SeedVendorAsync(log, 25);
|
|
|
|
|
|
//PERF
|
|
watch.Stop();
|
|
await LogStatusAsync(JobId, LogJob, log, $"Small level sample data 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 sample data....");
|
|
var watch = new Stopwatch();
|
|
watch.Start();
|
|
|
|
//USERS
|
|
//One IT administrator, can change ops but nothing else
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.OpsAdminFull, UserType.NotService);
|
|
|
|
//One business administrator, can view ops issues
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminLimited, UserType.NotService);
|
|
|
|
//One owner who doesn't control anything but views stuff
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.BizAdminLimited | AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited | AuthorizationRoles.OpsAdminLimited | AuthorizationRoles.SalesLimited, UserType.NotService);
|
|
|
|
//20 techs
|
|
await SeedUserAsync(log, 20, AuthorizationRoles.TechFull | AuthorizationRoles.DispatchLimited, UserType.Service);
|
|
|
|
//2 subcontractors
|
|
await SeedUserAsync(log, 2, AuthorizationRoles.SubContractorFull, UserType.ServiceContractor);
|
|
|
|
//3 generic office people people
|
|
await SeedUserAsync(log, 3, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited, UserType.NotService);
|
|
|
|
//2 Full sales people
|
|
await SeedUserAsync(log, 2, AuthorizationRoles.SalesFull, UserType.NotService);
|
|
|
|
//1 dispatch manager
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryLimited, UserType.NotService);
|
|
|
|
//1 Inventory manager
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.InventoryFull | AuthorizationRoles.DispatchLimited, UserType.NotService);
|
|
|
|
//1 accountant / bookkeeper
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NotService);
|
|
|
|
|
|
//WIDGETS
|
|
await SeedWidgetAsync(log, 100);
|
|
|
|
//CUSTOMERS
|
|
await SeedCustomerAsync(log, 500);
|
|
|
|
//HEAD-OFFICES
|
|
await SeedHeadOfficeAsync(log, 20);
|
|
|
|
//VENDORS
|
|
await SeedVendorAsync(log, 50);
|
|
|
|
//PERF
|
|
watch.Stop();
|
|
await LogStatusAsync(JobId, LogJob, log, $"MEDIUM level sample data 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 sample data....");
|
|
var watch = new Stopwatch();
|
|
watch.Start();
|
|
|
|
|
|
//USERS
|
|
//IT administrator, can change ops but nothing else
|
|
await SeedUserAsync(log, 2, AuthorizationRoles.OpsAdminFull, UserType.NotService);
|
|
|
|
//business administrator, can view ops issues
|
|
await SeedUserAsync(log, 2, AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminLimited, UserType.NotService);
|
|
|
|
//owner / upper management who doesn't control anything but views stuff
|
|
await SeedUserAsync(log, 5, AuthorizationRoles.BizAdminLimited | AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited | AuthorizationRoles.OpsAdminLimited, UserType.NotService);
|
|
|
|
//100 techs
|
|
await SeedUserAsync(log, 100, AuthorizationRoles.TechFull | AuthorizationRoles.DispatchLimited, UserType.Service);
|
|
|
|
//limited techs
|
|
await SeedUserAsync(log, 50, AuthorizationRoles.TechLimited | AuthorizationRoles.DispatchLimited, UserType.Service);
|
|
|
|
//20 subcontractors
|
|
await SeedUserAsync(log, 20, AuthorizationRoles.SubContractorFull, UserType.ServiceContractor);
|
|
|
|
//10 limited subcontractors
|
|
await SeedUserAsync(log, 10, AuthorizationRoles.SubContractorLimited, UserType.ServiceContractor);
|
|
|
|
//30 generic office people people
|
|
await SeedUserAsync(log, 30, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited, UserType.NotService);
|
|
|
|
//10 Full sales people
|
|
await SeedUserAsync(log, 10, AuthorizationRoles.SalesFull, UserType.NotService);
|
|
|
|
//5 Limited sales people
|
|
await SeedUserAsync(log, 5, AuthorizationRoles.SalesLimited, UserType.NotService);
|
|
|
|
//5 dispatch manager
|
|
await SeedUserAsync(log, 5, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryLimited, UserType.NotService);
|
|
|
|
//5 Inventory manager
|
|
await SeedUserAsync(log, 5, AuthorizationRoles.InventoryFull | AuthorizationRoles.DispatchLimited, UserType.NotService);
|
|
|
|
//10 Inventory manager assistants
|
|
await SeedUserAsync(log, 5, AuthorizationRoles.InventoryLimited, UserType.NotService);
|
|
|
|
//5 accountant / bookkeeper
|
|
await SeedUserAsync(log, 5, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NotService);
|
|
|
|
|
|
|
|
|
|
//WIDGETS
|
|
await SeedWidgetAsync(log, 100);
|
|
|
|
//CUSTOMERS
|
|
await SeedCustomerAsync(log, 5000);
|
|
|
|
//HEAD-OFFICES
|
|
await SeedHeadOfficeAsync(log, 30);
|
|
|
|
//VENDORS
|
|
await SeedVendorAsync(log, 75);
|
|
|
|
//PERF
|
|
watch.Stop();
|
|
await LogStatusAsync(JobId, LogJob, log, $"LARGE level sample data 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 sample data....");
|
|
var watch = new Stopwatch();
|
|
watch.Start();
|
|
|
|
|
|
//USERS
|
|
//IT administrator, can change ops but nothing else
|
|
await SeedUserAsync(log, 10, AuthorizationRoles.OpsAdminFull, UserType.NotService);
|
|
|
|
//business administrator, can view ops issues
|
|
await SeedUserAsync(log, 10, AuthorizationRoles.BizAdminFull | AuthorizationRoles.OpsAdminLimited, UserType.NotService);
|
|
|
|
//owner / upper management who doesn't control anything but views stuff
|
|
await SeedUserAsync(log, 20, AuthorizationRoles.BizAdminLimited | AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited | AuthorizationRoles.OpsAdminLimited, UserType.NotService);
|
|
|
|
//regular techs
|
|
await SeedUserAsync(log, 500, AuthorizationRoles.TechFull | AuthorizationRoles.DispatchLimited, UserType.Service);
|
|
|
|
//limited techs
|
|
await SeedUserAsync(log, 200, AuthorizationRoles.TechLimited | AuthorizationRoles.DispatchLimited, UserType.Service);
|
|
|
|
//subcontractors
|
|
await SeedUserAsync(log, 80, AuthorizationRoles.SubContractorFull, UserType.ServiceContractor);
|
|
|
|
//limited subcontractors
|
|
await SeedUserAsync(log, 40, AuthorizationRoles.SubContractorLimited, UserType.ServiceContractor);
|
|
|
|
//generic office people people
|
|
await SeedUserAsync(log, 200, AuthorizationRoles.DispatchLimited | AuthorizationRoles.InventoryLimited, UserType.NotService);
|
|
|
|
//20 Full sales people
|
|
await SeedUserAsync(log, 20, AuthorizationRoles.SalesFull, UserType.NotService);
|
|
|
|
//10 Limited sales people
|
|
await SeedUserAsync(log, 10, AuthorizationRoles.SalesLimited, UserType.NotService);
|
|
|
|
//dispatch manager
|
|
await SeedUserAsync(log, 20, AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryLimited, UserType.NotService);
|
|
|
|
//Inventory manager
|
|
await SeedUserAsync(log, 40, AuthorizationRoles.InventoryFull | AuthorizationRoles.DispatchLimited, UserType.NotService);
|
|
|
|
//Inventory manager assistants
|
|
await SeedUserAsync(log, 20, AuthorizationRoles.InventoryLimited, UserType.NotService);
|
|
|
|
//accountant / bookkeeper
|
|
await SeedUserAsync(log, 20, AuthorizationRoles.AccountingFull | AuthorizationRoles.BizAdminLimited, UserType.NotService);
|
|
|
|
|
|
|
|
|
|
//WIDGETS
|
|
await SeedWidgetAsync(log, 100);
|
|
|
|
//CUSTOMERS
|
|
await SeedCustomerAsync(log, 20000);
|
|
|
|
//HEAD-OFFICES
|
|
await SeedHeadOfficeAsync(log, 40);
|
|
|
|
//VENDORS
|
|
await SeedVendorAsync(log, 100);
|
|
|
|
//PERF
|
|
watch.Stop();
|
|
await LogStatusAsync(JobId, LogJob, log, $"HUGE level sample data seeded in {watch.ElapsedMilliseconds} ms");
|
|
#endregion genhuge
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
//Seed logo files
|
|
var LogoFilesPath = System.IO.Path.Combine(ServerBootConfig.AYANOVA_CONTENT_ROOT_PATH, "resource", "rpt", "stock-report-templates");
|
|
if (System.IO.Directory.Exists(LogoFilesPath))
|
|
{
|
|
using (var ct = ServiceProviderProvider.DBContext)
|
|
{
|
|
var logo = await ct.Logo.FirstOrDefaultAsync();
|
|
if (logo == null)
|
|
{
|
|
logo = new Logo();
|
|
ct.Logo.Add(logo);
|
|
await ct.SaveChangesAsync();
|
|
}
|
|
logo.Small = System.IO.File.ReadAllBytes(System.IO.Path.Combine(LogoFilesPath, "150x50.png"));
|
|
logo.SmallType = "image/png";
|
|
|
|
logo.Medium = System.IO.File.ReadAllBytes(System.IO.Path.Combine(LogoFilesPath, "300x100.png"));
|
|
logo.MediumType = "image/png";
|
|
|
|
logo.Large = System.IO.File.ReadAllBytes(System.IO.Path.Combine(LogoFilesPath, "600x200.png"));
|
|
logo.LargeType = "image/png";
|
|
|
|
await ct.SaveChangesAsync();
|
|
}
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
finally
|
|
{
|
|
//No matter what seeding is done
|
|
ServerBootConfig.SEEDING = false;
|
|
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();
|
|
}
|
|
|
|
public HashSet<string> HashUserNames = new HashSet<string>();
|
|
public HashSet<string> HashCompanyNames = new HashSet<string>();
|
|
|
|
|
|
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 SeedKnownObjectsAsync(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 SeedUserAsync(log, 1, AuthorizationRoles.BizAdminLimited, UserType.NotService, "BizAdminLimited", "BizAdminLimited", KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.BizAdminFull, UserType.NotService, "BizAdminFull", "BizAdminFull", KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.DispatchLimited, UserType.NotService, "DispatchLimited", "DispatchLimited", KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.DispatchFull, UserType.NotService, "DispatchFull", "DispatchFull", KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.InventoryLimited, UserType.NotService, "InventoryLimited", "InventoryLimited", KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.InventoryFull, UserType.NotService, "InventoryFull", "InventoryFull", KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.AccountingFull, UserType.NotService, "Accounting", "Accounting", KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.TechLimited, UserType.Service, "TechLimited", "TechLimited", KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.TechFull, UserType.Service, "TechFull", "TechFull", KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.SalesLimited, UserType.NotService, "SalesLimited", "SalesLimited", KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.SalesFull, UserType.NotService, "SalesFull", "SalesFull", KnownUserTags);
|
|
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.SubContractorLimited, UserType.ServiceContractor, "SubContractorLimited", "SubContractorLimited", KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.SubContractorFull, UserType.ServiceContractor, "SubContractorFull", "SubContractorFull", KnownUserTags);
|
|
|
|
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.OpsAdminLimited, UserType.NotService, "OpsAdminLimited", "OpsAdminLimited", KnownUserTags);
|
|
await SeedUserAsync(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 SeedUserAsync(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 SeedUserAsync(log, 1, AuthorizationRoles.OpsAdminLimited, UserType.NotService, false, "TEST_INACTIVE", "TEST_INACTIVE", 0, KnownUserTags);
|
|
|
|
//Alternate translation users for each stock translation
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.All, UserType.NotService, true, "de", "de", await TranslationBiz.TranslationNameToIdStaticAsync("de"), KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.All, UserType.NotService, true, "es", "es", await TranslationBiz.TranslationNameToIdStaticAsync("es"), KnownUserTags);
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.All, UserType.NotService, true, "fr", "fr", await TranslationBiz.TranslationNameToIdStaticAsync("fr"), KnownUserTags);
|
|
|
|
//CUSTOMER / HO Users
|
|
|
|
|
|
|
|
}
|
|
catch
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Generate seed user with active=true
|
|
/// (override to save typing)
|
|
/// </summary>
|
|
public async Task SeedUserAsync(ILogger log, int count, AuthorizationRoles roles, UserType userType, string login, string password, List<string> tags = null)
|
|
{
|
|
try
|
|
{
|
|
await SeedUserAsync(log, count, roles, userType, true, login, password, 0, tags);
|
|
}
|
|
catch
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public async Task SeedUserAsync(
|
|
ILogger log, int count, AuthorizationRoles roles, UserType userType,
|
|
bool active = true, string login = null, string password = null,
|
|
long translationId = 0, List<string> tags = null,
|
|
long? vendorId = null, long? customerId = null, long? headofficeId = null
|
|
)
|
|
{
|
|
if (translationId == 0)
|
|
translationId = ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID;
|
|
|
|
|
|
|
|
for (int x = 0; x < count; x++)
|
|
{
|
|
User u = new User();
|
|
u.Active = active;
|
|
|
|
do
|
|
{
|
|
u.Name = Fake.Name.FullName();
|
|
} while (!HashUserNames.Add(u.Name));
|
|
|
|
|
|
var bogusEmail = u.Name.ToLowerInvariant().Replace(" ", "_") + "@example.net";
|
|
if (login != null)
|
|
{
|
|
u.Login = login;
|
|
u.Name += " - " + login;
|
|
}
|
|
else
|
|
u.Login = bogusEmail;
|
|
|
|
if (password != null)
|
|
u.Password = password;
|
|
else
|
|
u.Password = u.Login;
|
|
u.Roles = roles;
|
|
u.UserType = userType;
|
|
u.EmployeeNumber = "A-" + (454 + SeededUserCount + x).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;
|
|
|
|
//relations
|
|
u.VendorId = vendorId;
|
|
u.CustomerId = customerId;
|
|
u.HeadOfficeId = headofficeId;
|
|
|
|
|
|
|
|
//Children and relations
|
|
u.UserOptions = new UserOptions();
|
|
u.UserOptions.TranslationId = translationId;
|
|
u.UserOptions.EmailAddress = bogusEmail;
|
|
u.UserOptions.Hour12 = true;
|
|
u.UserOptions.CurrencyName = "USD";
|
|
u.UserOptions.UiColor = Fake.Internet.Color().ToUpperInvariant();
|
|
|
|
|
|
//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);
|
|
var NewObject = await biz.CreateAsync(u);
|
|
if (NewObject == null)
|
|
{
|
|
log.LogError($"Seeder::SeedUser error creating {u.Name}\r\n" + biz.GetErrorsAsString());
|
|
throw new System.Exception("Seeder::SeedUser error creating user\r\n" + biz.GetErrorsAsString());
|
|
}
|
|
}
|
|
}
|
|
|
|
SeededUserCount += count;
|
|
}
|
|
|
|
#region WIDGET
|
|
//////////////////////////////////////////////////////
|
|
//Seed widget for testing
|
|
//
|
|
public async Task SeedWidgetAsync(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::SeedWidget error creating {o.Name}\r\n" + biz.GetErrorsAsString());
|
|
throw new System.Exception("Seeder::SeedWidget error creating widget\r\n" + biz.GetErrorsAsString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////
|
|
//CUSTOMER
|
|
//
|
|
public async Task SeedCustomerAsync(ILogger log, int count, long? headOfficeId = null)
|
|
{
|
|
|
|
for (int x = 0; x < count; x++)
|
|
{
|
|
Customer o = new Customer();
|
|
|
|
do
|
|
{
|
|
o.Name = Fake.Name.FullName();
|
|
} while (!HashCompanyNames.Add(o.Name));
|
|
|
|
|
|
o.Active = true;
|
|
o.Notes = Fake.Company.CatchPhrase();
|
|
o.Tags = RandomTags();
|
|
|
|
o.AccountNumber = Fake.Finance.Account();
|
|
o.Latitude = (decimal)Fake.Address.Latitude();
|
|
o.Longitude = (decimal)Fake.Address.Longitude();
|
|
o.Address = Fake.Address.StreetAddress();
|
|
o.City = Fake.Address.City();
|
|
o.Region = Fake.Address.State();
|
|
o.Country = Fake.Address.Country();
|
|
|
|
o.Phone1 = Fake.Phone.PhoneNumber();
|
|
o.Phone2 = Fake.Phone.PhoneNumber();
|
|
o.Phone3 = Fake.Phone.PhoneNumber();
|
|
o.WebAddress = Fake.Internet.Url();
|
|
o.EmailAddress = Fake.Internet.ExampleEmail();
|
|
|
|
if (headOfficeId != null)
|
|
{
|
|
o.HeadOfficeId = headOfficeId;
|
|
o.BillHeadOffice = true;
|
|
}
|
|
|
|
|
|
|
|
//This seems wrong to do in a loop but is 4 times faster this way ?!?
|
|
using (AyContext ct = ServiceProviderProvider.DBContext)
|
|
{
|
|
CustomerBiz biz = CustomerBiz.GetBiz(ct);
|
|
var NewObject = await biz.CreateAsync(o);
|
|
|
|
if (NewObject == null)
|
|
{
|
|
var err = $"Seeder::SeedCustomer error creating {o.Name}\r\n{biz.GetErrorsAsString()}";
|
|
log.LogError(err);
|
|
throw new System.Exception(err);
|
|
}
|
|
//Customer contacts
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.CustomerFull, UserType.Customer, true, null, null, 0, null, null, NewObject.Id, null);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////
|
|
//HEADOFFICE
|
|
//
|
|
public async Task SeedHeadOfficeAsync(ILogger log, int count)
|
|
{
|
|
|
|
for (int x = 0; x < count; x++)
|
|
{
|
|
HeadOffice o = new HeadOffice();
|
|
|
|
do
|
|
{
|
|
o.Name = Fake.Name.FullName();
|
|
} while (!HashCompanyNames.Add(o.Name));
|
|
|
|
|
|
o.Active = true;
|
|
o.Notes = Fake.Company.CatchPhrase();
|
|
o.Tags = RandomTags();
|
|
|
|
o.AccountNumber = Fake.Finance.Account();
|
|
o.Latitude = (decimal)Fake.Address.Latitude();
|
|
o.Longitude = (decimal)Fake.Address.Longitude();
|
|
o.Address = Fake.Address.StreetAddress();
|
|
o.City = Fake.Address.City();
|
|
o.Region = Fake.Address.State();
|
|
o.Country = Fake.Address.Country();
|
|
|
|
o.Phone1 = Fake.Phone.PhoneNumber();
|
|
o.Phone2 = Fake.Phone.PhoneNumber();
|
|
o.Phone3 = Fake.Phone.PhoneNumber();
|
|
o.WebAddress = Fake.Internet.Url();
|
|
o.EmailAddress = Fake.Internet.ExampleEmail();
|
|
|
|
|
|
|
|
//This seems wrong to do in a loop but is 4 times faster this way ?!?
|
|
using (AyContext ct = ServiceProviderProvider.DBContext)
|
|
{
|
|
HeadOfficeBiz biz = HeadOfficeBiz.GetBiz(ct);
|
|
var NewObject = await biz.CreateAsync(o);
|
|
|
|
if (NewObject == null)
|
|
{
|
|
var err = $"Seeder::SeedHeadOffice error creating {o.Name}\r\n{biz.GetErrorsAsString()}";
|
|
log.LogError(err);
|
|
throw new System.Exception(err);
|
|
}
|
|
//HeadOffice contacts
|
|
await SeedUserAsync(log, 1, AuthorizationRoles.CustomerFull, UserType.HeadOffice, true, null, null, 0, null, null, null, NewObject.Id);
|
|
//HeadOffice Customer
|
|
await SeedCustomerAsync(log, 2, NewObject.Id);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////
|
|
//VENDOR
|
|
//
|
|
public async Task SeedVendorAsync(ILogger log, int count)
|
|
{
|
|
|
|
for (int x = 0; x < count; x++)
|
|
{
|
|
Vendor o = new Vendor();
|
|
do
|
|
{
|
|
o.Name = Fake.Name.FullName();
|
|
} while (!HashCompanyNames.Add(o.Name));
|
|
|
|
|
|
o.Active = true;
|
|
o.Notes = Fake.Company.CatchPhrase();
|
|
o.Tags = RandomTags();
|
|
|
|
o.Contact = Fake.Name.FullName();
|
|
o.ContactNotes = Fake.Name.FullName();
|
|
o.AccountNumber = Fake.Finance.Account();
|
|
o.Latitude = (decimal)Fake.Address.Latitude();
|
|
o.Longitude = (decimal)Fake.Address.Longitude();
|
|
o.Address = Fake.Address.StreetAddress();
|
|
o.City = Fake.Address.City();
|
|
o.Region = Fake.Address.State();
|
|
o.Country = Fake.Address.Country();
|
|
|
|
o.Phone1 = Fake.Phone.PhoneNumber();
|
|
o.Phone2 = Fake.Phone.PhoneNumber();
|
|
o.Phone3 = Fake.Phone.PhoneNumber();
|
|
o.WebAddress = Fake.Internet.Url();
|
|
o.EmailAddress = Fake.Internet.ExampleEmail();
|
|
|
|
//This seems wrong to do in a loop but is 4 times faster this way ?!?
|
|
using (AyContext ct = ServiceProviderProvider.DBContext)
|
|
{
|
|
VendorBiz biz = VendorBiz.GetBiz(ct);
|
|
var NewObject = await biz.CreateAsync(o);
|
|
|
|
if (NewObject == null)
|
|
{
|
|
var err = $"Seeder::SeedVendor error creating {o.Name}\r\n{biz.GetErrorsAsString()}";
|
|
log.LogError(err);
|
|
throw new System.Exception(err);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}//eoc
|
|
|
|
|
|
|
|
}//eons |