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(); JobsBiz.UpdateJobStatus(job.GId, JobStatus.Running, ct); JobsBiz.LogJob(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"); } //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 //for example scheduleable user groups are imported as tags, but then a second pass is required to tag the users of that group //USERS await DoImport("GZTW.AyaNova.BLL.User", "main", AyaType.User, job.GId, importMap, importFileName, zipEntries); //Now can do event log entries await DoImport("GZTW.AyaNova.BLL.User", "eventlog", AyaType.User, job.GId, importMap, importFileName, zipEntries); //IMPORT UNIT MODEL CATEGORIES AS TAGS await DoImport("GZTW.AyaNova.BLL.UnitModelCategory", "main", AyaType.Tag, job.GId, importMap, importFileName, zipEntries); //IMPORT Unit service type AS TAGS await DoImport("GZTW.AyaNova.BLL.UnitServiceType", "main", AyaType.Tag, job.GId, importMap, importFileName, zipEntries); //IMPORT Workorder Item Type AS TAGS await DoImport("GZTW.AyaNova.BLL.WorkorderItemType", "main", AyaType.Tag, job.GId, importMap, importFileName, zipEntries); //IMPORT Client group AS TAGS await DoImport("GZTW.AyaNova.BLL.ClientGroup", "main", AyaType.Tag, job.GId, importMap, importFileName, zipEntries); //IMPORT Workorder category AS TAGS await DoImport("GZTW.AyaNova.BLL.WorkorderCategory", "main", AyaType.Tag, job.GId, importMap, importFileName, zipEntries); //IMPORT Part Category AS TAGS await DoImport("GZTW.AyaNova.BLL.PartCategory", "main", AyaType.Tag, job.GId, importMap, importFileName, zipEntries); //IMPORT Dispatch zones AS TAGS await DoImport("GZTW.AyaNova.BLL.DispatchZone", "main", AyaType.Tag, job.GId, importMap, importFileName, zipEntries); //IMPORT Scheduleable User Groups AS TAGS await DoImport("GZTW.AyaNova.BLL.ScheduleableUserGroup", "main", AyaType.Tag, job.GId, importMap, importFileName, zipEntries); //Now can set users to correct tag for scheduleable user group await DoImport("GZTW.AyaNova.BLL.ScheduleableUserGroup", "scheduleableusergrouptags", AyaType.Tag, job.GId, importMap, importFileName, zipEntries); //IMPORT REGIONS AS TAGS await DoImport("GZTW.AyaNova.BLL.Region", "main", AyaType.Tag, job.GId, importMap, importFileName, zipEntries); //IMPORT LOCALES await DoImport("GZTW.AyaNova.BLL.Locale", "main", AyaType.Locale, job.GId, importMap, importFileName, zipEntries); //Now can do user locale settings properly await DoImport("GZTW.AyaNova.BLL.User", "locale", AyaType.User, job.GId, importMap, importFileName, zipEntries); //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); //---------------- JobsBiz.LogJob(job.GId, "ImportAyaNova7 finished", ct); JobsBiz.UpdateJobStatus(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 DoImport(string entryStartsWith, string importTask, AyaType importerType, Guid jobId, List importMap, string importFileName, List zipEntries) { var zipObjectList = zipEntries.Where(m => m.StartsWith(entryStartsWith)).ToList(); long importCount = 0; long notImportCount = 0; if (zipObjectList.Count > 0) { if (importTask != "main") { JobsBiz.LogJob(jobId, $"Starting import sub-task {importTask} of {entryStartsWith} objects", ct); } else { JobsBiz.LogJob(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); if (bImportSucceeded) importCount++; else notImportCount++; } if (importCount > 0) { if (importTask != "main") { JobsBiz.LogJob(jobId, $"Successfully ran import subtask {importTask} on {importCount.ToString()} of {zipObjectList.Count.ToString()} {entryStartsWith} objects", ct); } else { JobsBiz.LogJob(jobId, $"Successfully imported {importCount.ToString()} of {zipObjectList.Count.ToString()} {entryStartsWith} objects", ct); } } if (notImportCount > 0) { if (importTask != "main") { JobsBiz.LogJob(jobId, $"Failed to run import subtask {importTask} on {notImportCount.ToString()} of {zipObjectList.Count.ToString()} {entryStartsWith} objects", ct); } else { JobsBiz.LogJob(jobId, $"Did not import {notImportCount.ToString()} of {zipObjectList.Count.ToString()} {entryStartsWith} objects", ct); } } } } //Other job handlers here... ////////////////////////////////////////////////////////////////// //UTILITIES internal static void LogEventCreatedModifiedEvents(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 EventLogProcessor.LogEventToDatabase(new Event(Creator, RavenId, ayaType, AyaEvent.Created, Created), ct); //MODIFIED EventLogProcessor.LogEventToDatabase(new Event(Modifier, RavenId, ayaType, AyaEvent.Modified, Modified), ct); } ///////////////////////////////////////////////////////////////////// }//eoc }//eons