974 lines
38 KiB
C#
974 lines
38 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.ComponentModel;
|
|
using System.Windows.Forms;
|
|
using System.Reflection;
|
|
using AyaNova.PlugIn;
|
|
using GZTW.AyaNova.BLL;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Serialization;
|
|
using Newtonsoft.Json.Linq;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
|
|
|
|
namespace AyaNova.PlugIn.V8
|
|
{
|
|
class V8 : IAyaNovaPlugin
|
|
{
|
|
|
|
#region Plugin interface
|
|
System.Resources.ResourceManager resman = null;
|
|
private static List<RootObjectTypes> ObjectsWeCanDealWith = null;
|
|
|
|
|
|
public string PluginName
|
|
{
|
|
get { return "Export to V8"; }
|
|
}
|
|
|
|
public string PluginVersion
|
|
{
|
|
get { return "7.6 (patch 3)"; }
|
|
}
|
|
|
|
public string About
|
|
{
|
|
get
|
|
{
|
|
return "AyaNova V8 export plugin\r\n" +
|
|
"Built " + AyaNova.PlugIn.V8.Timestamp.BuildAt.ToString() + "\r\n" +
|
|
"Copyright 2020 Ground Zero Tech-Works Inc.";
|
|
}
|
|
}
|
|
|
|
public Guid PluginID
|
|
{
|
|
get { return new Guid("{73D7B77F-C96A-4198-9449-6529AFB6AA5B}"); }
|
|
}
|
|
|
|
public System.Drawing.Image PluginSmallIcon
|
|
{
|
|
get { return Resource1.Dump16; }
|
|
}
|
|
|
|
public System.Drawing.Image PluginLargeIcon
|
|
{
|
|
get { return Resource1.Dump32; }
|
|
}
|
|
|
|
public System.Resources.ResourceManager AyaNovaResourceManager
|
|
{
|
|
set { resman = value; }
|
|
get { return resman; }
|
|
}
|
|
|
|
public bool Initialize(Version AyaNovaVersion, LocalizedTextTable localizedText)
|
|
{
|
|
if (AyaNovaVersion.Major < 7)
|
|
{
|
|
MessageBox.Show("The V8 export plugin requires AyaNova version 7.6 or newer");
|
|
return false;
|
|
}
|
|
|
|
if (AyaNovaVersion.Minor < 6)
|
|
{
|
|
MessageBox.Show("The V8 export plugin requires AyaNova version 7.6 or newer");
|
|
return false;
|
|
}
|
|
|
|
util.LocaleText = localizedText;
|
|
|
|
ObjectsWeCanDealWith = new List<RootObjectTypes>();
|
|
ObjectsWeCanDealWith.Add(RootObjectTypes.Nothing);
|
|
return true;
|
|
}
|
|
|
|
public void Close()
|
|
{
|
|
;
|
|
}
|
|
|
|
public bool SingleObjectMenuShow(RootObjectTypes objectType)
|
|
{
|
|
return (ObjectsWeCanDealWith.Contains(objectType));
|
|
}
|
|
|
|
public bool MultipleObjectsMenuShow(RootObjectTypes objectType)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public List<AyaNovaPluginMenuItem> SingleObjectMenuOptions(RootObjectTypes objectType, object ayaNovaObject)
|
|
{
|
|
if (!ObjectsWeCanDealWith.Contains(objectType)) return null;
|
|
List<AyaNovaPluginMenuItem> list = new List<AyaNovaPluginMenuItem>();
|
|
list.Add(new AyaNovaPluginMenuItem("V8 Export", "Export to AyaNova 8 server", null, null));
|
|
return list;
|
|
}
|
|
|
|
public List<AyaNovaPluginMenuItem> MultipleObjectsMenuOptions(RootObjectTypes objectType)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public bool CommandSelectedForList(string commandKey, RootObjectTypes objectType, List<Guid> objectIDList, object listObject)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public void CommandSelectedForSingleObject(string commandKey, RootObjectTypes objectType, object ayaNovaObject)
|
|
{
|
|
|
|
if (!User.CurrentUserIsAnAdministrator)
|
|
{
|
|
MessageBox.Show("This action can only be done by the AyaNova Administrator account");
|
|
return;
|
|
}
|
|
|
|
#if(!DEBUG)
|
|
if (!AyaBizUtils.AyaNovaConnectionSetting.SingleUserConnection)
|
|
{
|
|
MessageBox.Show("** WARNING: before proceeding ensure no other users are logged into AyaNova to ensure the integrity of your exported data. Failing to do so *will* result in damaged data. ***");
|
|
MessageBox.Show("** WARNING: before proceeding make sure your AyaNova Generator service is STOPPED to ensure the integrity of your exported data. Failing to do so *will* result in damaged data. ***");
|
|
}
|
|
#endif
|
|
|
|
Auth d = new Auth();
|
|
var res = d.ShowDialog(); ;
|
|
if (res == DialogResult.Cancel)
|
|
{
|
|
return;
|
|
}
|
|
//here because we logged in fine and can proceed
|
|
|
|
//MessageBox.Show("Login successful! JWT is " + util.JWT);
|
|
//Only one command
|
|
DoExport();
|
|
}
|
|
|
|
#endregion
|
|
|
|
private Dictionary<Guid, long> Map = new Dictionary<Guid, long>();
|
|
private Dictionary<Guid, string> TagMap = new Dictionary<Guid, string>();
|
|
private Dictionary<string, string> CustomFieldLocaleKeys = new Dictionary<string, string>();//holds custom field Raven as key and v7 custom text for that field for later export
|
|
private string ImportTag = "v7-import";
|
|
/// <summary>
|
|
/// Dump the objects into a temporary directory as a series of JSON files
|
|
/// then zip it all up into a single archive file and then erase the temporary folder
|
|
/// </summary>
|
|
private async void DoExport()
|
|
{
|
|
//Show progress form
|
|
ProgressForm progress = new ProgressForm();
|
|
progress.Show();
|
|
progress.StartedImport();
|
|
progress.Append("Exporting data to AyaNova server @ " + util.ApiBaseUrl);
|
|
try
|
|
{
|
|
Map.Clear();
|
|
TagMap.Clear();
|
|
CustomFieldLocaleKeys.Clear();
|
|
|
|
//admin user (not exported but is there already)
|
|
Map.Add(User.AdministratorID, 1);
|
|
//not sure if this is a good idea or not because in some cases would want to know if something is unexpectedly empty but will see for now
|
|
//Map.Add(Guid.Empty, 0);
|
|
|
|
/*
|
|
TODO:
|
|
* wiki / attached docs
|
|
*
|
|
* locales
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
|
|
//Export in correct order:
|
|
|
|
//ERASE DB
|
|
var a = await util.PostAsync("License/PermanentlyEraseAllData", "\"I understand\"");
|
|
if (!a.HttpResponse.IsSuccessStatusCode) { MessageBox.Show("Error erasing database: \n" + a.HttpResponse.ReasonPhrase); return; }
|
|
|
|
//TAGS
|
|
ExportUnitModelCategories(progress);
|
|
ExportUnitServiceTypes(progress);
|
|
ExportWorkorderItemTypes(progress);
|
|
ExportRegions(progress);
|
|
ExportClientGroups(progress);
|
|
ExportWorkorderCategories(progress);
|
|
ExportPartCategories(progress);
|
|
ExportScheduleableUserGroups(progress);
|
|
ExportDispatchZones(progress);
|
|
ExportUserSkills(progress);
|
|
ExportUserCertifications(progress);
|
|
|
|
//BIZ objects
|
|
await ExportUsers(progress);
|
|
// await ExportLocales(progress);
|
|
|
|
|
|
|
|
|
|
|
|
//dumpGlobalSettings(tempArchiveFolder, progress);
|
|
|
|
//dumpSeedNumbers(tempArchiveFolder, progress);
|
|
//dumpClients(tempArchiveFolder, progress);
|
|
//dumpHeadOffices(tempArchiveFolder, progress);
|
|
//
|
|
|
|
|
|
//NOTE: when get to PRIORITY, or WORKORDER STATUS be sure to add color code as per already done in USER export
|
|
|
|
|
|
progress.Append("Export completed");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
progress.Append("\n************\nExport failed with error:");
|
|
progress.Append(ex.Message);
|
|
}
|
|
progress.FinishedImport();
|
|
|
|
//-----------------------------------
|
|
//endof method
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Object Export methods
|
|
|
|
#region Global settings
|
|
private void ExportGlobalSettings(ProgressForm progress)
|
|
{
|
|
|
|
progress.Append("STUB: Dumping Global Settings");
|
|
////DumpObjectToFolder(tempArchiveFolder, AyaBizUtils.GlobalSettings, "globalsettings", objectExcludeProperties, new TypeAndID(RootObjectTypes.Global, Address.GlobalAddressID));
|
|
}
|
|
#endregion globalsettings
|
|
|
|
#region locales
|
|
private void ExportLocales(ProgressForm progress)
|
|
{
|
|
// List<string> objectExcludeProperties = new List<string>(standardExcludePropertiesList);
|
|
|
|
//Skip stock locales already handled in Raven
|
|
List<string> SkipLocales = new List<string>();
|
|
SkipLocales.Add("Deutsch");
|
|
SkipLocales.Add("English");
|
|
SkipLocales.Add("Español");
|
|
SkipLocales.Add("Français");
|
|
|
|
LocaleList l = LocaleList.GetList();
|
|
progress.Append("Dumping " + l.Count.ToString() + " Locales");
|
|
foreach (LocaleList.LocaleListInfo i in l)
|
|
{
|
|
if (!SkipLocales.Contains(i.Locale))
|
|
{
|
|
LocalizedTextTable lt = LocalizedTextTable.Load(i.Locale);
|
|
//DumpObjectToFolder(tempArchiveFolder, lt.LT, "translation." + EnsureValidFileName(i.Locale), objectExcludeProperties, TypeAndID.Empty, "GZTW.AyaNova.BLL.Translation");
|
|
}
|
|
}
|
|
}
|
|
#endregion locales
|
|
|
|
#region Seeds
|
|
private class GZSeeds
|
|
{
|
|
public int InventoryAdjustmentStartSeed = 1;
|
|
public int PurchaseOrderStartSeed = 1;
|
|
public int QuoteNumberStartSeed = 1;
|
|
public int WorkorderNumberStartSeed = 1;
|
|
public int PreventiveMaintenanceNumberStartSeed = 1;
|
|
}
|
|
private void ExportSeedNumbers(ProgressForm progress)
|
|
{
|
|
// List<string> objectExcludeProperties = new List<string>(standardExcludePropertiesList);
|
|
progress.Append("Dumping seeds");
|
|
//create a new object with the id numbers in it and then dump it
|
|
WorkorderPMList pml = WorkorderPMList.GetList("<?xml version=\"1.0\" encoding=\"utf-16\" standalone=\"yes\"?> \r\n" +
|
|
"<GRIDCRITERIA> \r\n" +
|
|
" <COLUMNITEM CM=\"aWorkorderPreventiveMaintenance.aPreventiveMaintenanceNumber\" UI=\"LT_O_WorkorderPreventiveMaintenance\" PIN=\"0\" WIDTH=\"150\" SORT=\"DESC\" /> \r\n" +
|
|
"</GRIDCRITERIA> ");
|
|
|
|
int PMStartSeed = 0;
|
|
if (pml.Count > 0)
|
|
{
|
|
PMStartSeed = int.Parse(pml[0].LT_O_WorkorderPreventiveMaintenance.Display);
|
|
}
|
|
|
|
var seeds = new GZSeeds();
|
|
seeds.InventoryAdjustmentStartSeed = AyaBizUtils.GlobalSettings.InventoryAdjustmentStartSeed + 1;
|
|
seeds.PurchaseOrderStartSeed = AyaBizUtils.GlobalSettings.PurchaseOrderStartSeed + 1;
|
|
seeds.QuoteNumberStartSeed = AyaBizUtils.GlobalSettings.QuoteNumberStartSeed + 1;
|
|
seeds.WorkorderNumberStartSeed = AyaBizUtils.GlobalSettings.WorkorderNumberStartSeed + 1;
|
|
seeds.PreventiveMaintenanceNumberStartSeed = PMStartSeed + 1;
|
|
|
|
//DumpObjectToFolder(tempArchiveFolder, seeds, "seeds", objectExcludeProperties, TypeAndID.Empty, "GZTW.AyaNova.BLL.Seed");
|
|
}
|
|
#endregion globalsettings
|
|
|
|
#region clients
|
|
private void ExportClients(ProgressForm progress)
|
|
{
|
|
ClientPickList pl = ClientPickList.GetList();
|
|
progress.Append("Dumping " + pl.Count.ToString() + " Clients");
|
|
foreach (ClientPickList.ClientPickListInfo i in pl)
|
|
{
|
|
Client c = Client.GetItem(i.ID);
|
|
//DumpObjectToFolder(tempArchiveFolder, c, "client." + c.ID.ToString(), objectExcludeProperties, new TypeAndID(RootObjectTypes.Client, c.ID));
|
|
|
|
}
|
|
}
|
|
#endregion clients
|
|
|
|
#region headoffices
|
|
private void ExportHeadOffices(ProgressForm progress)
|
|
{
|
|
|
|
PickListAutoComplete pl = PickListAutoComplete.GetList("**", "headoffice");
|
|
|
|
progress.Append("Dumping " + pl.Count.ToString() + " Head offices");
|
|
foreach (PickListAutoComplete.PickListAutoCompleteInfo i in pl)
|
|
{
|
|
HeadOffice c = HeadOffice.GetItem(i.ID);
|
|
//DumpObjectToFolder(tempArchiveFolder, c, "headoffice." + c.ID.ToString(), excludes, new TypeAndID(RootObjectTypes.HeadOffice, c.ID));
|
|
}
|
|
}
|
|
#endregion clients
|
|
|
|
#region users
|
|
private async System.Threading.Tasks.Task ExportUsers(ProgressForm progress)
|
|
{
|
|
//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 users
|
|
|
|
|
|
UserPickList pl = UserPickList.GetList(false);
|
|
progress.Append("Exporting " + pl.Count.ToString() + " Users");
|
|
|
|
#region Export administrator wiki and attached files if present
|
|
User admin = User.GetItem(User.AdministratorID);
|
|
|
|
//wiki page
|
|
var adminWiki = GetWikiContent(new TypeAndID(RootObjectTypes.User, admin.ID));
|
|
string adminCustomFields = null;
|
|
//Custom fields?
|
|
if (ShouldExportCustom)
|
|
{
|
|
adminCustomFields = CustomFieldData(admin, DateCustomFields);
|
|
}
|
|
|
|
//check if we need to do anything with the manager account
|
|
if (adminWiki != null || adminCustomFields != null)
|
|
{
|
|
//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.wiki = adminWiki;
|
|
d.customFields = CustomFieldData(admin, DateCustomFields);
|
|
await util.PutAsync("User/1", d.ToString());
|
|
}
|
|
|
|
//Attachments
|
|
if (adminWiki != null)
|
|
await ExportAttachments(new TypeAndID(RootObjectTypes.User, User.AdministratorID));
|
|
#endregion admin export
|
|
|
|
|
|
foreach (UserPickList.UserPickListInfo i in pl)
|
|
{
|
|
List<string> tags = new List<string>();
|
|
tags.Add(ImportTag);
|
|
|
|
//skip administrator user fields
|
|
//but do export administrator
|
|
if (i.ID == User.AdministratorID) continue;
|
|
|
|
User c = User.GetItem(i.ID);
|
|
dynamic d = new JObject();
|
|
d.name = c.FirstName + " " + c.LastName;
|
|
|
|
d.userType = (int)c.UserType;
|
|
|
|
//if special 3rd party user type then set their parent object id to -1 to signify will fill in later and satisfy biz rules at server
|
|
switch (c.UserType)
|
|
{
|
|
case UserTypes.Client:
|
|
d.customerId = -1;
|
|
break;
|
|
case UserTypes.HeadOffice:
|
|
d.headOfficeId = -1;
|
|
break;
|
|
}
|
|
if (c.VendorID != Guid.Empty)
|
|
{
|
|
d.userType = 7;//7 is the RAVEN user type for subcontractor
|
|
d.subVendorId = -1;
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
//wiki page
|
|
var w = GetWikiContent(new TypeAndID(RootObjectTypes.User, c.ID));
|
|
if (w != null)
|
|
{
|
|
d.wiki = w;
|
|
}
|
|
|
|
//Custom fields?
|
|
if (ShouldExportCustom)
|
|
{
|
|
d.customFields = CustomFieldData(c, DateCustomFields);
|
|
}
|
|
|
|
var a = await util.PostAsync("User", d.ToString());
|
|
long RavenId = util.IdFromResponse(a);
|
|
Map.Add(c.ID, RavenId);
|
|
|
|
//USER OPTIONS
|
|
if (c.ScheduleBackColor != 0 || !string.IsNullOrWhiteSpace(c.EmailAddress))
|
|
{
|
|
a = await util.GetAsync("UserOptions/" + RavenId.ToString());
|
|
d = a.ObjectResponse["data"];
|
|
d.uiColor = System.Drawing.ColorTranslator.ToHtml(System.Drawing.Color.FromArgb(c.ScheduleBackColor));
|
|
d.emailAddress = string.IsNullOrWhiteSpace(c.EmailAddress) ? null : c.EmailAddress;
|
|
|
|
await util.PutAsync("UserOptions/" + RavenId.ToString(), d.ToString());
|
|
}
|
|
|
|
//Attachments / FILES
|
|
await ExportAttachments(new TypeAndID(RootObjectTypes.User, c.ID));
|
|
|
|
}
|
|
|
|
|
|
//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)
|
|
{
|
|
User c = User.GetItem(i.ID);
|
|
var newId = Map[c.ID];
|
|
var creator = Map[c.Creator];
|
|
var modifier = Map[c.Modifier];
|
|
|
|
await util.EventLog(3, newId, creator, modifier, c.Created, c.Modified);
|
|
}
|
|
//todo fixup post import
|
|
progress.Append("TODO: User, fixup translationID, headofficeid, clientid vendorid, phone1, phone2, pagermaxtext");
|
|
}
|
|
#endregion clients
|
|
|
|
#region TAG ITEMS
|
|
#region Unitmodelcategories
|
|
private void ExportUnitModelCategories(ProgressForm progress)
|
|
{
|
|
UnitModelCategories l = UnitModelCategories.GetItems();
|
|
progress.Append("Compiling " + l.Count.ToString() + " Unit model categories");
|
|
foreach (UnitModelCategory i in l) TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "unitmodelcategory"));
|
|
}
|
|
#endregion
|
|
|
|
#region Unitservicetypes
|
|
private void ExportUnitServiceTypes(ProgressForm progress)
|
|
{
|
|
UnitServiceTypes l = UnitServiceTypes.GetItems();
|
|
progress.Append("Compiling " + l.Count.ToString() + " Unit service types");
|
|
foreach (UnitServiceType i in l)
|
|
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "unitservicetype"));
|
|
}
|
|
#endregion
|
|
|
|
#region WorkorderItemTypes
|
|
private void ExportWorkorderItemTypes(ProgressForm progress)
|
|
{
|
|
|
|
WorkorderItemTypes l = WorkorderItemTypes.GetItems();
|
|
progress.Append("Compiling " + l.Count.ToString() + " Workorder item types");
|
|
foreach (WorkorderItemType i in l)
|
|
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "workorderitemtype"));
|
|
}
|
|
#endregion
|
|
|
|
#region REGIONS
|
|
private void ExportRegions(ProgressForm progress)
|
|
{
|
|
RegionList l = RegionList.GetList(string.Empty);
|
|
progress.Append("Compiling " + l.Count.ToString() + " Regions");
|
|
foreach (RegionList.RegionListInfo i in l)
|
|
TagMap.Add(i.LT_Region_Label_Name.Value, util.NormalizeTag(i.LT_Region_Label_Name.Display + "." + "region"));
|
|
}
|
|
#endregion
|
|
|
|
#region Client groups
|
|
private void ExportClientGroups(ProgressForm progress)
|
|
{
|
|
ClientGroups l = ClientGroups.GetItems();
|
|
progress.Append("Compiling " + l.Count.ToString() + " Client groups");
|
|
foreach (ClientGroup i in l)
|
|
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "clientgroup"));
|
|
}
|
|
#endregion
|
|
|
|
#region Workorder categories
|
|
private void ExportWorkorderCategories(ProgressForm progress)
|
|
{
|
|
WorkorderCategories l = WorkorderCategories.GetItems();
|
|
progress.Append("Compiling " + l.Count.ToString() + " Workorder categories");
|
|
foreach (WorkorderCategory i in l)
|
|
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "workordercategory"));
|
|
}
|
|
#endregion
|
|
|
|
#region Part categories
|
|
private void ExportPartCategories(ProgressForm progress)
|
|
{
|
|
PartCategories l = PartCategories.GetItems();
|
|
progress.Append("Compiling " + l.Count.ToString() + " Part categories");
|
|
foreach (PartCategory i in l) TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "partcategory"));
|
|
}
|
|
#endregion
|
|
|
|
#region ScheduleableUserGroups
|
|
private void ExportScheduleableUserGroups(ProgressForm progress)
|
|
{
|
|
ScheduleableUserGroupPickList pl = ScheduleableUserGroupPickList.GetList();
|
|
progress.Append("Compiling " + pl.Count.ToString() + " Scheduleable user groups");
|
|
foreach (ScheduleableUserGroupPickList.ScheduleableUserGroupPickListInfo i in pl)
|
|
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "partcategory"));
|
|
}
|
|
#endregion clients
|
|
|
|
#region Dispatch zones
|
|
private void ExportDispatchZones(ProgressForm progress)
|
|
{
|
|
DispatchZones l = DispatchZones.GetItems(false);
|
|
progress.Append("Compiling " + l.Count.ToString() + " Dispatch zones");
|
|
foreach (DispatchZone i in l)
|
|
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "dispatchzone"));
|
|
}
|
|
#endregion
|
|
|
|
private void ExportUserSkills(ProgressForm progress)
|
|
{
|
|
UserSkills l = UserSkills.GetItems();
|
|
progress.Append("Compiling " + l.Count.ToString() + " User skills");
|
|
foreach (UserSkill i in l)
|
|
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "user-skill"));
|
|
}
|
|
|
|
private void ExportUserCertifications(ProgressForm progress)
|
|
{
|
|
UserCertifications l = UserCertifications.GetItems();
|
|
progress.Append("Compiling " + l.Count.ToString() + " User certifications");
|
|
foreach (UserCertification i in l)
|
|
TagMap.Add(i.ID, util.NormalizeTag(i.Name + "." + "user-certification"));
|
|
}
|
|
|
|
#endregion TAG ITEMS
|
|
//--------------------------------------------
|
|
#endregion object export
|
|
|
|
|
|
#region Custom fields exporter
|
|
|
|
|
|
//export objects custom field data into jobject string
|
|
private string CustomFieldData(object biz, List<int> dateFields)
|
|
{
|
|
dynamic d = new JObject();
|
|
|
|
for (int x = 0; x < 10; x++)
|
|
{
|
|
object o = (object)biz.GetType().GetProperty("Custom" + x.ToString()).GetValue(biz, null);
|
|
string s = o.ToString();
|
|
if (string.IsNullOrWhiteSpace(s))
|
|
{
|
|
s = null;
|
|
}
|
|
if (s != null && dateFields.Contains(x))
|
|
{
|
|
//parse out to UTC date
|
|
DateTime dt = new DateTime();
|
|
if (DateTime.TryParse(s, out dt))
|
|
{
|
|
s = dt.ToUniversalTime().ToString("s");
|
|
}
|
|
}
|
|
if (!string.IsNullOrWhiteSpace(s))
|
|
d["c" + (x + 1).ToString()] = s;
|
|
|
|
}
|
|
return d.ToString();
|
|
}
|
|
|
|
static public ObjectCustomFields ObjectHasCustomFieldDataToExport(string sObject)
|
|
{
|
|
ObjectCustomFields ocf = ObjectCustomFields.GetItems(sObject);
|
|
if (ocf.Count == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
foreach (ObjectCustomField f in ocf)
|
|
{
|
|
if (f.Visible)
|
|
return ocf;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private async System.Threading.Tasks.Task<List<int>> ExportCustomFieldSchema(ObjectCustomFields ocf, string v7CustomFieldObjectName, string RavenCustomTranslationKeyObjectName)
|
|
{
|
|
var ret = new List<int>();
|
|
//NOTE: this code inspired by winforApp::Util.cs PrepareCustomFieldsGrid method
|
|
dynamic d = new JObject();
|
|
d.formkey = RavenCustomTranslationKeyObjectName;
|
|
dynamic dtemplate = new JArray();
|
|
foreach (ObjectCustomField f in ocf)
|
|
{
|
|
if (f.Visible)
|
|
{
|
|
int n = Convert.ToInt32(f.FieldName.Replace("Custom", "")) + 1;//raven custom fields are 1 based, v7 are zero based
|
|
CustomFieldLocaleKeys.Add(RavenCustomTranslationKeyObjectName + n.ToString(),
|
|
util.LocaleText.GetLocalizedText(v7CustomFieldObjectName + ".Label." + f.FieldName));
|
|
|
|
dynamic dt = new JObject();
|
|
dt.fld = RavenCustomTranslationKeyObjectName + "Custom" + n.ToString();
|
|
dt.hide = false;
|
|
dt.required = false;
|
|
switch (f.FieldType)
|
|
{
|
|
case FormFieldDataTypes.Currency:
|
|
dt.type = util.AyaUiFieldDataType.Currency;
|
|
break;
|
|
case FormFieldDataTypes.DateOnly:
|
|
dt.type = util.AyaUiFieldDataType.Date;
|
|
ret.Add(n - 1);
|
|
break;
|
|
case FormFieldDataTypes.DateTime:
|
|
dt.type = util.AyaUiFieldDataType.DateTime;
|
|
ret.Add(n - 1);
|
|
break;
|
|
case FormFieldDataTypes.Number:
|
|
dt.type = util.AyaUiFieldDataType.Decimal;
|
|
break;
|
|
case FormFieldDataTypes.Text:
|
|
dt.type = util.AyaUiFieldDataType.Text;
|
|
break;
|
|
case FormFieldDataTypes.TimeOnly:
|
|
dt.type = util.AyaUiFieldDataType.Time;
|
|
ret.Add(n - 1);
|
|
break;
|
|
case FormFieldDataTypes.TrueFalse:
|
|
dt.type = util.AyaUiFieldDataType.Bool;
|
|
break;
|
|
default:
|
|
dt.type = util.AyaUiFieldDataType.Text;
|
|
break;
|
|
}
|
|
dtemplate.Add(dt);
|
|
}
|
|
}
|
|
d.template = dtemplate.ToString();
|
|
|
|
//ok, were here because there *are* custom fields available
|
|
var a = await util.GetAsync("FormCustom/" + RavenCustomTranslationKeyObjectName);
|
|
var ctoken = util.CTokenFromResponse(a);
|
|
d.concurrencyToken = ctoken;
|
|
await util.PutAsync("FormCustom/" + RavenCustomTranslationKeyObjectName, d.ToString());
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endregion custom fields
|
|
|
|
#region WIKI page exporter
|
|
|
|
|
|
//WIKI
|
|
#region Wikiable objects reference
|
|
/*
|
|
Find all "Util.OpenWikiPage", Whole word, Subfolders, Keep modified files open, Find Results 1, Entire Solution, ""
|
|
C:\data\ayanova\source\WinFormApp\ClientInfoForm.cs(1579): Util.OpenWikiPage(RootObjectTypes.Client, mClient.ID,false);
|
|
C:\data\ayanova\source\WinFormApp\ContractInfoForm.cs(687): Util.OpenWikiPage(RootObjectTypes.Contract, mContract.ID, false);
|
|
C:\data\ayanova\source\WinFormApp\Form1.cs(3713): Util.OpenWikiPage(RootObjectTypes.Global, Address.GlobalAddressID, false);
|
|
C:\data\ayanova\source\WinFormApp\Form1.cs(3856): Util.OpenWikiPage(RootObjectTypes.User, User.CurrentThreadUserID, false);
|
|
C:\data\ayanova\source\WinFormApp\Form1.cs(3867): // Util.OpenWikiPage(RootObjectTypes.User,User.CurrentThreadUserID,false);
|
|
C:\data\ayanova\source\WinFormApp\HeadOfficeInfoForm.cs(1402): Util.OpenWikiPage(RootObjectTypes.HeadOffice, mHeadOffice.ID,false);
|
|
C:\data\ayanova\source\WinFormApp\LoanItemInfoForm.cs(860): Util.OpenWikiPage(RootObjectTypes.LoanItem, mLoanItem.ID, false);
|
|
C:\data\ayanova\source\WinFormApp\PartInfoForm.cs(1111): Util.OpenWikiPage(RootObjectTypes.Part, mPart.ID, false);
|
|
C:\data\ayanova\source\WinFormApp\ProjectInfoForm.cs(712): Util.OpenWikiPage(RootObjectTypes.Project, mProject.ID, false);
|
|
C:\data\ayanova\source\WinFormApp\PurchaseOrderInfoForm.cs(1010): Util.OpenWikiPage(RootObjectTypes.PurchaseOrder, mPurchaseOrder.ID, false);
|
|
C:\data\ayanova\source\WinFormApp\RegionInfoForm.cs(1186): Util.OpenWikiPage(RootObjectTypes.Region, mRegion.ID, false);
|
|
C:\data\ayanova\source\WinFormApp\UnitInfoForm.cs(1280): Util.OpenWikiPage(RootObjectTypes.Unit, mUnit.ID, false);
|
|
C:\data\ayanova\source\WinFormApp\UnitModelInfoForm.cs(926): Util.OpenWikiPage(RootObjectTypes.UnitModel, mUnitModel.ID, false);
|
|
C:\data\ayanova\source\WinFormApp\UserInfoForm.cs(1395): Util.OpenWikiPage(RootObjectTypes.User, mUser.ID, false);
|
|
C:\data\ayanova\source\WinFormApp\VendorInfoForm.cs(1193): Util.OpenWikiPage(RootObjectTypes.Vendor, mVendor.ID, false);
|
|
C:\data\ayanova\source\WinFormApp\WorkorderForm.cs(10332): Util.OpenWikiPage(mWorkorder.RootObjectType, mWorkorder.ID, false);//case 1584 was RootObjectTypes.Workorder
|
|
C:\data\ayanova\source\WBI\maingrid.aspx.cs(1277): Util.OpenWikiPage(this.Page, new TypeAndID(RootObjectTypes.Global, Address.GlobalAddressID));
|
|
C:\data\ayanova\source\WBI\schedule.aspx.cs(187): Util.OpenWikiPage(this.Page, new TypeAndID(RootObjectTypes.Global, Address.GlobalAddressID));
|
|
Matching lines: 18 Matching files: 16 Total files searched: 1769
|
|
*/
|
|
#endregion
|
|
|
|
private string GetWikiContent(TypeAndID tid)
|
|
{
|
|
//may not exist
|
|
if (!WikiPage.HasWiki(tid.ID)) return null;
|
|
|
|
WikiPage w = WikiPage.GetItem(tid);
|
|
var content = w.GetContentAsString;
|
|
|
|
if (!string.IsNullOrWhiteSpace(content))
|
|
return content;
|
|
else
|
|
return null;
|
|
}
|
|
|
|
|
|
private async System.Threading.Tasks.Task ExportAttachments(TypeAndID tid)
|
|
{
|
|
if (!WikiPage.HasWiki(tid.ID)) return;
|
|
|
|
WikiPage w = WikiPage.GetItem(tid);
|
|
AyaFileList fl = AyaFileList.GetList(w.ID);
|
|
if (fl.Count == 0) return;
|
|
|
|
|
|
//files
|
|
foreach (AyaFileList.AyaFileListInfo i in fl)
|
|
{
|
|
//WikiFileInfo fi = new WikiFileInfo();
|
|
// fi.Id = i.LT_O_AyaFile.Value.ToString();
|
|
// fi.Name = i.LT_O_AyaFile.Display;
|
|
// fi.Size = i.LT_AyaFile_Label_FileSize;
|
|
// fi.Creator = i.LT_Common_Label_Creator.Display;
|
|
// fi.Created = i.LT_Common_Label_Created.ToString();
|
|
// ret.Add(fi);
|
|
|
|
|
|
var af = AyaFile.GetItem(i.LT_O_AyaFile.Value);
|
|
if (af == null) continue;
|
|
|
|
//Upload
|
|
|
|
|
|
MultipartFormDataContent formDataContent = new MultipartFormDataContent();
|
|
|
|
//Form data like the bizobject type and id
|
|
formDataContent.Add(new StringContent(util.RootObjectToAyaType(tid.RootObjectType).ToString()), name: "AttachToObjectType");
|
|
formDataContent.Add(new StringContent(Map[tid.ID].ToString()), name: "AttachToObjectId");
|
|
formDataContent.Add(new StringContent(ImportTag), name: "Notes");
|
|
//or if testing non-existant this is probably safe: long.MaxValue
|
|
|
|
|
|
StreamContent AttachmentFile = new StreamContent(af.GetContent());
|
|
AttachmentFile.Headers.ContentType = new MediaTypeHeaderValue(af.mimeType);
|
|
AttachmentFile.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
|
|
AttachmentFile.Headers.ContentDisposition.FileName = af.Name;
|
|
|
|
var sDate = i.LT_Common_Label_Created.ToString();
|
|
DateTime dtLastModified = DateTime.UtcNow;
|
|
if (sDate != null)
|
|
{
|
|
//parse out to UTC date
|
|
DateTime dt = new DateTime();
|
|
if (DateTime.TryParse(sDate, out dt))
|
|
{
|
|
dtLastModified = dt.ToUniversalTime();
|
|
}
|
|
}
|
|
|
|
AttachmentFile.Headers.ContentDisposition.ModificationDate = dtLastModified;
|
|
formDataContent.Add(AttachmentFile);
|
|
|
|
//create via inventory full test user as attachments use the role of the object attaching to
|
|
await util.PostFormDataAsync("Attachment", formDataContent);
|
|
|
|
|
|
|
|
|
|
|
|
//af.WriteToDisk(filePath, af.Name);
|
|
|
|
//var fileInfo = new
|
|
//{
|
|
// name = i.LT_O_AyaFile.Display,
|
|
// created = i.LT_Common_Label_Created,
|
|
// creator = i.LT_Common_Label_Creator.Value,
|
|
// mimetype = af.mimeType,
|
|
// id = af.ID,
|
|
// size = af.FileSize,
|
|
// ayafiletype = af.FileType,
|
|
// rootobjectid = af.RootObjectID,
|
|
// rootobjecttype = af.RootObjectType
|
|
//};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
#endregion wiki
|
|
|
|
|
|
#region TAGS
|
|
private void Tagit(Guid g, List<string> tags)
|
|
{
|
|
if (g == Guid.Empty) return;
|
|
if (!TagMap.ContainsKey(g)) return;
|
|
var t = TagMap[g];
|
|
if (!string.IsNullOrWhiteSpace(t))
|
|
{
|
|
tags.Add(t);
|
|
}
|
|
}
|
|
|
|
private void SetTags(dynamic d, List<string> tags)
|
|
{
|
|
dynamic dtags = new JArray();
|
|
foreach (string s in tags)
|
|
dtags.Add(s);
|
|
d.tags = dtags;
|
|
}
|
|
|
|
#endregion tags
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region OLD JSON EXPORT STUFF
|
|
|
|
|
|
#region contract resolver
|
|
//public class ExcludeNamedPropertiesContractResolver : DefaultContractResolver
|
|
//{
|
|
// private readonly List<string> _excludeProperties;
|
|
|
|
// public ExcludeNamedPropertiesContractResolver(List<string> excludeProperties)
|
|
// {
|
|
// _excludeProperties = excludeProperties;
|
|
// }
|
|
|
|
// protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
|
|
// {
|
|
// IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
|
|
|
|
// // only serializer properties that start with the specified character
|
|
// //properties = properties.Where(p => p.PropertyName.StartsWith(_startingWithChar.ToString())).ToList();
|
|
// properties = properties.Where(p => !_excludeProperties.Contains(p.PropertyName)).ToList();
|
|
|
|
// return properties;
|
|
// }
|
|
//}
|
|
#endregion contract resolver
|
|
|
|
|
|
//private static string EnsureValidFileName(string fileName)
|
|
//{
|
|
// //make lower and replace spaces with dashes
|
|
// fileName = fileName.ToLowerInvariant().Replace(" ", "-");
|
|
|
|
// //ensure each character is a valid path character
|
|
// foreach (char c in System.IO.Path.GetInvalidFileNameChars())
|
|
// {
|
|
// fileName = fileName.Replace(c, '_');
|
|
// }
|
|
// return fileName;
|
|
//}
|
|
|
|
|
|
|
|
//private static void makeFolderIfNotExist(string fldr, bool shouldNotExist = false)
|
|
//{
|
|
// if (Directory.Exists(fldr))
|
|
// {
|
|
// if (shouldNotExist)
|
|
// throw new System.Exception("Error: path already exists and shouldn't:\r\n" + fldr);
|
|
// return;
|
|
// }
|
|
// Directory.CreateDirectory(fldr);
|
|
//}
|
|
|
|
//private List<string> standardExcludePropertiesList
|
|
//{
|
|
// get
|
|
// {
|
|
// return new List<string>()
|
|
// {
|
|
// "CanWiki",
|
|
// "CanDuplicate",
|
|
// "IsValid",
|
|
// "IsDirty",
|
|
// "CurrentUserID",
|
|
// "IsEditing",
|
|
// "IsNew",
|
|
// "IsDeleted",
|
|
// "IsSavable",
|
|
// "Notify",
|
|
// "BrokenRulesText",
|
|
// "Docs",
|
|
// "MapQuestURL",
|
|
// "FullAddress"
|
|
// //"XXX",
|
|
// //"XXX",
|
|
// //"XXX",
|
|
// //"XXX",
|
|
// //"XXX",
|
|
// //"XXX",
|
|
// //"XXX",
|
|
// //"XXX",
|
|
// //"XXX",
|
|
// //"XXX",
|
|
// //"XXX"
|
|
// };
|
|
|
|
// }
|
|
//}
|
|
#endregion old
|
|
|
|
//eoc
|
|
}
|
|
|
|
//eons
|
|
}
|