diff --git a/source/Plugins/AyaNova.Plugin.V8/V8.cs b/source/Plugins/AyaNova.Plugin.V8/V8.cs index 422938b..31a5868 100644 --- a/source/Plugins/AyaNova.Plugin.V8/V8.cs +++ b/source/Plugins/AyaNova.Plugin.V8/V8.cs @@ -192,14 +192,14 @@ namespace AyaNova.PlugIn.V8 return Map[id]; } - private enum RavenUserType : int - { - Service = 1, - NotService = 2, - Customer = 3, - HeadOffice = 4, - ServiceContractor = 5 - } + private enum RavenUserType : int + { + Service = 1, + NotService = 2, + Customer = 3, + HeadOffice = 4, + ServiceContractor = 5 + } private Dictionary TagMap = new Dictionary(); private Dictionary LocaleMap = new Dictionary(); @@ -295,7 +295,7 @@ namespace AyaNova.PlugIn.V8 progress.Op("Exporting Business objects"); //BIZ objects await ExportLocales(progress); - await ExportUsers(progress); + await ExportStaffUsers(progress); await ExportClients(progress); await ExportHeadOffices(progress); await ExportContracts(progress); @@ -306,6 +306,7 @@ namespace AyaNova.PlugIn.V8 await ExportUnits(progress); await ExportUnitModels(progress); await ExportVendors(progress); + await ExportExternalUsers(progress);//needs vendors, clients and headoffices already exported so needs to be here late await ExportServiceWorkorders(progress); //todo: these are now invalid and awaiting RAVEN end implementation //after which can copy mostly from service workorder block @@ -375,10 +376,11 @@ namespace AyaNova.PlugIn.V8 } #region users - private async System.Threading.Tasks.Task ExportUsers(ProgressForm progress) + + private async System.Threading.Tasks.Task ExportStaffUsers(ProgressForm progress) { if (!progress.KeepGoing) return; - progress.Op("Start User export"); + progress.Op("Start internal (staff) User export"); progress.SubOp(""); ResetUniqueNames(); @@ -422,7 +424,7 @@ namespace AyaNova.PlugIn.V8 //yes, so fetch it and modify it and put it back again var a = await util.GetAsync("user/1"); dynamic d = a.ObjectResponse["data"]; - d.id=1; + d.id = 1; d.wiki = AdminWikiContent; d.customFields = CustomFieldData(admin, DateCustomFields); await util.PutAsync("user", d.ToString()); @@ -437,6 +439,8 @@ namespace AyaNova.PlugIn.V8 foreach (UserPickList.UserPickListInfo i in pl) { if (!progress.KeepGoing) return; + + List tags = new List(); tags.Add(ImportTag); @@ -446,6 +450,168 @@ namespace AyaNova.PlugIn.V8 User c = User.GetItem(i.ID); + //skip any external users + if (i.Type == UserTypes.Client || i.Type == UserTypes.HeadOffice || c.VendorID != Guid.Empty) + continue; + + var ObjectTID = new TypeAndID(RootObjectTypes.User, c.ID); + + dynamic d = new JObject(); + d.name = GetUniqueName(c.FirstName + " " + c.LastName); + if (IsDuplicateMapItem(c.ID, c.FirstName + " " + c.LastName, progress)) continue; + progress.Op("User " + d.name); + //throw new System.Exception("TODO: UserTypes sb done differently now to align"); + //TODO: User type + //d.userType = (int)c.UserType; + + //todo: this needs to be adjusted later + //after vendor, customer and headoffice objects are all exported + //then loop through all users again here and set them accordingly if required + + //RAVEN user types are different numbers so even the regular ones need to be set alternatively + switch (c.UserType) + { + case UserTypes.Administrator: + d.userType = 2; + break; + case UserTypes.NonSchedulable: + d.userType = 2; + break; + case UserTypes.Schedulable: + d.userType = 1; + break; + } + + + + d.active = false;//all imported users are inactive to start + d.roles = 0;//todo: try to determine role from v7 member of group? or is that even possible? + d.login = util.RandomString(); + d.password = util.RandomString(); + + d.employeeNumber = c.EmployeeNumber; + d.notes = c.Notes; + Tagit(c.RegionID, tags); + Tagit(c.DispatchZoneID, tags); + foreach (UserSkillAssigned skill in c.UserSkills) + { + Tagit(skill.UserSkillID, tags); + } + foreach (UserCertificationAssigned cert in c.UserCertifications) + { + Tagit(cert.UserCertificationID, tags); + } + SetTags(d, tags); + + //Custom fields? + if (ShouldExportCustom) + d.customFields = CustomFieldData(c, DateCustomFields); + + var rMainObject = await util.PostAsync("user", d.ToString()); + long RavenId = util.IdFromResponse(rMainObject); + AddMap(c.ID, RavenId); + + //USER OPTIONS + if (c.ScheduleBackColor != 0 || !string.IsNullOrWhiteSpace(c.EmailAddress)) + { + var rOptions = await util.GetAsync("user-option/" + RavenId.ToString()); + d = rOptions.ObjectResponse["data"]; + d.uiColor = System.Drawing.ColorTranslator.ToHtml(System.Drawing.Color.FromArgb(c.ScheduleBackColor)); + d.emailAddress = string.IsNullOrWhiteSpace(c.EmailAddress) ? null : c.EmailAddress; + if (LocaleMap.ContainsKey(c.DefaultLanguage)) + d.translationId = LocaleMap[c.DefaultLanguage]; + else + d.translationId = 1; + + await util.PutAsync("user-option/" + RavenId.ToString(), d.ToString()); + } + + //Attachments / FILES + await ExportAttachments(ObjectTID, progress); + + //----- + bool repost = false; + d = rMainObject.ObjectResponse["data"]; + // wiki + if (WikiPage.HasWiki(c.ID)) + { + // await ExportAttachments(ObjectTID, progress); + d.wiki = GetWikiContent(ObjectTID); + repost = true; + } + + //docs + string NonFileUrls = await ExportDocs(ObjectTID, c.Docs, progress); + if (!string.IsNullOrEmpty(NonFileUrls)) + { + //need to repost the user with the notes modified + + d.login = null; + d.password = null; + d.notes = NonFileUrls + "\n-----------------\n" + d.notes; + repost = true; + } + if (repost) + await util.PutAsync("user", d.ToString()); + //----- + + } + + + //## NOT ALL USERS YET, SO ONLY CALL THIS WHEN THE EXTERNAL USERS LATER ARE EXPORTED + ////EVENT LOG + ////Because this is the User's we need to do the event log *after* they have all been posted as event log requires all user's id + //foreach (UserPickList.UserPickListInfo i in pl) + //{ + // if (!progress.KeepGoing) return; + // User c = User.GetItem(i.ID); + // var newId = Map[c.ID]; + // var creator = SafeGetUserMap(c.Creator); + // var modifier = SafeGetUserMap(c.Modifier); + + // await util.EventLog(util.AyaType.User, newId, creator, modifier, c.Created, c.Modified); + //} + + } + + private async System.Threading.Tasks.Task ExportExternalUsers(ProgressForm progress) + { + if (!progress.KeepGoing) return; + progress.Op("Start external User export"); + progress.SubOp(""); + ResetUniqueNames(); + + //Step 1: export the CustomFields to FormCustom if applicable so that when doing individual items we can export their custom data too + var ocf = ObjectHasCustomFieldDataToExport("User"); + bool ShouldExportCustom = ocf != null; + + var DateCustomFields = await ExportCustomFieldSchema(ocf, "User", "User"); + + //Step 2: export the objects + + UserPickList pl = UserPickList.GetList(false); + progress.Append("Exporting " + pl.Count.ToString() + " Users"); + + + + foreach (UserPickList.UserPickListInfo i in pl) + { + if (!progress.KeepGoing) return; + + + List tags = new List(); + tags.Add(ImportTag); + + //skip administrator user fields + //but do export administrator + if (i.ID == User.AdministratorID) continue; + + User c = User.GetItem(i.ID); + + //skip any internal or non subcontractor Users + if (c.VendorID == Guid.Empty && (i.Type == UserTypes.Administrator || i.Type == UserTypes.NonSchedulable + || i.Type == UserTypes.Schedulable || i.Type == UserTypes.Utility)) + continue; var ObjectTID = new TypeAndID(RootObjectTypes.User, c.ID); @@ -483,6 +649,17 @@ namespace AyaNova.PlugIn.V8 if (c.VendorID != Guid.Empty) { d.userType = 2; + d.vendorId = Map[c.VendorID]; + } + + if (c.ClientID != Guid.Empty) + { + d.customerId = Map[c.ClientID]; + } + + if (c.HeadOfficeID != Guid.Empty) + { + d.headOfficeId = Map[c.HeadOfficeID]; } @@ -547,7 +724,7 @@ namespace AyaNova.PlugIn.V8 if (!string.IsNullOrEmpty(NonFileUrls)) { //need to repost the user with the notes modified - + d.login = null; d.password = null; d.notes = NonFileUrls + "\n-----------------\n" + d.notes; @@ -574,6 +751,8 @@ namespace AyaNova.PlugIn.V8 } } + + #endregion users #region Clients @@ -601,51 +780,51 @@ namespace AyaNova.PlugIn.V8 Client c = Client.GetItem(i.ID); var ObjectTID = new TypeAndID(RootObjectTypes.Client, c.ID); -/*v8 -## route [Route("api/v{version:apiVersion}/customer")] -## object format -[ - { - "Id": 100, - "Concurrency": 90525, - "Name": "Parker - Kling 321", - "Active": true, - "Notes": "Cross-group system-worthy installation", - "Wiki": null, - "CustomFields": null, - "Tags": [ - "red" - ], - "WebAddress": "http://esther.name", - "PopUpNotes": null, - "BillHeadOffice": false, - "HeadOfficeID": null, - "TechNotes": null, - "AccountNumber": "31070722", - "UsesBanking": false, - "ContractID": null, - "ContractExpires": null, - "DefaultServiceTemplateID": null, - "Phone1": "(651) 496-8691", - "Phone2": "919.303.4097 x10230", - "Phone3": "1-829-391-7162", - "Phone4": null, - "Phone5": null, - "EmailAddress": "Domingo.White@example.net", - "PostAddress": null, - "PostCity": null, - "PostRegion": null, - "PostCountry": null, - "PostCode": null, - "Address": "470 Conroy Island", - "City": "Lake Ambrose", - "Region": "Massachusetts", - "Country": "Argentina", - "Latitude": -60.473000, - "Longitude": 25.380100 - } -] -*/ + /*v8 + ## route [Route("api/v{version:apiVersion}/customer")] + ## object format + [ + { + "Id": 100, + "Concurrency": 90525, + "Name": "Parker - Kling 321", + "Active": true, + "Notes": "Cross-group system-worthy installation", + "Wiki": null, + "CustomFields": null, + "Tags": [ + "red" + ], + "WebAddress": "http://esther.name", + "PopUpNotes": null, + "BillHeadOffice": false, + "HeadOfficeID": null, + "TechNotes": null, + "AccountNumber": "31070722", + "UsesBanking": false, + "ContractID": null, + "ContractExpires": null, + "DefaultServiceTemplateID": null, + "Phone1": "(651) 496-8691", + "Phone2": "919.303.4097 x10230", + "Phone3": "1-829-391-7162", + "Phone4": null, + "Phone5": null, + "EmailAddress": "Domingo.White@example.net", + "PostAddress": null, + "PostCity": null, + "PostRegion": null, + "PostCountry": null, + "PostCode": null, + "Address": "470 Conroy Island", + "City": "Lake Ambrose", + "Region": "Massachusetts", + "Country": "Argentina", + "Latitude": -60.473000, + "Longitude": 25.380100 + } + ] + */ dynamic d = new JObject(); d.name = GetUniqueName(c.Name); if (IsDuplicateMapItem(c.ID, c.Name, progress)) continue; @@ -798,7 +977,7 @@ namespace AyaNova.PlugIn.V8 ClientNotes cnl = ClientNotes.GetItems(c.ID); foreach (ClientNote cn in cnl) { - tags.Clear(); + tags.Clear(); d = new JObject(); d.customerId = RavenId; d.userId = SafeGetUserMap(cn.Creator); @@ -813,8 +992,8 @@ namespace AyaNova.PlugIn.V8 } } } - - + + #endregion Clients #region Headoffices @@ -1918,26 +2097,26 @@ namespace AyaNova.PlugIn.V8 progress.SubOp(""); progress.Op("Exporting " + i.Locale + " to " + exportName); - // var t = new util.NameIdItem { Name = exportName, Id = x }; - a = await util.PostAsync("translation/duplicate/"+ x.ToString()); + // var t = new util.NameIdItem { Name = exportName, Id = x }; + a = await util.PostAsync("translation/duplicate/" + x.ToString()); var targetTranslationId = util.IdFromResponse(a); - // var ctoken = util.CTokenFromResponse(a); + // var ctoken = util.CTokenFromResponse(a); //now set the name dynamic dTransName = new JObject(); - dTransName.id=a.ObjectResponse["data"]["id"]; + dTransName.id = a.ObjectResponse["data"]["id"]; dTransName.concurrency = a.ObjectResponse["data"]["concurrency"]; - dTransName.name=exportName; - dTransName.stock=false; + dTransName.name = exportName; + dTransName.stock = false; dTransName.cjkIndex = a.ObjectResponse["data"]["cjkIndex"]; - var vtemp=await util.PutAsync("translation", dTransName.ToString()); - // vtemp["data"]["concurrency"] - var ctoken = util.CTokenFromResponse(vtemp); - // "id": 5, - //"concurrency": 92149, - //"name": "en-1", - //"stock": false, - //"cjkIndex": false, + var vtemp = await util.PutAsync("translation", dTransName.ToString()); + // vtemp["data"]["concurrency"] + var ctoken = util.CTokenFromResponse(vtemp); + // "id": 5, + //"concurrency": 92149, + //"name": "en-1", + //"stock": false, + //"cjkIndex": false, //add to maps so can set user to it on export //going to default to the English based one because