diff --git a/server/AyaNova/ControllerHelpers/ApiUploadProcessor.cs b/server/AyaNova/ControllerHelpers/ApiUploadProcessor.cs index edddd5df..bd3671a6 100644 --- a/server/AyaNova/ControllerHelpers/ApiUploadProcessor.cs +++ b/server/AyaNova/ControllerHelpers/ApiUploadProcessor.cs @@ -36,7 +36,7 @@ namespace AyaNova.Api.ControllerHelpers /// - /// Process uploaded utility file (backup, import etc) + /// Process uploaded utility file (backup) /// Anything that will be stored in the backup folder as is /// /// diff --git a/server/AyaNova/Controllers/EventLogController.cs b/server/AyaNova/Controllers/EventLogController.cs index fabe9b53..21b204de 100644 --- a/server/AyaNova/Controllers/EventLogController.cs +++ b/server/AyaNova/Controllers/EventLogController.cs @@ -100,7 +100,7 @@ namespace AyaNova.Api.Controllers /// - /// V7 Import replace log entry + /// V7 export replace log entry /// (internal use only) /// /// diff --git a/server/AyaNova/Controllers/ImportAyaNova7Controller.cs b/server/AyaNova/Controllers/ImportAyaNova7Controller.cs deleted file mode 100644 index ba2fcceb..00000000 --- a/server/AyaNova/Controllers/ImportAyaNova7Controller.cs +++ /dev/null @@ -1,263 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Routing; -using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.Logging; -using Microsoft.EntityFrameworkCore; -using System.Globalization; -using System.IO; -using System.Text; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.WebUtilities; -using Microsoft.Net.Http.Headers; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json.Linq; -using AyaNova.Models; -using AyaNova.Api.ControllerHelpers; -using AyaNova.Util; -using AyaNova.Biz; - - -namespace AyaNova.Api.Controllers -{ - - - /// - /// Import AyaNova 7 data controller - /// - [ApiController] - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] - [Produces("application/json")] - [Authorize] - public class ImportAyaNova7Controller : ControllerBase - { - private readonly AyContext ct; - private readonly ILogger log; - private readonly ApiServerState serverState; - - - /// - /// - /// - /// - /// - /// - public ImportAyaNova7Controller(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) - { - ct = dbcontext; - log = logger; - serverState = apiServerState; - } - - - - /// - /// Upload AyaNova 7 import file - /// - /// NameValue list of filenames and id's - [HttpPost] - [DisableFormValueModelBinding] - [RequestSizeLimit(10737418241)]//10737418240 = 10gb https://github.com/aspnet/Announcements/issues/267 - public async Task Upload() - { - //outright closed then not allowed - if (serverState.IsClosed) - return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); - - if (!Authorized.HasCreateRole(HttpContext.Items, AyaType.AyaNova7Import)) - { - return StatusCode(403, new ApiNotAuthorizedResponse()); - } - - var returnList = new List(); - - try - { - if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)) - { - return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "FileUploadAttempt", $"Expected a multipart request, but got {Request.ContentType}")); - } - - var uploadFormData = await ApiUploadProcessor.ProcessUtilityFileUploadAsync(HttpContext); - - bool badRequest = false; - - string errorMessage = string.Empty; - - //are these the right files? - if (uploadFormData.UploadedFiles.Count > 0) - { - foreach (UploadedFileInfo a in uploadFormData.UploadedFiles) - { - //should look like this: ayanova.data.dump.2018-04-2--12-30-57.zip - string lwr = a.OriginalFileName.ToLowerInvariant(); - if (!(lwr.StartsWith("ayanova.data.dump") && lwr.EndsWith(".zip"))) - { - badRequest = true; - errorMessage = $"File uploaded \"{lwr}\" does not appear to be an AyaNova 7 data dump file. The name should start with \"ayanova.data.dump\" have a date in the middle and end with \".zip\". Upload process is terminated without saving."; - } - } - } - - - if (badRequest) - { - //delete temp files - if (uploadFormData.UploadedFiles.Count > 0) - { - foreach (UploadedFileInfo a in uploadFormData.UploadedFiles) - { - System.IO.File.Delete(a.InitialUploadedPathName); - } - } - //return bad request - return BadRequest(new ApiErrorResponse(ApiErrorCode.VALIDATION_INVALID_VALUE, null, errorMessage)); - } - - - //We have our files and a confirmed AyObject, ready to attach and save permanently - if (uploadFormData.UploadedFiles.Count > 0) - { - foreach (UploadedFileInfo a in uploadFormData.UploadedFiles) - { - returnList.Add(a.OriginalFileName); - } - } - } - catch (InvalidDataException ex) - { - return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "FileUploadAttempt", ex.Message)); - } - - //Return the list of attachment ids and filenames - return Ok(ApiOkResponse.Response(returnList, true)); - } - - - /// - /// Delete import file - /// - /// - /// Ok - [HttpDelete("{filename}")] - public ActionResult Delete([FromRoute] string filename) - { - if (serverState.IsClosed) - return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); - - if (!ModelState.IsValid) - { - return BadRequest(new ApiErrorResponse(ModelState)); - } - - - if (!Authorized.HasDeleteRole(HttpContext.Items, AyaType.AyaNova7Import)) - { - return StatusCode(403, new ApiNotAuthorizedResponse()); - } - - //do the delete - //this handles removing the file if there are no efs left and also the db record for the attachment - FileUtil.DeleteUtilityFile(filename); - - return NoContent(); - } - - - /// - /// Get AyaNova 7 data dump uploaded files list - /// - /// List of uploaded data dump files - [HttpGet] - public ActionResult List() - { - if (serverState.IsClosed) - return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); - - if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.AyaNova7Import)) - { - return StatusCode(403, new ApiNotAuthorizedResponse()); - } - - if (!ModelState.IsValid) - { - return BadRequest(new ApiErrorResponse(ModelState)); - } - - //dump file name example: ayanova.data.dump.XXX.zip - List l = FileUtil.UtilityFileList("ayanova.data.dump.*.zip"); - return Ok(ApiOkResponse.Response(l, true)); - } - - - /// - /// *ERASE DATABASE and start import of previously uploaded import file - /// **This will permanently erase all current data in database without further warning as the first step in the import process** - /// - /// - /// Ok - [HttpPost("EraseDatabaseAndStartImport/{filename}")] - public async Task EraseDatabaseAndStartImport([FromRoute] string filename) - { - if (serverState.IsClosed) - return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); - - if (!serverState.IsOpsOnly) - return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, null, "Server must be set to Operations Only mode before importing")); - - if (!ModelState.IsValid) - { - return BadRequest(new ApiErrorResponse(ModelState)); - } - - //UPDATE: I think it should be ok so commenting this out for now pending something coming up in testing - // //LOOKAT: I decided not to allow trial to import v7 data. - // //This was a snap decision, I didn't think about it much other than - // //I'm concerned right now as of April 17 2018 during development that - // //a trial user will import their old AyaNova data and then ... well somehow continue to use it I guess, - // //maybe it's a non-issue as a trial will only work so long anyway - // #if (!DEBUG) - // if (AyaNova.Core.License.LicenseIsTrial) - // { - // return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, null, "Current license is a trial license key. Only a licensed database can be used with import.")); - // } - // #endif - - //Create, in that they are creating new data in AyaNova - if (!Authorized.HasCreateRole(HttpContext.Items, AyaType.AyaNova7Import)) - { - return StatusCode(403, new ApiNotAuthorizedResponse()); - } - - //does the file even exist? - if (!FileUtil.UtilityFileExists(filename)) - { - return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND, "filename", "File not found, ensure the name via the GET route endpoint list of previously uploaded import files")); - } - - - //Create the job here - dynamic jobInfo = new JObject(); - jobInfo.ImportFileName = filename; - - OpsJob j = new OpsJob(); - j.Name = $"Import AyaNova7 data (import file \"{filename}\""; - j.JobType = JobType.ImportV7Data; - //j.O wnerId = UserIdFromContext.Id(HttpContext.Items); - j.JobInfo = jobInfo.ToString(); - await JobsBiz.AddJobAsync(j, ct); - return Accepted(new { JobId = j.GId });//202 accepted - } - - //////////////////////////////////////////////////////////////////////////////////// - - - - }//eoc -}//eons - diff --git a/server/AyaNova/biz/AyaType.cs b/server/AyaNova/biz/AyaType.cs index 80c13aa2..5602adb5 100644 --- a/server/AyaNova/biz/AyaType.cs +++ b/server/AyaNova/biz/AyaType.cs @@ -36,7 +36,7 @@ namespace AyaNova.Biz PickListTemplate = 7, DEPRECATED_REUSELATER_08 = 8, ServerJob = 9, - AyaNova7Import = 10, + DEPRECATED_10 = 10, TrialSeeder = 11, Metrics = 12, Translation = 13, diff --git a/server/AyaNova/biz/EventLogProcessor.cs b/server/AyaNova/biz/EventLogProcessor.cs index efc4702b..a4138cd8 100644 --- a/server/AyaNova/biz/EventLogProcessor.cs +++ b/server/AyaNova/biz/EventLogProcessor.cs @@ -125,13 +125,13 @@ namespace AyaNova.Biz /// - /// V7 import handler - /// Import needs to fixup event log CREATED entry to show original created and last modified times + /// V7 export handler + /// Exporter needs to fixup event log CREATED entry to show original created and last modified times /// and users /// internal static async Task V7_Modify_LogAsync(AyaNova.Api.Controllers.EventLogController.V7Event ev, AyContext ct) { - //delete the automatically created entry from the import object + //delete the automatically created entry from the exported object await ct.Database.ExecuteSqlInterpolatedAsync($"delete from aevent where aytype = {ev.AyType} and ayid={ev.AyId}"); //Now create the entries to reflect the original data from v7 diff --git a/server/AyaNova/biz/IImportAyaNova7Object.cs b/server/AyaNova/biz/IImportAyaNova7Object.cs deleted file mode 100644 index 141bce1b..00000000 --- a/server/AyaNova/biz/IImportAyaNova7Object.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using AyaNova.Models; -using Newtonsoft.Json.Linq; - - -namespace AyaNova.Biz -{ - /// - /// Interface for biz objects that support importing AyaNova 7 data - /// - internal interface IImportAyaNova7Object - { - - /// - /// Import from the JSON data provided - /// - /// Json object containing source record - /// A collection that can be used to match import records to new records, NOT persistent between imports - /// JobId for logging or controlling jobs from within processor - /// All the items imported to lists of tags with matching id for attribution / tagging imported object - /// True if imported, False if not imported due to invalid or other error (logged in job log) - Task ImportV7Async(JObject v7ImportData, List importMap, Guid JobId, Dictionary> tagLists); - - /// - /// If true, relaxes validation rules so that incomplete data can be imported - /// - bool SeedOrImportRelaxedRulesMode { get; set; } - - } - -} \ No newline at end of file diff --git a/server/AyaNova/biz/ImportAyaNova7Biz.cs b/server/AyaNova/biz/ImportAyaNova7Biz.cs deleted file mode 100644 index 46b6c668..00000000 --- a/server/AyaNova/biz/ImportAyaNova7Biz.cs +++ /dev/null @@ -1,364 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore; -using Microsoft.AspNetCore.Mvc; -using Newtonsoft.Json.Linq; -using EnumsNET; -using AyaNova.Util; -using AyaNova.Api.ControllerHelpers; -using AyaNova.Biz; -using AyaNova.Models; - - -namespace AyaNova.Biz -{ - - - internal class ImportAyaNova7Biz : BizObject, IJobObject - { - // private readonly AyContext ct; - // public readonly long userId; - // private readonly AuthorizationRoles userRoles; - - - internal ImportAyaNova7Biz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles) - { - ct = dbcontext; - UserId = currentUserId; - CurrentUserRoles = userRoles; - BizType = AyaType.AyaNova7Import; - } - - //////////////////////////////////////////////////////////////////////////////////////////////// - //JOB / OPERATIONS - // - public async Task HandleJobAsync(OpsJob job) - { - //Hand off the particular job to the corresponding processing code - //NOTE: If this code throws an exception the caller (JobsBiz::ProcessJobsAsync) will automatically set the job to failed and log the exeption so - //basically any error condition during job processing should throw up an exception if it can't be handled - - //There might be future other job types so doing it like this for all biz job handlers for now - switch (job.JobType) - { - case JobType.ImportV7Data: - await ProcessImportV7JobAsync(job); - break; - default: - throw new System.ArgumentOutOfRangeException($"ImportAyaNovaBiz.HandleJob-> Invalid job type{job.JobType.ToString()}"); - } - } - - - /// - /// /// Handle the test job - /// - /// - private async Task ProcessImportV7JobAsync(OpsJob job) - { - //NOTE: If this code throws an exception the caller will automatically set the job to failed and log the exeption so - //basically any error condition during job processing should throw up an exception if it can't be handled - List importMap = new List(); - - await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Running, ct); - await JobsBiz.LogJobAsync(job.GId, $"ImportAyaNova7 starting", ct); - - //Get the import filename from the jsondata - JObject jobData = JObject.Parse(job.JobInfo); - var importFileName = jobData["ImportFileName"].Value(); - if (string.IsNullOrWhiteSpace(importFileName)) - { - throw new System.ArgumentNullException("ImportAyaNova7 job failed due to no import filename being specified"); - } - - if (!FileUtil.UtilityFileExists(importFileName)) - { - throw new System.ArgumentNullException("ImportAyaNova7 job failed due to import file specified not existing"); - } - - - //Erase all the data except for the license, schema and the manager user - Microsoft.Extensions.Logging.ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("ImportAyaNova7"); - await JobsBiz.LogJobAsync(job.GId, "ImportAyaNova7 - Erasing data from database", ct); - await DbUtil.EmptyBizDataFromDatabaseForSeedingOrImportingAsync(log); - - - //get the contents of the archive - List zipEntries = FileUtil.ZipGetUtilityFileEntries(importFileName); - - //Iterate through the import items in the preferred order, checking for corresponding entries in the zip file - //In turn try to instantiate the type and id job that can handle that import, attempt to case or see if implements IImportAyaNova7Object - //, if null / not supported for import then skip and log as not currently supported - - //Pass off the JSON data from the import file into the import job item by item - - //NOTE: Many of these require a second pass - one to get the object imported and then another to set another imported object to that object - - //////////////////////////////////// - //TAGS - // - - //FIRST: import items that will become tags first into temporary cache lists - Dictionary> TagLists = new Dictionary>(); - - //IMPORT UNIT MODEL CATEGORIES AS TAGS - TagLists.Add("UnitModelCategory", new Dictionary()); - await ImportTagListAsync("GZTW.AyaNova.BLL.UnitModelCategory", job.GId, TagLists["UnitModelCategory"], importFileName, zipEntries); - - //IMPORT Unit service type AS TAGS - TagLists.Add("UnitServiceType", new Dictionary()); - await ImportTagListAsync("GZTW.AyaNova.BLL.UnitServiceType", job.GId, TagLists["UnitServiceType"], importFileName, zipEntries); - - //IMPORT Workorder Item Type AS TAGS - TagLists.Add("WorkorderItemType", new Dictionary()); - await ImportTagListAsync("GZTW.AyaNova.BLL.WorkorderItemType", job.GId, TagLists["WorkorderItemType"], importFileName, zipEntries); - - //IMPORT Client group AS TAGS - TagLists.Add("ClientGroup", new Dictionary()); - await ImportTagListAsync("GZTW.AyaNova.BLL.ClientGroup", job.GId, TagLists["ClientGroup"], importFileName, zipEntries); - - //IMPORT Workorder category AS TAGS - TagLists.Add("WorkorderCategory", new Dictionary()); - await ImportTagListAsync("GZTW.AyaNova.BLL.WorkorderCategory", job.GId, TagLists["WorkorderCategory"], importFileName, zipEntries); - - //IMPORT Part Category AS TAGS - TagLists.Add("PartCategory", new Dictionary()); - await ImportTagListAsync("GZTW.AyaNova.BLL.PartCategory", job.GId, TagLists["PartCategory"], importFileName, zipEntries); - - //IMPORT Dispatch zones AS TAGS - TagLists.Add("DispatchZone", new Dictionary()); - await ImportTagListAsync("GZTW.AyaNova.BLL.DispatchZone", job.GId, TagLists["DispatchZone"], importFileName, zipEntries); - - //IMPORT Scheduleable User Groups AS TAGS - TagLists.Add("ScheduleableUserGroup", new Dictionary()); - await ImportTagListAsync("GZTW.AyaNova.BLL.ScheduleableUserGroup", job.GId, TagLists["ScheduleableUserGroup"], importFileName, zipEntries); - - //Now can set users to correct tag for scheduleable user group - // await ImportTagList("GZTW.AyaNova.BLL.ScheduleableUserGroup", "scheduleableusergrouptags", AyaType.Tag, job.GId, importMap, importFileName, zipEntries); - - //IMPORT REGIONS AS TAGS - TagLists.Add("Region", new Dictionary()); - await ImportTagListAsync("GZTW.AyaNova.BLL.Region", job.GId, TagLists["Region"], importFileName, zipEntries); - - - - //////////////////////////////////// - // OBJECTS - // - - //USERS - await DoImportAsync("GZTW.AyaNova.BLL.User", "main", AyaType.User, job.GId, importMap, importFileName, zipEntries, TagLists); - //Now can do event log entries - await DoImportAsync("GZTW.AyaNova.BLL.User", "eventlog", AyaType.User, job.GId, importMap, importFileName, zipEntries, TagLists); - - - - //IMPORT TRANSLATIONS - await DoImportAsync("GZTW.AyaNova.BLL.Translation", "main", AyaType.Translation, job.GId, importMap, importFileName, zipEntries, TagLists); - //Now can do user translation settings properly - await DoImportAsync("GZTW.AyaNova.BLL.User", "translation", AyaType.User, job.GId, importMap, importFileName, zipEntries, TagLists); - - //TODO: CLIENT - //do import for client here - //Now can do user client settings properly - //await DoImport("GZTW.AyaNova.BLL.User","clientid", AyaType.User, job.GId, importMap, importFileName, zipEntries); - - //TODO: HEADOFFICE - //do import for ho here - //Now can do user ho settings properly - //await DoImport("GZTW.AyaNova.BLL.User","headofficeid", AyaType.User, job.GId, importMap, importFileName, zipEntries); - - - - //---------------- - await JobsBiz.LogJobAsync(job.GId, "ImportAyaNova7 finished", ct); - await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Completed, ct); - - - } - - /// - /// This method does the actual import by - /// - Fetching the list of entries in the zip archive that match the passed in startsWtih (folder name in zip archive) - /// - Instantiating the corresponding new biz object type to handle the import - /// - Passing the json parsed to the biz object one at a time to do the import - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - private async Task DoImportAsync(string entryStartsWith, string importTask, AyaType importerType, Guid jobId, - List importMap, string importFileName, List zipEntries, Dictionary> tagLists) - { - var zipObjectList = zipEntries.Where(m => m.StartsWith(entryStartsWith)).ToList(); - long importCount = 0; - long notImportCount = 0; - if (zipObjectList.Count > 0) - { - if (importTask != "main") - { - await JobsBiz.LogJobAsync(jobId, $"Starting import sub-task {importTask} of {entryStartsWith} objects", ct); - } - else - { - await JobsBiz.LogJobAsync(jobId, $"Starting import of {entryStartsWith} objects", ct); - } - - var jList = FileUtil.ZipGetUtilityArchiveEntriesAsJsonObjects(zipObjectList, importFileName); - - IImportAyaNova7Object o = (IImportAyaNova7Object)BizObjectFactory.GetBizObject(importerType, ct); - - foreach (JObject j in jList) - { - bool bImportSucceeded = false; - //some new types can import multiple old types and it might matter which is which to the importer - //so tag it with the original type - //------ - j.Add("V7_TYPE", JToken.FromObject(entryStartsWith)); - j.Add("IMPORT_TASK", JToken.FromObject(importTask)); - - bImportSucceeded = await o.ImportV7Async(j, importMap, jobId, tagLists); - if (bImportSucceeded) - importCount++; - else - notImportCount++; - } - - if (importCount > 0) - { - if (importTask != "main") - { - await JobsBiz.LogJobAsync(jobId, $"Successfully ran import subtask {importTask} on {importCount.ToString()} of {zipObjectList.Count.ToString()} {entryStartsWith} objects", ct); - } - else - { - await JobsBiz.LogJobAsync(jobId, $"Successfully imported {importCount.ToString()} of {zipObjectList.Count.ToString()} {entryStartsWith} objects", ct); - } - } - - if (notImportCount > 0) - { - if (importTask != "main") - { - await JobsBiz.LogJobAsync(jobId, $"Failed to run import subtask {importTask} on {notImportCount.ToString()} of {zipObjectList.Count.ToString()} {entryStartsWith} objects", ct); - } - else - { - await JobsBiz.LogJobAsync(jobId, $"Did not import {notImportCount.ToString()} of {zipObjectList.Count.ToString()} {entryStartsWith} objects", ct); - } - } - } - } - - //Other job handlers here... - - - private async Task ImportTagListAsync(string entryStartsWith, Guid jobId, Dictionary tagDictionary, string importFileName, List zipEntries) - { - var zipObjectList = zipEntries.Where(m => m.StartsWith(entryStartsWith)).ToList(); - long importCount = 0; - - if (zipObjectList.Count > 0) - { - await JobsBiz.LogJobAsync(jobId, $"Starting import to TAGS of {entryStartsWith} objects", ct); - var jList = FileUtil.ZipGetUtilityArchiveEntriesAsJsonObjects(zipObjectList, importFileName); - - foreach (JObject j in jList) - { - - //------- IMPORT OBJECTS NAME AND ID TO LIST ------ - #region main import task - var NewTagName = j["Name"].Value(); - - var ShortTypeName = string.Empty; - switch (entryStartsWith) - { - case "GZTW.AyaNova.BLL.Region": - ShortTypeName = "region"; - break; - case "GZTW.AyaNova.BLL.UnitModelCategory": - ShortTypeName = "unitmodelcategory"; - break; - case "GZTW.AyaNova.BLL.UnitServiceType": - ShortTypeName = "unitservicetype"; - break; - case "GZTW.AyaNova.BLL.WorkorderItemType": - ShortTypeName = "workorderitemtype"; - break; - case "GZTW.AyaNova.BLL.ClientGroup": - ShortTypeName = "clientgroup"; - break; - case "GZTW.AyaNova.BLL.WorkorderCategory": - ShortTypeName = "workordercategory"; - break; - case "GZTW.AyaNova.BLL.PartCategory": - ShortTypeName = "partcategory"; - break; - case "GZTW.AyaNova.BLL.DispatchZone": - ShortTypeName = "dispatchzone"; - break; - case "GZTW.AyaNova.BLL.ScheduleableUserGroup": - ShortTypeName = "scheduleableusergroup"; - break; - } - - NewTagName += "." + ShortTypeName; - var OldV7Id = new Guid(j["ID"].Value()); - - //Ensure it follows the rules - NewTagName = TagUtil.NormalizeTag(NewTagName); - - //Add to dictionary if not present - tagDictionary.Add(OldV7Id, NewTagName); - - #endregion - - //----------------------------------------------- - importCount++; - - } - - if (importCount > 0) - { - await JobsBiz.LogJobAsync(jobId, $"Successfully imported as TAGS {importCount.ToString()} of {zipObjectList.Count.ToString()} {entryStartsWith} objects", ct); - } - } - } - - - - - - ////////////////////////////////////////////////////////////////// - //UTILITIES - internal static async Task LogEventCreatedModifiedEventsAsync(JObject j, List importMap, AyaType ayaType, AyContext ct) - { - var V7Id = new Guid(j["ID"].Value()); - var RavenId = importMap.Where(m => m.V7ObjectId == V7Id).First().NewObjectAyaTypeId.ObjectId; - var Creator = importMap.Where(m => m.V7ObjectId == new Guid(j["Creator"].Value())).First().NewObjectAyaTypeId.ObjectId; - var Modifier = importMap.Where(m => m.V7ObjectId == new Guid(j["Modifier"].Value())).First().NewObjectAyaTypeId.ObjectId; - var Created = j["Created"].Value(); - var Modified = j["Modified"].Value(); - - //handle EventLog entries for users now that we have the user's created - //Created - await EventLogProcessor.LogEventToDatabaseAsync(new Event(Creator, RavenId, ayaType, AyaEvent.Created, Created), ct); - //MODIFIED - await EventLogProcessor.LogEventToDatabaseAsync(new Event(Modifier, RavenId, ayaType, AyaEvent.Modified, Modified), ct); - - } - - ///////////////////////////////////////////////////////////////////// - - }//eoc - - -}//eons - diff --git a/server/AyaNova/biz/JobType.cs b/server/AyaNova/biz/JobType.cs index 441ab1af..e93abbae 100644 --- a/server/AyaNova/biz/JobType.cs +++ b/server/AyaNova/biz/JobType.cs @@ -9,8 +9,7 @@ namespace AyaNova.Biz { NotSet = 0, TestWidgetJob = 1,//test job for unit testing - CoreJobSweeper = 2, - ImportV7Data = 3, + CoreJobSweeper = 2, SeedTestData = 4, diff --git a/server/AyaNova/biz/JobsBiz.cs b/server/AyaNova/biz/JobsBiz.cs index 09946663..10199ef0 100644 --- a/server/AyaNova/biz/JobsBiz.cs +++ b/server/AyaNova/biz/JobsBiz.cs @@ -385,10 +385,7 @@ namespace AyaNova.Biz { case JobType.TestWidgetJob: o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.Widget, ct); - break; - case JobType.ImportV7Data: - o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.AyaNova7Import, ct); - break; + break; case JobType.SeedTestData: o = (IJobObject)BizObjectFactory.GetBizObject(AyaType.TrialSeeder, ct); break; diff --git a/server/AyaNova/biz/TranslationBiz.cs b/server/AyaNova/biz/TranslationBiz.cs index 55c954a3..044911aa 100644 --- a/server/AyaNova/biz/TranslationBiz.cs +++ b/server/AyaNova/biz/TranslationBiz.cs @@ -12,7 +12,7 @@ using System.Text.RegularExpressions; namespace AyaNova.Biz { - internal class TranslationBiz : BizObject, IImportAyaNova7Object + internal class TranslationBiz : BizObject { public bool SeedOrImportRelaxedRulesMode { get; set; } @@ -199,7 +199,7 @@ namespace AyaNova.Biz return await ct.TranslationItem.Where(m => m.TranslationId == ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID && m.Key == key).Select(m => m.Display).AsNoTracking().FirstOrDefaultAsync(); } - //Get all stock keys that are valid (used for import) + //Get all stock keys that are valid (used for key coverage reporting) internal static async Task> GetKeyListAsync() { AyContext ct = ServiceProviderProvider.DBContext; @@ -253,8 +253,9 @@ namespace AyaNova.Biz foreach (NewTextIdConcurrencyTokenItem tit in inObj) { - var titem=await ct.TranslationItem.SingleOrDefaultAsync(m => m.Id == tit.Id); - if(titem==null){ + var titem = await ct.TranslationItem.SingleOrDefaultAsync(m => m.Id == tit.Id); + if (titem == null) + { AddError(ApiErrorCode.NOT_FOUND, $"Translation item ID {tit.Id}"); return false; } @@ -429,107 +430,6 @@ namespace AyaNova.Biz } - /// - /// Used by import, translate the old v7 translation key name into the new shorter version - /// - /// - /// - public string Translatev7TranslationKey(string oldKey) - { - string s = oldKey.Replace(".Label.", ".", StringComparison.InvariantCultureIgnoreCase); - if (s.StartsWith("O.", StringComparison.InvariantCultureIgnoreCase)) - s = s.Replace("O.", "", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace(".ToolBar.", ".", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace(".Go.", ".", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace(".Command.", ".", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace(".Error.", ".", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace(".Object.", ".", StringComparison.InvariantCultureIgnoreCase); - if (s.StartsWith("UI.", StringComparison.InvariantCultureIgnoreCase)) - s = s.Replace("UI.", "", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace(".", "", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("AddressAddress", "Address", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ContactPhoneContactPhone", "ContactPhone", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ContactPhonePhone", "ContactPhone", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("PurchaseOrderPurchaseOrder", "PurchaseOrder", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("WorkorderItemMiscExpenseExpense", "WorkorderItemMiscExpense", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("WorkorderItemTravelTravel", "WorkorderItemTravel", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("DashboardDashboard", "Dashboard", StringComparison.InvariantCultureIgnoreCase); - - //ScheduleMarkers -> Reminder - s = s.Replace("ScheduleMarker", "Reminder", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerARGB", "ReminderARGB", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerColor", "ReminderColor", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerCompleted", "ReminderCompleted", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerEventCreated", "ReminderEventCreated", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerEventPendingAlert", "ReminderEventPendingAlert", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerFollowUp", "ReminderFollowUp", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerList", "ReminderList", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerName", "ReminderName", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerNotes", "ReminderNotes", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerRecurrence", "ReminderRecurrence", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerScheduleMarkerSourceType", "ReminderSourceType", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerSourceID", "ReminderSourceID", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerStartDate", "ReminderStartDate", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleMarkerStopDate", "ReminderStopDate", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleEditScheduleMarker", "ScheduleEditReminder", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("ScheduleNewScheduleMarker", "ScheduleNewReminder", StringComparison.InvariantCultureIgnoreCase); - - - - - //Custom fields were 0 to 9, now 1 to 16 - s = s.Replace("Custom9", "Custom10", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("Custom8", "Custom9", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("Custom7", "Custom8", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("Custom6", "Custom7", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("Custom5", "Custom6", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("Custom4", "Custom5", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("Custom3", "Custom4", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("Custom2", "Custom3", StringComparison.InvariantCultureIgnoreCase); - if (!s.EndsWith("Custom10")) - s = s.Replace("Custom1", "Custom2", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("Custom0", "Custom1", StringComparison.InvariantCultureIgnoreCase); - //separate code will handle adding the new keys that didn't exist in v7 (custom 11 - 16) - - //CommonActive CommonID etc remove Common - s = s.Replace("Common", ""); - - //Misc - s = s.Replace("FormFieldDataType", "UiFieldDataType", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("UserUserType", "UserType", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("UserTypesUtilityNotification", "UserTypesUtility", StringComparison.InvariantCultureIgnoreCase); - - //Localized -> Translation - s = s.Replace("LocaleCustomizeText", "TranslationCustomizeText", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocaleExport", "TranslationExport", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocaleImport", "TranslationImport", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocaleList", "TranslationList", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocaleLocaleFile", "TranslationFile", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocaleUIDestLocale", "TranslationDest", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocaleUISourceLocale", "TranslationSource", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocaleWarnLocaleLocked", "TranslationWarnLocked", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocalizedTextDisplayText", "TranslationDisplayText", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocalizedTextDisplayTextCustom", "TranslationDisplayTextCustom", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocalizedTextKey", "TranslationKey", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocalizedTextLocale", "Translation", StringComparison.InvariantCultureIgnoreCase); - s = s.Replace("LocalizedText", "TranslatedText", StringComparison.InvariantCultureIgnoreCase); - - - //FUTURE - // s = s.Replace("WASXXX", "NOWXXXX", StringComparison.InvariantCultureIgnoreCase); - // s = s.Replace("WASXXX", "NOWXXXX", StringComparison.InvariantCultureIgnoreCase); - // s = s.Replace("WASXXX", "NOWXXXX", StringComparison.InvariantCultureIgnoreCase); - // s = s.Replace("WASXXX", "NOWXXXX", StringComparison.InvariantCultureIgnoreCase); - // s = s.Replace("WASXXX", "NOWXXXX", StringComparison.InvariantCultureIgnoreCase); - // s = s.Replace("WASXXX", "NOWXXXX", StringComparison.InvariantCultureIgnoreCase); - // s = s.Replace("WASXXX", "NOWXXXX", StringComparison.InvariantCultureIgnoreCase); - // s = s.Replace("WASXXX", "NOWXXXX", StringComparison.InvariantCultureIgnoreCase); - // s = s.Replace("WASXXX", "NOWXXXX", StringComparison.InvariantCultureIgnoreCase); - - return s; - } - - /// @@ -580,108 +480,6 @@ namespace AyaNova.Biz } - ///////////////////////////////////////////////////////////////////// - /// IMPORT v7 implementation - public async Task ImportV7Async( - JObject j, List importMap, - Guid jobId, Dictionary> tagLists) - { - //some types need to import from more than one source hence the seemingly redundant switch statement for futureproofing - switch (j["IMPORT_TASK"].Value()) - { - case "main": - { - //Get source translation name from filename using regex - var SourceTranslationFileName = j["V7_SOURCE_FILE_NAME"].Value(); - Regex RxExtractTranslationName = new Regex(@"translation\.(.*)\.json"); - var v = RxExtractTranslationName.Match(SourceTranslationFileName); - var SourceTranslationName = v.Groups[1].ToString(); - - //Ensure doesn't already exist - if (await TranslationExistsAsync(SourceTranslationName)) - { - //If there are any validation errors, log in joblog and move on - await JobsBiz.LogJobAsync(jobId, $"TranslationBiz::ImportV7Async -> - Translation \"{SourceTranslationName}\" already exists in database, can not import over an existing translation", ct); - return false; - } - - //keys to skip importing - List SkipKeys = new List(); - SkipKeys.Add("UI.Label.CurrentUserName"); - SkipKeys.Add("V7_SOURCE_FILE_NAME"); - SkipKeys.Add("V7_TYPE"); - SkipKeys.Add("IMPORT_TASK"); - - List ValidKeys = await GetKeyListAsync(); - Dictionary NewTranslationDict = new Dictionary(); - foreach (var Pair in j.Children()) - { - var V7Value = Pair.First.Value().Replace(" && ", " ").Replace(" & ", " ").Replace("&", "");//clean out LT values that had double ampersands for old Windows menu shortcut scheme - var V7KeyName = ((JProperty)Pair).Name; - - if (!SkipKeys.Contains(V7KeyName)) - { - var RavenKeyName = Translatev7TranslationKey(V7KeyName); - if (!ValidKeys.Contains(RavenKeyName)) - { - throw new System.ArgumentOutOfRangeException($"TranslationBiz::ImportV7 - old Key \"{V7KeyName}\" translates to new Key \"{RavenKeyName}\" which is not valid!"); - } - - if (!NewTranslationDict.ContainsKey(RavenKeyName)) - { - NewTranslationDict.Add(RavenKeyName, V7Value); - } - else - { - //Use the shortest V7Value string in the case of dupes - if (NewTranslationDict[RavenKeyName].Length > V7Value.Length) - { - NewTranslationDict[RavenKeyName] = V7Value; - } - } - } - } - - //Now add keys that were added after v7 for RAVEN using default translation values - foreach (string s in ValidKeys) - { - if (!NewTranslationDict.ContainsKey(s)) - { - NewTranslationDict.Add(s, await GetDefaultTranslationAsync(s)); - } - } - - //Validate it's the correct number of keys expected - if (NewTranslationDict.Count != ValidKeys.Count) - { - throw new System.ArgumentOutOfRangeException($"TranslationBiz::ImportV7 - Import translation \"{SourceTranslationName}\" has an unexpected number of keys: {NewTranslationDict.Count}, expected {ValidKeys.Count} "); - } - - //have file name, have all localized text - Translation l = new Translation(); - l.Name = SourceTranslationName; - l.Stock = false; - - foreach (KeyValuePair K in NewTranslationDict) - { - l.TranslationItems.Add(new TranslationItem() { Key = K.Key, Display = K.Value }); - } - - await ct.Translation.AddAsync(l); - await ct.SaveChangesAsync(); - - //Log now that we have the Id, note that there is no source created / modified for this so just attributing to current userId - await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, l.Id, AyaType.Translation, AyaEvent.Created), ct); - - } - break; - } - - - - //this is the equivalent of returning void for a Task signature with nothing to return - return true; - } ///////////////////////////////////////////////////////////////////// diff --git a/server/AyaNova/biz/TrialBiz.cs b/server/AyaNova/biz/TrialBiz.cs index 50ab95c5..280be5b4 100644 --- a/server/AyaNova/biz/TrialBiz.cs +++ b/server/AyaNova/biz/TrialBiz.cs @@ -60,14 +60,8 @@ namespace AyaNova.Biz //NOTE: If this code throws an exception the caller will automatically set the job to failed and log the exeption so //basically any error condition during job processing should throw up an exception if it can't be handled - - //FOR NOW NOT ASYNC so faking it at end of this method - - await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Running, ct); - await JobsBiz.LogJobAsync(job.GId, $"Starting...", ct); - - //Get the import filename from the jsondata + await JobsBiz.LogJobAsync(job.GId, $"Starting...", ct); JObject jobData = JObject.Parse(job.JobInfo); var seedLevel = (Seeder.SeedLevel)jobData["seedLevel"].Value(); var timeZoneOffset = jobData["timeZoneOffset"].Value(); diff --git a/server/AyaNova/biz/UserBiz.cs b/server/AyaNova/biz/UserBiz.cs index fa0590be..352e4b36 100644 --- a/server/AyaNova/biz/UserBiz.cs +++ b/server/AyaNova/biz/UserBiz.cs @@ -6,15 +6,12 @@ using EnumsNET; using AyaNova.Util; using AyaNova.Api.ControllerHelpers; using AyaNova.Models; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; namespace AyaNova.Biz { - internal class UserBiz : BizObject, IJobObject, IImportAyaNova7Object, ISearchAbleObject + internal class UserBiz : BizObject, IJobObject, ISearchAbleObject { public bool SeedOrImportRelaxedRulesMode { get; set; } @@ -503,304 +500,6 @@ namespace AyaNova.Biz } - - - public async Task ImportV7Async(JObject j, List importMap, Guid jobId, Dictionary> tagLists) - { - - //NEEDS 3 of the tag lists - - //TODO: Some of these items will need to be imported in future USEROPTIONS object that doesn't exist yet - #region V7 record format - /* - { - "DefaultLanguage": "Custom English", - "DefaultServiceTemplateID": "ca83a7b8-4e5f-4a7b-a02b-9cf78d5f983f", - "UserType": 2, - "Active": true, - "ClientID": "00000000-0000-0000-0000-000000000000", - "HeadOfficeID": "00000000-0000-0000-0000-000000000000", - * "MemberOfGroup": "0f8a80ff-4b03-4114-ae51-2d13b812dd65", - "Created": "03/21/2005 07:19 AM", - "Modified": "09/15/2015 12:22 PM", - "Creator": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed", - "Modifier": "1d859264-3f32-462a-9b0c-a67dddfdf4d3", - "ID": "1d859264-3f32-462a-9b0c-a67dddfdf4d3", - "FirstName": "Hank", - "LastName": "Rearden", - "Initials": "HR", - "EmployeeNumber": "EMP1236", - "PageAddress": "", - "PageMaxText": 24, - "Phone1": "", - "Phone2": "", - "EmailAddress": "", - "UserCertifications": [ - { - "Created": "12/22/2005 02:07 PM", - "Creator": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed", - "Modified": "12/22/2005 02:08 PM", - "Modifier": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed", - "ID": "4492360c-43e4-4209-9f33-30691b0808ed", - "UserCertificationID": "b2f26359-7c42-4218-923a-e949f3ef1f85", - "UserID": "1d859264-3f32-462a-9b0c-a67dddfdf4d3", - "ValidStartDate": "2005-10-11T00:00:00-07:00", - "ValidStopDate": "2006-10-11T00:00:00-07:00" - } - ], - "UserSkills": [ - { - "Created": "12/22/2005 02:06 PM", - "Creator": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed", - "Modified": "12/22/2005 02:08 PM", - "Modifier": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed", - "ID": "1dc5ce96-f411-4885-856e-5bdb3ad79728", - "UserSkillID": "2e6f8b65-594c-4f6c-9cd6-e14a562daba8", - "UserID": "1d859264-3f32-462a-9b0c-a67dddfdf4d3" - }, - { - "Created": "12/22/2005 02:06 PM", - "Creator": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed", - "Modified": "12/22/2005 02:08 PM", - "Modifier": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed", - "ID": "88e476d3-7526-45f5-a0dd-706c8053a63f", - "UserSkillID": "47a4ee94-b0e9-41b5-afe5-4b4f2c981877", - "UserID": "1d859264-3f32-462a-9b0c-a67dddfdf4d3" - } - ], - "Notes": "", - "VendorID": "06e502c2-69ba-4e88-8efb-5b53c1687740", - * "RegionID": "f856423a-d468-4344-b7b8-121e466738c6", - * "DispatchZoneID": "00000000-0000-0000-0000-000000000000", - "SubContractor": false,//This is not actually a feature in v7, you can just pick a vendorId for subcontractor but still be of type technician - "DefaultWarehouseID": "d45eab37-b6e6-4ad2-9163-66d7ba83a98c", - "Custom1": "", - "Custom2": "", - "Custom3": "", - "Custom4": "", - "Custom5": "", - "Custom6": "", - "Custom7": "", - "Custom8": "", - "Custom9": "", - "Custom0": "", - "ScheduleBackColor": -2097216, - "TimeZoneOffset": null - } - */ - - #endregion v7 record format - - SeedOrImportRelaxedRulesMode = true; - - //some types need to import from more than one source hence the seemingly redundant switch statement for futureproofing - switch (j["IMPORT_TASK"].Value()) - { - case "main": - { - #region Main import - var V7Id = new Guid(j["ID"].Value()); - - //skip the administrator account but add it to the map for all the other import code that requires it - if (V7Id == new Guid("2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed")) - { - var mapItem = new ImportAyaNova7MapItem(V7Id, BizType, 1); - importMap.Add(mapItem); - return true; - } - - //Copy values - User i = new User(); - - - i.Name = j["FirstName"].Value() + " " + j["LastName"].Value(); - var Temp = j["UserType"].Value(); - i.UserType = (UserType)Temp; - - //If there is a vendorId set then this user is actually a subcontractor in v7 so set accordingly - var VendorId = new Guid(j["VendorID"].Value()); - if (VendorId != Guid.Empty) - { - i.UserType = UserType.Subcontractor; - } - - i.Active = false;//Ignore incoming value and set all imports to false so that there's no chance of licensing getting circumvented; users all need to be edited anyway for pw and login - i.EmployeeNumber = j["EmployeeNumber"].Value(); - i.Notes = j["Notes"].Value(); - - //TAGS - //member of group is actually security group not sched user group so this was wrong anyway but moot now - // var MemberOfGroupId = new Guid(j["MemberOfGroup"].Value()); - // if (MemberOfGroupId != Guid.Empty) - // { - // string sTag = string.Empty; - // if (tagLists["ScheduleableUserGroup"].TryGetValue(MemberOfGroupId, out sTag)) - // { - // i.Tags.Add(sTag); - // } - // } - - var RegionID = new Guid(j["RegionID"].Value()); - if (RegionID != Guid.Empty) - { - string sTag = string.Empty; - if (tagLists["Region"].TryGetValue(RegionID, out sTag)) - { - i.Tags.Add(sTag); - } - } - - var DispatchZoneID = new Guid(j["DispatchZoneID"].Value()); - if (DispatchZoneID != Guid.Empty) - { - string sTag = string.Empty; - if (tagLists["DispatchZone"].TryGetValue(DispatchZoneID, out sTag)) - { - i.Tags.Add(sTag); - } - } - - //User options - i.UserOptions = new UserOptions(); - - //TimeZone Offset - //NOT IMPORTED / SUPPORTED - - - //Email address - i.UserOptions.EmailAddress = j["EmailAddress"].Value(); - - //UI colour - //TODO: this needs to be tested now that it's a web friendly value in the dbdump file - /* - Hexadecimal notation: #RGB[A] - R (red), G (green), B (blue), and A (alpha) are hexadecimal characters (0–9, A–F). A is optional. The three-digit notation (#RGB) is a shorter version of the six-digit form (#RRGGBB). For example, #f09 is the same color as #ff0099. Likewise, the four-digit RGB notation (#RGBA) is a shorter version of the eight-digit form (#RRGGBBAA). For example, #0f38 is the same color as #00ff3388. - */ - // This is untested as of now, but should work, maybe if it doesn't the selector needs to be combined with dot notation instead of two array notations? - i.UserOptions.UiColor = j["jextra"]["hexaScheduleBackColor"].Value(); - - - //Set unusable random login credentials - i.Salt = Hasher.GenerateSalt(); - i.Login = Hasher.GenerateSalt(); - i.Password = Hasher.hash(i.Salt, Hasher.GenerateSalt()); - - //No rights - i.Roles = AuthorizationRoles.NoRole; - - //temporary translation id to satisfy db settings - i.UserOptions.TranslationId = ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID; - - User o = await CreateAsync(i); - if (HasErrors) - { - //If there are any validation errors, log in joblog and move on - await JobsBiz.LogJobAsync(jobId, $" -> import object \"{i.Name}\" source id {V7Id.ToString()} failed validation and was not imported: {GetErrorsAsString()} ", ct); - - //This is a fundamental problem with the import as users are required for many things so bomb out entirely - //other things might be able to work around but this is too serious - throw new System.SystemException("UserBiz::ImportV7Async - FATAL ERROR, IMPORT FROM V7 CANNOT CONTINUE WITHOUT ALL USERS BEING IMPORTED, SEE JOB ERROR LOG FOR DETAILS"); - // return false; - } - else - { - await ct.SaveChangesAsync(); - var mapItem = new ImportAyaNova7MapItem(V7Id, BizType, o.Id); - importMap.Add(mapItem); - - - } - #endregion - } - break; - case "eventlog": - { - await ImportAyaNova7Biz.LogEventCreatedModifiedEventsAsync(j, importMap, BizType, ct); - } - break; - case "translation": - { - #region set translation - //get the userId - //---- - var V7Id = new Guid(j["ID"].Value()); - var MapItem = importMap.Where(m => m.V7ObjectId == V7Id).FirstOrDefault(); - if (MapItem == null) - { - throw new System.Exception("UserBiz::ImportV7Async-translation - FATAL ERROR, IMPORT FROM V7 CANNOT CONTINUE USER NOT FOUND IN IMPORTMAP"); - } - var NewId = MapItem.NewObjectAyaTypeId.ObjectId; - User u = ct.User.Where(m => m.Id == NewId).FirstOrDefault(); - if (u == null) - { - throw new System.Exception("UserBiz::ImportV7Async-translation - FATAL ERROR, IMPORT FROM V7 CANNOT CONTINUE USER NOT FOUND IN DATABASE"); - } - - //handle translation entries for users now that we have the Translations created - var V7Translation = j["DefaultLanguage"].Value(); - - //Get new translation name - var NewTranslationName = string.Empty; - switch (V7Translation) - { - case "Français": - NewTranslationName = "fr"; - break; - case "Español": - NewTranslationName = "es"; - break; - case "Deutsch": - NewTranslationName = "de"; - break; - case "English": - NewTranslationName = "en"; - break; - default: - { - //It's a custom translation, translate it from v7 original format to imported name format - //make lower and replace spaces with dashes - NewTranslationName = V7Translation.ToLowerInvariant().Replace(" ", "-"); - - //ensure each character is a valid path character - foreach (char c in System.IO.Path.GetInvalidFileNameChars())//is this kosher on linux? Original code was windows - { - NewTranslationName = NewTranslationName.Replace(c, '_'); - } - } - break; - } - - u.UserOptions.TranslationId = await TranslationBiz.TranslationNameToIdStaticAsync(NewTranslationName, ct); - - ct.SaveChanges(); - #endregion set translation - } - break; - - case "clientid": - { - var V7Id = new Guid(j["ID"].Value()); - //handle setting client id for user client login - //throw new System.NotImplementedException(); - } - break; - case "headofficeid": - { - var V7Id = new Guid(j["ID"].Value()); - //handle setting ho id for user headoffice login - //throw new System.NotImplementedException(); - } - break; - } - - - //this is the equivalent of returning void for a Task signature with nothing to return - return true; - - } - - - //Other job handlers here... diff --git a/server/AyaNova/models/dto/ImportV7MapItem.cs b/server/AyaNova/models/dto/ImportV7MapItem.cs deleted file mode 100644 index ddbc8323..00000000 --- a/server/AyaNova/models/dto/ImportV7MapItem.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using AyaNova.Biz; -namespace AyaNova.Models -{ - - /// - /// Provides mapping during import - /// - public partial class ImportAyaNova7MapItem - { - public AyaTypeId NewObjectAyaTypeId { get; set; } - public Guid V7ObjectId { get; set; } - - public ImportAyaNova7MapItem(Guid v7Guid, AyaType ayaType, long newId) - { - NewObjectAyaTypeId = new AyaTypeId(ayaType, newId); - V7ObjectId = v7Guid; - } - } - -} diff --git a/server/AyaNova/util/DbUtil.cs b/server/AyaNova/util/DbUtil.cs index b4bef3ee..3dc3f85e 100644 --- a/server/AyaNova/util/DbUtil.cs +++ b/server/AyaNova/util/DbUtil.cs @@ -336,8 +336,7 @@ namespace AyaNova.Util /////////////////////////////////////////// // Check if DB is empty - // CALLED BY LICENSE CONTROLLER AND LICENSE.CS FOR TRIAL Request check - // Also called by Import + // CALLED BY LICENSE CONTROLLER AND LICENSE.CS FOR TRIAL Request check internal static async Task DBIsEmptyAsync(AyContext ct, ILogger _log) { //TODO: This needs to be way more thorough, only the main tables though, no need to get crazy with it diff --git a/server/AyaNova/util/FileUtil.cs b/server/AyaNova/util/FileUtil.cs index ced5213a..42abd20a 100644 --- a/server/AyaNova/util/FileUtil.cs +++ b/server/AyaNova/util/FileUtil.cs @@ -188,40 +188,40 @@ namespace AyaNova.Util return zipEntries; } - /// - /// Import utility - get individual files specified in zip archive as JSON objects - /// - /// - /// Name of utility zip import file - /// Name of entries in utility file archive to fetch - /// - internal static List ZipGetUtilityArchiveEntriesAsJsonObjects(List entryList, string zipFileName) - { - List jList = new List(); - var zipPath = GetFullPathForUtilityFile(zipFileName); - using (ZipArchive archive = ZipFile.OpenRead(zipPath)) - { - foreach (string importFileName in entryList) - { - ZipArchiveEntry entry = archive.GetEntry(importFileName); - if (entry != null) - { - //stream entry into a new jobject and add it to the list - StreamReader reader = new StreamReader(entry.Open()); - string text = reader.ReadToEnd(); - var j = JObject.Parse(text); + // /// + // /// Import utility - get individual files specified in zip archive as JSON objects + // /// + // /// + // /// Name of utility zip import file + // /// Name of entries in utility file archive to fetch + // /// + // internal static List ZipGetUtilityArchiveEntriesAsJsonObjects(List entryList, string zipFileName) + // { + // List jList = new List(); + // var zipPath = GetFullPathForUtilityFile(zipFileName); + // using (ZipArchive archive = ZipFile.OpenRead(zipPath)) + // { + // foreach (string importFileName in entryList) + // { + // ZipArchiveEntry entry = archive.GetEntry(importFileName); + // if (entry != null) + // { + // //stream entry into a new jobject and add it to the list + // StreamReader reader = new StreamReader(entry.Open()); + // string text = reader.ReadToEnd(); + // var j = JObject.Parse(text); - //Here add v7 import file name as sometimes it's needed later (Translations) - j.Add("V7_SOURCE_FILE_NAME", JToken.FromObject(importFileName)); - jList.Add(j); - } - } + // //Here add v7 import file name as sometimes it's needed later (Translations) + // j.Add("V7_SOURCE_FILE_NAME", JToken.FromObject(importFileName)); + // jList.Add(j); + // } + // } - } + // } - return jList; + // return jList; - } + // } #endregion Zip handling