Files
ayanova7/source/Plugins/AyaNova.Plugin.V8/V8.cs
2020-05-13 22:59:28 +00:00

3045 lines
118 KiB
C#
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
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.1-alpha.8"; }
}
public string About
{
get
{
return "AyaNova V8 export plugin";
}
}
public Guid PluginID
{
get { return new Guid("{BD608E8A-820C-46D1-9D81-4CCB6E71B213}"); }
}
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)
{
util.PRE_RELEASE_VERSION_STRING = "Pre-release test " + this.PluginVersion;
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;
}
Opt dOpt = new Opt();
var ro = dOpt.ShowDialog();
if (ro == DialogResult.Cancel)
{
return;
}
ExportAssignedDocs = dOpt.ExportAssignedDocs;
//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 void AddMap(Guid v7id, long v8id)
{
if (Map.ContainsKey(v7id))
{
throw new Exception("Error: AddMap - v7id already mapped previously, id is " + v7id.ToString());
}
else Map.Add(v7id, v8id);
}
private bool IsDuplicateMapItem(Guid v7id, string name, ProgressForm progress)
{
if (Map.ContainsKey(v7id))
{
progress.Append("DUPLICATE: " + name + " - has duplicate ID, not exported");
return true;
}
return false;
}
private long SafeGetUserMap(Guid id)
{
if (!Map.ContainsKey(id)) return 1;//1=raven administrator account
return Map[id];
}
private Dictionary<Guid, string> TagMap = new Dictionary<Guid, string>();
private Dictionary<string, long> LocaleMap = new Dictionary<string, long>();
private string ImportTag = "v7-import";
private bool ExportAssignedDocs = false;
/// <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);
progress.Append(util.PRE_RELEASE_VERSION_STRING);
try
{
progress.Op("Preparing to export....");
Map.Clear();
TagMap.Clear();
LocaleMap.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:
Need more detail when fails on release mode, right now no idea what actually happened
Global wiki export to user
Regions export wiki to user
todo: export docs, settle on "Export" and edit all references to Import to switch it around as it's probably confusing artifact from dbdump days
todo: User fields need to be rectified: headofficeid, clientid vendorid, phone1, phone2, pagermaxtext
Yeah and a million other things too, this can wait until Stage7 - "Reality"
*/
//if (progress.KeepGoing)
// await ExportLocales(progress);
//return;
//Export in correct order:
//ERASE DB
progress.Op("Erasing AyaNova 8 data");
var a = await util.PostAsync("License/PermanentlyEraseAllData", "\"I understand\"");
//TAGS
progress.Op("Compiling tags");
if (progress.KeepGoing)
ExportUnitModelCategories(progress);
if (progress.KeepGoing)
ExportUnitServiceTypes(progress);
if (progress.KeepGoing)
ExportWorkorderItemTypes(progress);
if (progress.KeepGoing)
ExportRegions(progress);
if (progress.KeepGoing)
ExportClientGroups(progress);
if (progress.KeepGoing)
ExportWorkorderCategories(progress);
if (progress.KeepGoing)
ExportPartCategories(progress);
if (progress.KeepGoing)
ExportScheduleableUserGroups(progress);
if (progress.KeepGoing)
ExportDispatchZones(progress);
if (progress.KeepGoing)
ExportUserSkills(progress);
if (progress.KeepGoing)
ExportUserCertifications(progress);
progress.Op("Exporting Business objects");
//BIZ objects
await ExportLocales(progress);
await ExportUsers(progress);
await ExportClients(progress);
await ExportHeadOffices(progress);
await ExportContracts(progress);
await ExportLoanItems(progress);
await ExportParts(progress);
await ExportProjects(progress);
await ExportPurchaseOrders(progress);
await ExportUnits(progress);
await ExportUnitModels(progress);
await ExportVendors(progress);
await ExportServiceWorkorders(progress);
//todo: these are now invalid and awaiting RAVEN end implementation
//after which can copy mostly from service workorder block
// await ExportQuotes(progress);
// await ExportPMs(progress);
//NOTE: when get to PRIORITY, or WORKORDER STATUS be sure to add color code as per already done in USER export
if (progress.KeepGoing)
{
progress.Append("Export completed");
progress.Op("");
goto End;
}
progress.Append("Export cancelled before completing");
progress.Op("");
End:
;
}
catch (Exception ex)
{
progress.Append("ERROR, During operation: \n" + progress.LastOp + "\n" + progress.LastSubOp);
progress.Append("\n************\nExport failed with error:\n");
progress.Append(ex.Message);
progress.Append("stack:\n" + ex.StackTrace);
}
finally
{
progress.FinishedImport();
}
//-----------------------------------
//endof method
}
#region BIZ OBJECT Export methods
List<string> UsedNames = new List<string>();
long LUniqueName = 1;
private string GetUniqueName(string tryName)
{
string retName = tryName;
do
{
if (!UsedNames.Contains(retName))
{
UsedNames.Add(retName);
return retName;
}
retName = util.UniqueNameBuilder(tryName, LUniqueName++, 255);
} while (true);
}
private void ResetUniqueNames()
{
LUniqueName = 1;
UsedNames.Clear();
}
#region users
private async System.Threading.Tasks.Task ExportUsers(ProgressForm progress)
{
if (!progress.KeepGoing) return;
progress.Op("Start 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");
#region Export administrator wiki and attached files if present
{
User admin = User.GetItem(User.AdministratorID);
progress.Op("Administrator account");
var adminTid = new TypeAndID(RootObjectTypes.User, User.AdministratorID);
//Attachments and wiki
string AdminWikiContent = null;
var hasWiki = WikiPage.HasWiki(User.AdministratorID);
if (hasWiki)
{
await ExportAttachments(adminTid, progress);
AdminWikiContent = GetWikiContent(adminTid);
}
string adminCustomFields = null;
//Custom fields?
if (ShouldExportCustom)
{
adminCustomFields = CustomFieldData(admin, DateCustomFields);
}
//check if we need to do anything with the manager account itself
if (hasWiki || 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 = AdminWikiContent;
d.customFields = CustomFieldData(admin, DateCustomFields);
await util.PutAsync("User/1", d.ToString());
}
}
#endregion admin export
foreach (UserPickList.UserPickListInfo i in pl)
{
if (!progress.KeepGoing) return;
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);
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);
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);
//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("UserOptions/" + 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("UserOptions/" + 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/" + RavenId.ToString(), d.ToString());
//-----
}
//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);
}
}
#endregion users
#region Clients
private async System.Threading.Tasks.Task ExportClients(ProgressForm progress)
{
if (!progress.KeepGoing) return;
progress.Op("Start Client export");
progress.SubOp("");
ResetUniqueNames();
var ObjectTypeName = "Client";
//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(ObjectTypeName);
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, ObjectTypeName, "Customer");
//Step 2: export the objects
ClientPickList pl = ClientPickList.GetList();
progress.Append("Exporting " + pl.Count.ToString() + " " + ObjectTypeName + "s");
foreach (ClientPickList.ClientPickListInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
Client c = Client.GetItem(i.ID);
var ObjectTID = new TypeAndID(RootObjectTypes.Client, c.ID);
dynamic d = new JObject();
d.name = GetUniqueName(c.Name);
if (IsDuplicateMapItem(c.ID, c.Name, progress)) continue;
progress.Op(ObjectTypeName + " " + d.name);
d.active = c.Active;
d.notes = c.Notes;
Tagit(c.RegionID, tags);
Tagit(c.DispatchZoneID, tags);
Tagit(c.ClientGroupID, tags);
SetTags(d, tags);
//Custom fields?
if (ShouldExportCustom)
d.customFields = CustomFieldData(c, DateCustomFields);
var rMainObject = await util.PostAsync("Customer", d.ToString());
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
//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("Customer/" + RavenId.ToString(), d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.Customer, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
}
}
#endregion Clients
#region Headoffices
private async System.Threading.Tasks.Task ExportHeadOffices(ProgressForm progress)
{
if (!progress.KeepGoing) return;
progress.Op("Start Head office export");
progress.SubOp("");
ResetUniqueNames();
var ObjectTypeName = "HeadOffice";
//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(ObjectTypeName);
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, ObjectTypeName, ObjectTypeName);
//Step 2: export the objects
PickListAutoComplete pl = PickListAutoComplete.GetList("**", "headoffice");
progress.Append("Exporting " + pl.Count.ToString() + " " + ObjectTypeName + "s");
foreach (PickListAutoComplete.PickListAutoCompleteInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
HeadOffice c = HeadOffice.GetItem(i.ID);
var ObjectTID = new TypeAndID(RootObjectTypes.HeadOffice, c.ID);
dynamic d = new JObject();
d.name = GetUniqueName(c.Name);
if (IsDuplicateMapItem(c.ID, c.Name, progress)) continue;
progress.Op(ObjectTypeName + " " + d.name);
d.active = c.Active;
d.notes = c.Notes;
Tagit(c.RegionID, tags);
Tagit(c.ClientGroupID, tags);
SetTags(d, tags);
//Custom fields?
if (ShouldExportCustom)
d.customFields = CustomFieldData(c, DateCustomFields);
var rMainObject = await util.PostAsync("HeadOffice", d.ToString());
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
//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(ObjectTypeName + "/" + RavenId.ToString(), d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.HeadOffice, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
}
}
#endregion ho
#region Contracts
private async System.Threading.Tasks.Task ExportContracts(ProgressForm progress)
{
ResetUniqueNames();
if (!progress.KeepGoing) return;
progress.Op("Start Contract export");
progress.SubOp("");
var ObjectTypeName = "Contract";
//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(ObjectTypeName);
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, ObjectTypeName, ObjectTypeName);
//Step 2: export the objects
PickListAutoComplete pl = PickListAutoComplete.GetList("**", "contract");
progress.Append("Exporting " + pl.Count.ToString() + " " + ObjectTypeName + "s");
foreach (PickListAutoComplete.PickListAutoCompleteInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
Contract c = Contract.GetItem(i.ID);
var ObjectTID = new TypeAndID(RootObjectTypes.Contract, c.ID);
dynamic d = new JObject();
d.name = GetUniqueName(c.Name);
if (IsDuplicateMapItem(c.ID, c.Name, progress)) continue;
progress.Op(ObjectTypeName + " " + d.name);
d.active = c.Active;
d.notes = c.Notes;
Tagit(c.RegionID, tags);
SetTags(d, tags);
//Custom fields?
if (ShouldExportCustom)
d.customFields = CustomFieldData(c, DateCustomFields);
var rMainObject = await util.PostAsync("contract", d.ToString());
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
//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("contract", d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.Contract, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
}
}
#endregion Contracts
#region LoanItems
private async System.Threading.Tasks.Task ExportLoanItems(ProgressForm progress)
{
ResetUniqueNames();
if (!progress.KeepGoing) return;
progress.Op("Start Loan item export");
progress.SubOp("");
var ObjectTypeName = "LoanItem";
var RavenObjectName = "LoanUnit";
//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(ObjectTypeName);
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, ObjectTypeName, RavenObjectName);
//Step 2: export the objects
PickListAutoComplete pl = PickListAutoComplete.GetList("**", "loanitem");
progress.Append("Exporting " + pl.Count.ToString() + " " + ObjectTypeName + "s");
foreach (PickListAutoComplete.PickListAutoCompleteInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
LoanItem c = LoanItem.GetItem(i.ID);
var ObjectTID = new TypeAndID(RootObjectTypes.LoanItem, c.ID);
dynamic d = new JObject();
d.name = GetUniqueName(c.Name);
if (IsDuplicateMapItem(c.ID, c.Name, progress)) continue;
progress.Op(ObjectTypeName + " " + d.name);
d.active = c.Active;
d.notes = c.Notes;
Tagit(c.RegionID, tags);
SetTags(d, tags);
//Custom fields?
if (ShouldExportCustom)
d.customFields = CustomFieldData(c, DateCustomFields);
var rMainObject = await util.PostAsync(RavenObjectName, d.ToString());
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
//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(RavenObjectName + "/" + RavenId.ToString(), d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.LoanUnit, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
}
}
#endregion LoanItems
#region Parts
private async System.Threading.Tasks.Task ExportParts(ProgressForm progress)
{
ResetUniqueNames();
if (!progress.KeepGoing) return;
progress.Op("Start Parts export");
progress.SubOp("");
var ObjectTypeName = "Part";
var RavenObjectName = "Part";
//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(ObjectTypeName);
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, ObjectTypeName, RavenObjectName);
//Step 2: export the objects
PartPickList pl = PartPickList.GetAllParts();
// PickListAutoComplete pl = PickListAutoComplete.GetList("**", "loanitem");
progress.Append("Exporting " + pl.Count.ToString() + " " + ObjectTypeName + "s");
foreach (PartPickList.PartPickListInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
Part c = Part.GetItem(i.ID);
var ObjectTID = new TypeAndID(RootObjectTypes.Part, c.ID);
dynamic d = new JObject();
d.name = GetUniqueName(i.DisplayName(AyaBizUtils.GlobalSettings.DefaultPartDisplayFormat));//todo: temporary for testing
if (IsDuplicateMapItem(c.ID, c.Name, progress)) continue;
progress.Op(ObjectTypeName + " " + d.name);
d.active = c.Active;
d.notes = c.Notes;
SetTags(d, tags);
//Custom fields?
if (ShouldExportCustom)
d.customFields = CustomFieldData(c, DateCustomFields);
var rMainObject = await util.PostAsync(RavenObjectName, d.ToString());
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
//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(ObjectTypeName + "/" + RavenId.ToString(), d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.Part, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
}
}
#endregion Parts
#region Projects
private async System.Threading.Tasks.Task ExportProjects(ProgressForm progress)
{
ResetUniqueNames();
if (!progress.KeepGoing) return;
progress.Op("Start Projects export");
progress.SubOp("");
var ObjectTypeName = "Project";
//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(ObjectTypeName);
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, ObjectTypeName, ObjectTypeName);
//Step 2: export the objects
PickListAutoComplete pl = PickListAutoComplete.GetList("**", "project");
progress.Append("Exporting " + pl.Count.ToString() + " " + ObjectTypeName + "s");
foreach (PickListAutoComplete.PickListAutoCompleteInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
Project c = Project.GetItem(i.ID);
var ObjectTID = new TypeAndID(RootObjectTypes.Project, c.ID);
dynamic d = new JObject();
d.name = GetUniqueName(c.Name);
if (IsDuplicateMapItem(c.ID, c.Name, progress)) continue;
progress.Op(ObjectTypeName + " " + d.name);
d.active = c.Active;
d.notes = c.Notes;
Tagit(c.RegionID, tags);
SetTags(d, tags);
//Custom fields?
if (ShouldExportCustom)
d.customFields = CustomFieldData(c, DateCustomFields);
var rMainObject = await util.PostAsync(ObjectTypeName, d.ToString());
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
//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(ObjectTypeName + "/" + RavenId.ToString(), d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.Project, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
}
}
#endregion Projects
#region PurchaseOrders
private async System.Threading.Tasks.Task ExportPurchaseOrders(ProgressForm progress)
{
if (!progress.KeepGoing) return;
var ObjectTypeName = "PurchaseOrder";
progress.Op("Start Purchase orders export");
progress.SubOp("");
//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(ObjectTypeName);
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, ObjectTypeName, ObjectTypeName);
//Step 2: export the objects
PurchaseOrderList pl = PurchaseOrderList.GetListByCriteria("");
progress.Append("Exporting " + pl.Count.ToString() + " " + ObjectTypeName + "s");
foreach (PurchaseOrderList.PurchaseOrderListInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
PurchaseOrder c = PurchaseOrder.GetItem(i.LT_PurchaseOrder_Label_PONumber.Value);
var ObjectTID = new TypeAndID(RootObjectTypes.PurchaseOrder, c.ID);
dynamic d = new JObject();
d.name = c.PONumber.ToString();
if (IsDuplicateMapItem(c.ID, i.LT_PurchaseOrder_Label_PONumber.Display, progress)) continue;
progress.Op(ObjectTypeName + " " + d.name);
// d.active = c.Active;
d.notes = c.Notes;
// Tagit(c.RegionID, tags);
SetTags(d, tags);
//Custom fields?
if (ShouldExportCustom)
d.customFields = CustomFieldData(c, DateCustomFields);
var rMainObject = await util.PostAsync(ObjectTypeName, d.ToString());
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
//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;
}
if (repost)
await util.PutAsync(ObjectTypeName + "/" + RavenId.ToString(), d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.PurchaseOrder, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
}
}
#endregion PurchaseOrders
#region Units
private async System.Threading.Tasks.Task ExportUnits(ProgressForm progress)
{
ResetUniqueNames();
if (!progress.KeepGoing) return;
progress.Op("Start Units export");
progress.SubOp("");
var ObjectTypeName = "Unit";
//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(ObjectTypeName);
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, ObjectTypeName, ObjectTypeName);
//Step 2: export the objects
UnitPickList pl = UnitPickList.GetListOfAll();
progress.Append("Exporting " + pl.Count.ToString() + " " + ObjectTypeName + "s");
foreach (UnitPickList.UnitPickListInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
Unit c = Unit.GetItem(i.ID);
var ObjectTID = new TypeAndID(RootObjectTypes.Unit, c.ID);
dynamic d = new JObject();
d.name = GetUniqueName(c.Serial);
if (IsDuplicateMapItem(c.ID, c.Serial, progress)) continue;
progress.Op(ObjectTypeName + " " + d.name);
d.active = c.Active;
d.notes = c.Notes;
// Tagit(c.RegionID, tags);
SetTags(d, tags);
//Custom fields?
if (ShouldExportCustom)
d.customFields = CustomFieldData(c, DateCustomFields);
var rMainObject = await util.PostAsync(ObjectTypeName, d.ToString());
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
//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(ObjectTypeName + "/" + RavenId.ToString(), d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.Unit, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
}
}
#endregion Units
#region UnitModels
private async System.Threading.Tasks.Task ExportUnitModels(ProgressForm progress)
{
ResetUniqueNames();
if (!progress.KeepGoing) return;
progress.Op("Start Unit models export");
progress.SubOp("");
var ObjectTypeName = "UnitModel";
//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(ObjectTypeName);
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, ObjectTypeName, ObjectTypeName);
//Step 2: export the objects
PickListAutoComplete pl = PickListAutoComplete.GetList("**", "unitmodel");
progress.Append("Exporting " + pl.Count.ToString() + " " + ObjectTypeName + "s");
foreach (PickListAutoComplete.PickListAutoCompleteInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
UnitModel c = UnitModel.GetItem(i.ID);
var ObjectTID = new TypeAndID(RootObjectTypes.UnitModel, c.ID);
dynamic d = new JObject();
d.name = GetUniqueName(c.Name);
if (IsDuplicateMapItem(c.ID, c.Name, progress)) continue;
progress.Op(ObjectTypeName + " " + d.name);
d.active = c.Active;
d.notes = c.Notes;
Tagit(c.UnitModelCategoryID, tags);
SetTags(d, tags);
//Custom fields?
if (ShouldExportCustom)
d.customFields = CustomFieldData(c, DateCustomFields);
var rMainObject = await util.PostAsync(ObjectTypeName, d.ToString());
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
//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(ObjectTypeName + "/" + RavenId.ToString(), d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.UnitModel, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
}
}
#endregion UnitModels
#region Vendors
private async System.Threading.Tasks.Task ExportVendors(ProgressForm progress)
{
ResetUniqueNames();
if (!progress.KeepGoing) return;
progress.Op("Start Vendors export");
progress.SubOp("");
var ObjectTypeName = "Vendor";
//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(ObjectTypeName);
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, ObjectTypeName, ObjectTypeName);
//Step 2: export the objects
PickListAutoComplete pl = PickListAutoComplete.GetList("**", "vendor");
progress.Append("Exporting " + pl.Count.ToString() + " " + ObjectTypeName + "s");
foreach (PickListAutoComplete.PickListAutoCompleteInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
Vendor c = Vendor.GetItem(i.ID);
var ObjectTID = new TypeAndID(RootObjectTypes.Vendor, c.ID);
dynamic d = new JObject();
d.name = GetUniqueName(c.Name);
if (IsDuplicateMapItem(c.ID, c.Name, progress)) continue;
progress.Op(ObjectTypeName + " " + d.name);
d.active = c.Active;
d.notes = c.Notes;
SetTags(d, tags);
//Custom fields?
if (ShouldExportCustom)
d.customFields = CustomFieldData(c, DateCustomFields);
var rMainObject = await util.PostAsync(ObjectTypeName, d.ToString());
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
//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(ObjectTypeName + "/" + RavenId.ToString(), d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.Vendor, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
}
}
#endregion Vendors
#region Service Workorders
private async System.Threading.Tasks.Task ExportServiceWorkorders(ProgressForm progress)
{
if (!progress.KeepGoing) return;
progress.Op("Start Service workorders export");
progress.SubOp("");
var ObjectTypeName = "Workorder";
var RavenRouteName = "workorders";
//TODO: this in the workorder Items loop
//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("WorkorderItem");
bool ShouldExportCustom = ocf != null;
var DateCustomFields = await ExportCustomFieldSchema(ocf, "WorkorderItem", "WorkOrderItem");
//Step 2: export the objects
//sort by woid
var crit = @"<?xml version=""1.0"" encoding=""utf-16"" standalone=""yes""?>
<GRIDCRITERIA>
<COLUMNITEM CM=""aWorkorderService.aServiceNumber"" UI=""LT_O_Workorder"" PIN=""0"" WIDTH=""92"" SORT=""ASC"" />
</GRIDCRITERIA>";
WorkorderServiceList pl = WorkorderServiceList.GetList(crit);
progress.Append("Exporting " + pl.Count.ToString() + " Service " + ObjectTypeName + "s");
foreach (WorkorderServiceList.WorkorderServiceListInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
Workorder c = Workorder.GetItem(i.LT_O_Workorder.Value);
if (IsDuplicateMapItem(c.ID, c.WorkorderService.ServiceNumber.ToString(), progress)) continue;
var ObjectTID = new TypeAndID(RootObjectTypes.WorkorderService, c.ID);
dynamic d = new JObject();
//d.concurrencyToken = util.CTokenFromResponse(rMainObject);
progress.Op(ObjectTypeName + " " + c.WorkorderService.ServiceNumber);
d.active = true;//probably can remove this at server, just stubbed in for now
Tagit(c.RegionID, tags);
SetTags(d, tags);
var rMainObject = await util.PostAsync(RavenRouteName, d.ToString());
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
d = rMainObject.ObjectResponse["data"];
d.serial = c.WorkorderService.ServiceNumber;
d.notes = c.Summary;
//Attachments / FILES
await ExportAttachments(ObjectTID, progress, util.AyaType.WorkOrder);
//-----
// wiki
if (WikiPage.HasWiki(c.ID))
{
// await ExportAttachments(ObjectTID, progress);
d.wiki = GetWikiContent(ObjectTID);
}
//docs
string NonFileUrls = await ExportDocs(ObjectTID, c.Docs, progress, util.AyaType.WorkOrder);
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;
}
//put the final object
await util.PutAsync(RavenRouteName, d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.WorkOrder, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
//iterate all workorder items
foreach (WorkorderItem wi in c.WorkorderItems)
{
dynamic dwi = new JObject();
dwi.workOrderId = RavenId;
// d.concurrencyToken = util.CTokenFromResponse(rMainObject);
progress.Op("WorkorderItem " + wi.ID.ToString());
dwi.active = true;//probably can remove this at server, just stubbed in for now
Tagit(wi.TypeID, tags);
Tagit(wi.WorkorderItemUnitServiceTypeID, tags);
SetTags(dwi, tags);
////Custom fields?
if (ShouldExportCustom)
dwi.customFields = CustomFieldData(wi, DateCustomFields);
dwi.notes = "Summary:\n" + wi.Summary + "TechNotes: \n" + wi.TechNotes;
await util.PostAsync("workorders/items", dwi.ToString());
//and rest of tree below here...
}
}
}
#endregion Workorders
#region Quote Workorders
private async System.Threading.Tasks.Task ExportQuotes(ProgressForm progress)
{
if (!progress.KeepGoing) return;
progress.Op("Start Quotes export");
progress.SubOp("");
var ObjectTypeName = "Quote";
var RavenObjectName = "Quote";
//TODO: this in the workorder Items loop
////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("WorkorderItem");
//bool ShouldExportCustom = ocf != null;
//var DateCustomFields = await ExportCustomFieldSchema(ocf, "WorkorderItem", "WorkOrderItem");
//Step 2: export the objects
WorkorderQuoteList pl = WorkorderQuoteList.GetList("");
progress.Append("Exporting " + pl.Count.ToString() + " " + ObjectTypeName + "s");
foreach (WorkorderQuoteList.WorkorderQuoteListInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
Workorder c = Workorder.GetItem(i.LT_O_WorkorderQuote.Value);
if (IsDuplicateMapItem(c.ID, c.WorkorderQuote.QuoteNumber.ToString(), progress)) continue;
var ObjectTID = new TypeAndID(RootObjectTypes.WorkorderQuote, c.ID);
//make one on the server to update
var rMainObject = await util.PostAsync(RavenObjectName + "/Create?serial=" + c.WorkorderQuote.QuoteNumber);
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
dynamic d = new JObject();
d.concurrencyToken = util.CTokenFromResponse(rMainObject);
progress.Op(ObjectTypeName + " " + c.WorkorderQuote.QuoteNumber);
d.active = true;//probably can remove this at server, just stubbed in for now
Tagit(c.RegionID, tags);
SetTags(d, tags);
////Custom fields?
//if (ShouldExportCustom)
// d.customFields = CustomFieldData(c, DateCustomFields);
// var rMainObject = await util.PostAsync(RavenObjectName, d.ToString());
//Attachments / FILES
await ExportAttachments(ObjectTID, progress, util.AyaType.Quote);
//-----
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, util.AyaType.Quote);
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(RavenObjectName + "/" + RavenId.ToString(), d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.WorkOrder, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
//todo: workorder items etc
}
}
#endregion Quotes
#region PM Workorders
private async System.Threading.Tasks.Task ExportPMs(ProgressForm progress)
{
if (!progress.KeepGoing) return;
progress.Op("Start Preventive Maintenance export");
progress.SubOp("");
var ObjectTypeName = "Preventive Maintenance";
var RavenObjectName = "PM";
//TODO: this in the workorder Items loop
////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("WorkorderItem");
//bool ShouldExportCustom = ocf != null;
//var DateCustomFields = await ExportCustomFieldSchema(ocf, "WorkorderItem", "WorkOrderItem");
//Step 2: export the objects
WorkorderPMList pl = WorkorderPMList.GetList("");
progress.Append("Exporting " + pl.Count.ToString() + " Service " + ObjectTypeName + "s");
foreach (WorkorderPMList.WorkorderPMListInfo i in pl)
{
if (!progress.KeepGoing) return;
List<string> tags = new List<string>();
tags.Add(ImportTag);
Workorder c = Workorder.GetItem(i.LT_O_WorkorderPreventiveMaintenance.Value);
if (IsDuplicateMapItem(c.ID, c.WorkorderPreventiveMaintenance.PreventiveMaintenanceNumber.ToString(), progress)) continue;
var ObjectTID = new TypeAndID(RootObjectTypes.WorkorderPreventiveMaintenance, c.ID);
//make one on the server to update
var rMainObject = await util.PostAsync(RavenObjectName + "/Create?serial=" + c.WorkorderPreventiveMaintenance.PreventiveMaintenanceNumber);
long RavenId = util.IdFromResponse(rMainObject);
AddMap(c.ID, RavenId);
dynamic d = new JObject();
d.concurrencyToken = util.CTokenFromResponse(rMainObject);
progress.Op(ObjectTypeName + " " + c.WorkorderPreventiveMaintenance.PreventiveMaintenanceNumber);
d.active = true;//probably can remove this at server, just stubbed in for now
Tagit(c.RegionID, tags);
SetTags(d, tags);
////Custom fields?
//if (ShouldExportCustom)
// d.customFields = CustomFieldData(c, DateCustomFields);
// var rMainObject = await util.PostAsync(RavenObjectName, d.ToString());
//Attachments / FILES
await ExportAttachments(ObjectTID, progress, util.AyaType.PM);
//-----
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, util.AyaType.PM);
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(RavenObjectName + "/" + RavenId.ToString(), d.ToString());
//-----
//Event log fixup
await util.EventLog(util.AyaType.WorkOrder, RavenId, SafeGetUserMap(c.Creator), SafeGetUserMap(c.Modifier), c.Created, c.Modified);
//todo: workorder items etc
}
}
#endregion PM Workorders
#region locales
private async System.Threading.Tasks.Task ExportLocales(ProgressForm progress)
{
if (!progress.KeepGoing) return;
progress.Op("Start Locales export");
progress.SubOp("");
progress.Append("Exporting customized Locales");
////checksum locales
////if a recognized checksum then don't import because it means it wasn't modified from stock
///*
// Stock fresh trial db (fb) values:
// Locale Custom English [signature: -1965948581]
// Locale Deutsch [signature: -564065723]
// Locale English [signature: -1965948581]
// Locale Español [signature: -1122936791]
// Locale Français [signature: -679171126]
//Do not use these keys in hash calculation which were added / modified during various schema updates
// Global.Label.UseInventory.Description
// Locale.Label.LocaleFile
// UnitNameDisplayFormats.Label.ModelSerial
// UnitNameDisplayFormats.Label.SerialModel
// UnitNameDisplayFormats.Label.SerialModelVendor
// UnitNameDisplayFormats.Label.VendorModelSerial
// O.PartBin
//*/
//List<int> StockLocaleHashes = new List<int>();
//StockLocaleHashes.Add(-1965948581);
//StockLocaleHashes.Add(-564065723);
//StockLocaleHashes.Add(-1122936791);
//StockLocaleHashes.Add(-679171126);
//Get a list of RAVEN translations and ID's
var a = await util.GetAsync("Translation/List");
JArray ja = (JArray)a.ObjectResponse["data"];
var RavenLanguageList = ja.ToObject<List<util.NameIdItem>>();
LocaleList l = LocaleList.GetList();
foreach (LocaleList.LocaleListInfo i in l)
{
ResetUniqueNames();
if (!progress.KeepGoing) return;
LocalizedTextTable lt = LocalizedTextTable.Load(i.Locale);
progress.Op("Checking if locale " + i.Locale + " is customized");
if (!util.LocaleIsCustomized(i.Locale, lt, progress)) continue;
////calculate hash
//List<string> allStrings = new List<string>();
//foreach (var entry in lt.LT)
//{
// if(entry.Key=="Global.Label.UseInventory.Description") continue;
// if(entry.Key=="Locale.Label.LocaleFile") continue;
// if(entry.Key=="UnitNameDisplayFormats.Label.ModelSerial") continue;
// if(entry.Key=="UnitNameDisplayFormats.Label.SerialModel") continue;
// if(entry.Key=="UnitNameDisplayFormats.Label.SerialModelVendor") continue;
// if(entry.Key=="UnitNameDisplayFormats.Label.VendorModelSerial") continue;
// if (entry.Key == "O.PartBin") continue;
// allStrings.Add(entry.Value);
//}
//int CurrentLocaleHash = util.GetOrderIndependentHashCode<string>(allStrings);
//allStrings.Clear();
//if (StockLocaleHashes.Contains(CurrentLocaleHash)) continue;
//progress.Append("Locale " + i.Locale + " is customized [signature: "+CurrentLocaleHash.ToString()+"]; exporting");
//collection to hold items sent to server
List<UpdateTranslationItem> exportItems = new List<UpdateTranslationItem>();
//Iterate all RAVEN languages
for (int x = 1; x < 5; x++)//first four translations are the stock ones
{
//get raven name of locale
var RavenLocaleName = RavenLanguageList.Find(m => m.Id == x).Name;
//add stock locale mappings in case users are set to a stock one in v7
//so can set them later
//this is some half baked shit,it's intended for when users are exported later but it only works with stock locales
//so..not sure the exact point, maybe should just default all to english and let admin fix them later
//as they likely will have to anyway. Harmless though I guess so keeping
switch (RavenLocaleName)
{
case "en":
if (!LocaleMap.ContainsKey("English"))
LocaleMap.Add("English", x);
break;
case "fr":
if (!LocaleMap.ContainsKey("Français"))
LocaleMap.Add("Français", x);
break;
case "de":
if (!LocaleMap.ContainsKey("Deutsch"))
LocaleMap.Add("Deutsch", x);
break;
case "es":
if (!LocaleMap.ContainsKey("Español"))
LocaleMap.Add("Español", x);
break;
}
//MAKE A DUPLICATE
//name like this: "My custom (Espanol)" etc one for each target stock language
var exportName = GetUniqueName(i.Locale + " (" + RavenLocaleName + ")");
progress.SubOp("");
progress.Op("Exporting " + i.Locale + " to " + exportName);
var t = new util.NameIdItem { Name = exportName, Id = x };
a = await util.PostAsync("Translation/Duplicate", JObject.FromObject(t).ToString());
var targetTranslationId = util.IdFromResponse(a);
var ctoken = util.CTokenFromResponse(a);
//add to maps so can set user to it on export
//going to default to the English based one because
//that's the majority of the users
if (RavenLocaleName == "en" && !LocaleMap.ContainsKey(i.Locale))
LocaleMap.Add(i.Locale, targetTranslationId);
//Ok, have our target locale created, not we need to insert our custom translations one by one
var trans = ((JArray)a.ObjectResponse["data"]["translationItems"]).ToObject<List<TranslationItem>>();
var DuplicateAvoidanceList = new List<string>();
//SET MATCHING KEYS TO OUR TEXT
//iterate v7 locale items
foreach (var v7item in lt.LT)
{
progress.SubOp("Processing key: " + v7item.Key);
var v8key = Translatev7TranslationKey(v7item.Key);
if (v8key == "**SKIP**") continue;
if (!DuplicateAvoidanceList.Contains(v8key)) { DuplicateAvoidanceList.Add(v8key); }
else continue;
//System.Diagnostics.Debug.WriteLine("v7key:" + v7item.Key + " -> v8key: " + v8key);
TranslationItem v8TransItem = trans.FirstOrDefault(m => m.Key == v8key);
if (v8TransItem == null)
{
throw new ArgumentOutOfRangeException("On exporting custom locale " + i.Locale + " source key " + v7item.Key + ", destination key " + v8key + " was not found.");
}
//collect
exportItems.Add(new UpdateTranslationItem
{
Id = v8TransItem.Id,
ConcurrencyToken = v8TransItem.ConcurrencyToken,
NewText = v7item.Value
});
}
//update it
progress.SubOp("Posting translation " + exportName + " to server ");
await util.PutAsync("Translation/UpdateTranslationItemsDisplayText",
JArray.FromObject(exportItems).ToString());
progress.Op("");
progress.SubOp("");
}
}
progress.Op("");
progress.SubOp("");
}
#region locale utility
public class TranslationItem
{
public long Id { get; set; }
public uint ConcurrencyToken { get; set; }
public string Key { get; set; }
public string Display { get; set; }
public long TranslationId { get; set; }
}
public class UpdateTranslationItem
{
public long Id { get; set; }
public uint ConcurrencyToken { get; set; }
public string NewText { get; set; }
}
/// <summary>
/// Used by import, translate the old v7 translation key name into the new shorter version
/// </summary>
/// <param name="oldKey"></param>
/// <returns></returns>
public string Translatev7TranslationKey(string oldKey)
{
//skip keys definitely not in destination
//swaths:
if (oldKey.StartsWith("UI.ToolBar.")) return "**SKIP**";
if (oldKey.StartsWith("UI.Toolbar.")) return "**SKIP**";
// Custom English source key UI.Toolbar.ClientsToolBar, destination key ToolbarClientsToolBar was not found.
switch (oldKey)
{
// case "XXXX":
case "O.WikiPage": //skip over wikipage it's been dropped as it's an international term
case "UI.Command.LocalizedTextDesign":
case "O.WorkorderItemOutsideService":
case "O.WorkorderService.CloseByDate":
case "UI.Label.CurrentUserName":
case "UI.Go.Search":
case "ClientRequestTech.Label.ClientServiceRequestItemID":
return "**SKIP**";
}
string s = oldKey.Replace(".Label.", ".");
if (s.StartsWith("O."))
s = s.Replace("O.", "");
s = s.Replace(".ToolBar.", ".");
s = s.Replace(".Go.", ".");
s = s.Replace(".Command.", ".");
s = s.Replace(".Error.", ".");
s = s.Replace(".Object.", ".");
if (s.StartsWith("UI."))
s = s.Replace("UI.", "");
s = s.Replace(".", "");
s = s.Replace("AddressAddress", "Address");
s = s.Replace("ContactPhoneContactPhone", "ContactPhone");
s = s.Replace("ContactPhonePhone", "ContactPhone");
s = s.Replace("PurchaseOrderPurchaseOrder", "PurchaseOrder");
s = s.Replace("WorkorderItemMiscExpenseExpense", "WorkorderItemMiscExpense");
s = s.Replace("WorkorderItemTravelTravel", "WorkorderItemTravel");
s = s.Replace("DashboardDashboard", "Dashboard");
//ScheduleMarkers -> Reminder
s = s.Replace("ScheduleMarkerScheduleMarker", "ScheduleMarker");
s = s.Replace("ScheduleMarker", "Reminder");
s = s.Replace("ScheduleMarkerARGB", "ReminderARGB");
s = s.Replace("ScheduleMarkerColor", "ReminderColor");
s = s.Replace("ScheduleMarkerCompleted", "ReminderCompleted");
s = s.Replace("ScheduleMarkerEventCreated", "ReminderEventCreated");
s = s.Replace("ScheduleMarkerEventPendingAlert", "ReminderEventPendingAlert");
s = s.Replace("ScheduleMarkerFollowUp", "ReminderFollowUp");
s = s.Replace("ScheduleMarkerList", "ReminderList");
s = s.Replace("ScheduleMarkerName", "ReminderName");
s = s.Replace("ScheduleMarkerNotes", "ReminderNotes");
s = s.Replace("ScheduleMarkerRecurrence", "ReminderRecurrence");
s = s.Replace("ScheduleMarkerScheduleMarkerSourceType", "ReminderSourceType");
s = s.Replace("ScheduleMarkerSourceID", "ReminderSourceID");
s = s.Replace("ScheduleMarkerStartDate", "ReminderStartDate");
s = s.Replace("ScheduleMarkerStopDate", "ReminderStopDate");
s = s.Replace("ScheduleEditScheduleMarker", "ScheduleEditReminder");
s = s.Replace("ScheduleNewScheduleMarker", "ScheduleNewReminder");
//Custom fields were 0 to 9, now 1 to 16
s = s.Replace("Custom9", "Custom10");
s = s.Replace("Custom8", "Custom9");
s = s.Replace("Custom7", "Custom8");
s = s.Replace("Custom6", "Custom7");
s = s.Replace("Custom5", "Custom6");
s = s.Replace("Custom4", "Custom5");
s = s.Replace("Custom3", "Custom4");
s = s.Replace("Custom2", "Custom3");
if (!s.EndsWith("Custom10"))
s = s.Replace("Custom1", "Custom2");
s = s.Replace("Custom0", "Custom1");
//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");
s = s.Replace("UserUserType", "UserType");
s = s.Replace("UserTypesUtilityNotification", "UserTypesUtility");
//Localized -> Translation
s = s.Replace("LocaleCustomizeText", "TranslationCustomizeText");
s = s.Replace("LocaleExport", "TranslationExport");
s = s.Replace("LocaleImport", "TranslationImport");
s = s.Replace("LocaleList", "TranslationList");
s = s.Replace("LocaleLocaleFile", "TranslationFile");
s = s.Replace("LocaleUIDestLocale", "TranslationDest");
s = s.Replace("LocaleUISourceLocale", "TranslationSource");
s = s.Replace("LocaleWarnLocaleLocked", "TranslationWarnLocked");
s = s.Replace("LocalizedTextDisplayText", "TranslationDisplayText");
s = s.Replace("LocalizedTextDisplayTextCustom", "TranslationDisplayTextCustom");
s = s.Replace("LocalizedTextKey", "TranslationKey");
s = s.Replace("LocalizedTextLocale", "Translation");
s = s.Replace("LocalizedText", "TranslatedText");
//items that came up after moving this to v8 export plugin
s = s.Replace("DateRangeInTheLastYear", "DateRangePastYear");
s = s.Replace("ToolbarCustomizeDialog", "CustomizeDialog");
s = s.Replace("Client", "Customer");
s = s.Replace("LoanItem", "LoanUnit");
s = s.Replace("WorkorderPreventiveMaintenance", "PM");
s = s.Replace("WorkorderQuote", "Quote");
s = s.Replace("WorkorderService", "Workorder");
s = s.Replace("Workorder", "WorkOrder");
s = s.Replace("CustomerNoteCustomerNoteTypeID", "CustomerNoteTypeId");
s = s.Replace("CustomerRequestPartCustomerServiceRequestItemID", "CustomerRequestItemId");
s = s.Replace("WorkOrderItemMiscExpense", "WorkOrderItemExpense");
s = s.Replace("WorkOrderItemLoanLoan", "WorkOrderItemLoan");
s = s.Replace("WorkOrderItemLaborLabor", "WorkOrderItemLabor");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
//FUTURE
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
// s = s.Replace("WASXXX", "NOWXXXX");
return s;
}
#endregion locale utility
#endregion locales
#region TAG ITEMS
#region Unitmodelcategories
private void ExportUnitModelCategories(ProgressForm progress)
{
ResetUniqueNames();
UnitModelCategories l = UnitModelCategories.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Unit model categories");
foreach (UnitModelCategory i in l) TagMap.Add(i.ID, util.NormalizeTag(GetUniqueName(i.Name) + "." + "unitmodelcategory"));
}
#endregion
#region Unitservicetypes
private void ExportUnitServiceTypes(ProgressForm progress)
{
ResetUniqueNames();
UnitServiceTypes l = UnitServiceTypes.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Unit service types");
foreach (UnitServiceType i in l)
TagMap.Add(i.ID, util.NormalizeTag(GetUniqueName(i.Name) + "." + "unitservicetype"));
}
#endregion
#region WorkorderItemTypes
private void ExportWorkorderItemTypes(ProgressForm progress)
{
ResetUniqueNames();
WorkorderItemTypes l = WorkorderItemTypes.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Workorder item types");
foreach (WorkorderItemType i in l)
TagMap.Add(i.ID, util.NormalizeTag(GetUniqueName(i.Name) + "." + "workorderitemtype"));
}
#endregion
#region REGIONS
private void ExportRegions(ProgressForm progress)
{
ResetUniqueNames();
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(GetUniqueName(i.LT_Region_Label_Name.Display) + "." + "region"));
}
#endregion
#region Client groups
private void ExportClientGroups(ProgressForm progress)
{
ResetUniqueNames();
ClientGroups l = ClientGroups.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Client groups");
foreach (ClientGroup i in l)
TagMap.Add(i.ID, util.NormalizeTag(GetUniqueName(i.Name) + "." + "clientgroup"));
}
#endregion
#region Workorder categories
private void ExportWorkorderCategories(ProgressForm progress)
{
ResetUniqueNames();
WorkorderCategories l = WorkorderCategories.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Workorder categories");
foreach (WorkorderCategory i in l)
TagMap.Add(i.ID, util.NormalizeTag(GetUniqueName(i.Name) + "." + "workordercategory"));
}
#endregion
#region Part categories
private void ExportPartCategories(ProgressForm progress)
{
ResetUniqueNames();
PartCategories l = PartCategories.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " Part categories");
foreach (PartCategory i in l) TagMap.Add(i.ID, util.NormalizeTag(GetUniqueName(i.Name) + "." + "partcategory"));
}
#endregion
#region ScheduleableUserGroups
private void ExportScheduleableUserGroups(ProgressForm progress)
{
ResetUniqueNames();
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(GetUniqueName(i.Name) + "." + "partcategory"));
}
#endregion clients
#region Dispatch zones
private void ExportDispatchZones(ProgressForm progress)
{
ResetUniqueNames();
DispatchZones l = DispatchZones.GetItems(false);
progress.Append("Compiling " + l.Count.ToString() + " Dispatch zones");
foreach (DispatchZone i in l)
TagMap.Add(i.ID, util.NormalizeTag(GetUniqueName(i.Name) + "." + "dispatchzone"));
}
#endregion
private void ExportUserSkills(ProgressForm progress)
{
ResetUniqueNames();
UserSkills l = UserSkills.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " User skills");
foreach (UserSkill i in l)
TagMap.Add(i.ID, util.NormalizeTag(GetUniqueName(i.Name) + "." + "user-skill"));
}
private void ExportUserCertifications(ProgressForm progress)
{
ResetUniqueNames();
UserCertifications l = UserCertifications.GetItems();
progress.Append("Compiling " + l.Count.ToString() + " User certifications");
foreach (UserCertification i in l)
TagMap.Add(i.ID, util.NormalizeTag(GetUniqueName(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>();
if (ocf == null) return ret;
//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("form-custom/" + RavenCustomTranslationKeyObjectName);
var ctoken = util.CTokenFromResponse(a);
d.concurrencyToken = ctoken;
await util.PutAsync("form-custom/" + RavenCustomTranslationKeyObjectName, d.ToString());
return ret;
}
#endregion custom fields
#region Attachments exporter
private async System.Threading.Tasks.Task ExportAttachments(TypeAndID tid, ProgressForm progress, util.AyaType specificRavenType = util.AyaType.NoType)
{
if (!WikiPage.HasWiki(tid.ID)) return;
WikiPage w = WikiPage.GetItem(tid);
AyaFileList fl = AyaFileList.GetList(w.ID);
if (fl.Count == 0) return;
//iterate the files
foreach (AyaFileList.AyaFileListInfo i in fl)
{
if (!progress.KeepGoing) return;
var af = AyaFile.GetItem(i.LT_O_AyaFile.Value);
if (af == null) continue;
progress.SubOp("Wikifile: \"" + af.Name + "\" " + AyaBizUtils.FileSizeDisplay((decimal)af.FileSize));
if (IsDuplicateMapItem(i.LT_O_AyaFile.Value, i.LT_O_AyaFile.Display, progress)) continue;
//Compile the FileData property
var sDate = i.LT_Common_Label_Created.ToString();
DateTimeOffset dtLastModified = DateTime.UtcNow;
if (sDate != null)
{
//parse out to UTC date
DateTime dt = new DateTime();
if (DateTime.TryParse(sDate, out dt))
{
dtLastModified = dt.ToUniversalTime();
}
}
dynamic dFileData = new JArray();
dynamic dFile = new JObject();
dFile.name = af.Name;
dFile.lastModified = dtLastModified.ToUnixTimeMilliseconds();
dFileData.Add(dFile);
//Upload
MultipartFormDataContent formDataContent = new MultipartFormDataContent();
//Form data like the bizobject type and id
string RavenTypeAsString = "";
if (specificRavenType != util.AyaType.NoType)
RavenTypeAsString = ((int)specificRavenType).ToString();
else
RavenTypeAsString = ((int)util.RootObjectToAyaType(tid.RootObjectType)).ToString();
formDataContent.Add(new StringContent(RavenTypeAsString), name: "AttachToObjectType");
formDataContent.Add(new StringContent(Map[tid.ID].ToString()), name: "AttachToObjectId");
formDataContent.Add(new StringContent(ImportTag), name: "Notes");
formDataContent.Add(new StringContent(dFileData.ToString()), name: "FileData");
StreamContent AttachmentFile = new StreamContent(af.GetContent());
//try to get a more accurate mimetype than was originally
//in v7 as it uses the same method but from long ago and far far away...
string MType = af.mimeType;
try
{
MType = MimeTypeMap.GetMimeType(Path.GetExtension(af.Name));//latest up to date mime type
}
catch { }
AttachmentFile.Headers.ContentType = new MediaTypeHeaderValue(MType);
AttachmentFile.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
AttachmentFile.Headers.ContentDisposition.FileName = af.Name;
AttachmentFile.Headers.ContentDisposition.ModificationDate = dtLastModified;
formDataContent.Add(AttachmentFile);
//Upload
var a = await util.PostFormDataAsync("attachment", formDataContent);
//Map it for later processing of wiki
//attachment upload route returns all attachments for this object in file name order
//so need to find *our* most recent uploaded attachment so need to find the highest raven id number
var returnArray = ((JArray)a.ObjectResponse["data"]);
var ravenId = -1L;
foreach (JObject o in returnArray)
{
var oId = o["id"].Value<long>();
if (oId > ravenId) ravenId = oId;
}
AddMap(af.ID, ravenId);
}
progress.SubOp("");
}
#endregion attachments
#region Assigned docs exporter
private async System.Threading.Tasks.Task<string> ExportDocs(TypeAndID tid, AssignedDocs docs, ProgressForm progress, util.AyaType specificRavenType = util.AyaType.NoType)
{
if (!ExportAssignedDocs) return null;
if (docs.Count == 0) return null;
string NonFileUrls = string.Empty;
//iterate the files
foreach (AssignedDoc doc in docs)
{
if (!progress.KeepGoing) return null;
//is it a local file?
if (!new Uri(doc.URL).IsFile)
{
NonFileUrls += (doc.Description + "(" + ImportTag + ")\n" + doc.URL + "\n");
continue;
}
//can we see it?
if (!File.Exists(doc.URL))
{
NonFileUrls += (ImportTag + " - Assigned doc. file not found:\n" + doc.Description + "\n" + doc.URL + "\n");
continue;
}
//get the file info
FileInfo fi = new FileInfo(doc.URL);
progress.SubOp("Assigned doc: \"" + doc.URL + "\" " + AyaBizUtils.FileSizeDisplay((decimal)fi.Length));
//Compile the FileData property
DateTimeOffset dtLastModified = fi.LastWriteTimeUtc;
dynamic dFileData = new JArray();
dynamic dFile = new JObject();
dFile.name = fi.Name;
dFile.lastModified = dtLastModified.ToUnixTimeMilliseconds();
dFileData.Add(dFile);
//Upload
MultipartFormDataContent formDataContent = new MultipartFormDataContent();
//Form data like the bizobject type and id
string RavenTypeAsString = "";
if (specificRavenType != util.AyaType.NoType)
RavenTypeAsString = ((int)specificRavenType).ToString();
else
RavenTypeAsString = ((int)util.RootObjectToAyaType(tid.RootObjectType)).ToString();
formDataContent.Add(new StringContent(RavenTypeAsString), name: "AttachToObjectType");
formDataContent.Add(new StringContent(Map[tid.ID].ToString()), name: "AttachToObjectId");
formDataContent.Add(new StringContent(doc.Description + " (" + ImportTag + ")"), name: "Notes");
formDataContent.Add(new StringContent(dFileData.ToString()), name: "FileData");
StreamContent AttachmentFile = new StreamContent(fi.OpenRead());
AttachmentFile.Headers.ContentType = new MediaTypeHeaderValue(MimeTypeMap.GetMimeType(fi.Extension));
AttachmentFile.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
AttachmentFile.Headers.ContentDisposition.FileName = fi.Name;
AttachmentFile.Headers.ContentDisposition.ModificationDate = dtLastModified;
formDataContent.Add(AttachmentFile);
//Upload
await util.PostFormDataAsync("attachment", formDataContent);
//No need to map it or save response as long as it works that's all that matters
}
progress.SubOp("");
return NonFileUrls;
}
#endregion assigned docs
#region WIKI page exporter
//WIKI
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 null;
//TODO: fixup internal urls using MAP of file attachment uploads
MatchCollection mc = AyaBizUtils.rxAyaImageTags.Matches(content);
foreach (Match m in mc)
{
var RavenId = Map[new Guid(m.Groups["guid"].Value)];
content = content.Replace(m.Value, "<img src=\"" + "[ATTACH:" + RavenId.ToString() + "]" + "\">");
}
//todo: fixup font size, try to convert to heading tags instead
//figure out how to remove the inline style tag as it comes through for some reason
//TODO: Convert to Markdown format
//found 2 likely candidate libs to do this
//https://www.nuget.org/packages/Html2Markdown/
//https://www.nuget.org/packages/ReverseMarkdown/
//Not much difference at first glance, very similar stats, reverse markdown is a little more widely used and seems to have more config options
//built in, the other has to make some kind of processor for some stuff maybe so going with reverse for now
//NOTE: for this to work had to add an assembly redirect in app.config for ayanova project as it was looking for a really old version of
//the HtmlAgilityPack
var config = new ReverseMarkdown.Config
{
UnknownTags = ReverseMarkdown.Config.UnknownTagsOption.Bypass,
GithubFlavored = true, // generate GitHub flavoured markdown, supported for BR, PRE and table tags
RemoveComments = true, // will ignore all comments, (narrator: "It doesn't")
SmartHrefHandling = true // remove markdown output for links where appropriate
};
var converter = new ReverseMarkdown.Converter(config);
string res = converter.Convert(content);
//strip out comment and style chunk that is left behind by above tool
//style is an artifact of the rtf2html converter used by v7
int nStart = res.IndexOf("<!--");
int nEnd = res.IndexOf("-->");
if (nStart != -1 && nEnd != -1)
{
res = res.Substring(0, nStart) + res.Substring(nEnd + 3);
// res = newRes;
}
return res;
}
#region sample before and after
/*
* INPUT
* <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Untitled document</title>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<style type="text/css">
<!--
span.st1
{
font-family: Arial;
font-size: 39pt;
color: #000000;
}
span.st2
{
font-family: Arial;
font-size: 8pt;
color: #000000;
}
span.st3
{
font-family: Arial;
font-size: 6pt;
color: #000000;
}
span.st4
{
font-family: Arial;
font-size: 150pt;
color: #000000;
}
span.st5
{
font-family: Arial;
font-size: 8pt;
color: #ff0000;
}
span.st6
{
font-family: Arial;
font-size: 8pt;
color: #00ff00;
}
span.st7
{
font-family: Arial;
font-size: 8pt;
color: #000080;
}
span.st8
{
font-family: Symbol;
font-size: 8pt;
color: #000080;
}
span.st9
{
font-family: Consolas;
font-size: 8pt;
color: #000000;
}
span.st10
{
font-family: Comic Sans MS;
font-size: 8pt;
color: #000000;
}
span.st11
{
font-family: Comic Sans MS;
font-size: 16pt;
color: #000000;
}
span.st12
{
font-family: Arial;
font-size: 32pt;
color: #000000;
}
span.st13
{
font-family: Times New Roman;
font-size: 12pt;
color: #000000;
}
-->
</style>
</head>
<body>
<div><span class="st1"><b><u>Here is a title</u></b></span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2">This document has all possible options on it except for picking every single font size so instead</span><span class="st3"> here is the smallest font size which is 6</span></div>
<div><span class="st3">and here is the</span><span class="st4"> largest font size which is 150</span></div>
<div><span class="st3"></span>&nbsp;</div>
<div><span class="st2"><i>italics </i>and <u>underlined </u>and <b>bold</b></span></div>
<div><span class="st2"><b></b></span>&nbsp;</div>
<div><span class="st2"><b></b></span><span class="st5"><b>red </b></span></div>
<div><span class="st2"><b></b></span>&nbsp;</div>
<div><span class="st6"><b>green </b></span></div>
<div><span class="st2"><b></b></span>&nbsp;</div>
<div><span class="st2"><b></b></span><span class="st7"><b>blue</b></span></div>
<div><span class="st7"><b></b></span>&nbsp;</div>
<div><span class="st7"><b></b></span></div>
<ul style="list-style-type: none">
<li><span class="st8"><b>·&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b></span><span class="st7"><b>List one</b></span></li>
<li><span class="st7"><b></b></span><span class="st8"><b>·&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b></span><span class="st7"><b>list two </b></span></li>
<li><span class="st7"><b></b></span><span class="st8"><b>·&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</b></span><span class="st7"><b>list three</b></span></li>
</ul><div><span class="st7"><b></b></span></div>
<div><span class="st7"><b></b></span>&nbsp;</div>
<div><span class="st2"><b></b></span>&nbsp;</div>
<div><span class="st2"><b></b></span>&nbsp;</div>
<div><span class="st2">Arial font</span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span><span class="st9">Consolas font</span></div>
<div><span class="st9"></span>&nbsp;</div>
<div><span class="st9"></span><span class="st10">Comic &nbsp;sans</span></div>
<div><span class="st10"></span>&nbsp;</div>
<div><span class="st10"></span><span class="st11">font size 16 double default size whih is 8 </span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span><span class="st12">font size 32 which is quadruple default of 8</span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2">This block is</span></div>
<div><span class="st2">left aligned</span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span>&nbsp;</div>
<div align="center"><span class="st2">this block is </span></div>
<div align="center"><span class="st2">center aligned</span></div>
<div><span class="st2"></span>&nbsp;</div>
<div align="right"><span class="st2">This block is </span></div>
<div align="right"><span class="st2">right aligned</span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2"> &nbsp;<img src="[ATTACH:4]"></span><span class="st13">Wiki page - User: AyaNova Administrator</span></div>
<div><span class="st13"></span>&nbsp;</div>
<div><span class="st13">and more:</span></div>
<div><span class="st13"></span><span class="st2"> <img src="[ATTACH:4]"></span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st2">and more</span></div>
<div><span class="st2"> &nbsp;<img src="[ATTACH:4]"></span></div>
<div><span class="st2"></span>&nbsp;</div>
<div><span class="st13"></span></div></body>
</html>
========================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Untitled document</title>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<style type="text/css">
<!--
span.st1
{
font-family: Times New Roman;
font-size: 20pt;
color: #000000;
}
span.st2
{
font-family: Times New Roman;
font-size: 18pt;
color: #000000;
}
span.st3
{
font-family: Times New Roman;
font-size: 10pt;
color: #000000;
}
span.st4
{
font-family: Times New Roman;
font-size: 24pt;
color: #000000;
}
span.st5
{
font-family: Times New Roman;
font-size: 12pt;
color: #000000;
}
-->
</style>
</head>
<body>
<div><span class="st1">Wiki page - User: Eva Alexander - ALL REGIONS</span></div>
<div><span class="st2"></span><span class="st3">Here is some under title text</span></div>
<div><span class="st3"></span>&nbsp;</div>
<div><span class="st3"></span><span class="st4">Here is another title</span></div>
<div><span class="st3"></span>&nbsp;</div>
<div><span class="st3">Here is some more under title text.</span></div>
<div><span class="st3">Some more lines</span></div>
<div><span class="st3">like this one</span></div>
<div><span class="st3">and this one</span></div>
<div><span class="st3"></span>&nbsp;</div>
<div><span class="st5"></span></div></body>
</html>
=-=-=-==-
*
*
*
output
* Untitled document<!--<br>span.st1
{
font-family: Arial;
font-size: 39pt;
color: #000000;
}<br>span.st2
{
font-family: Arial;
font-size: 8pt;
color: #000000;
}<br>span.st3
{
font-family: Arial;
font-size: 6pt;
color: #000000;
}<br>span.st4
{
font-family: Arial;
font-size: 150pt;
color: #000000;
}<br>span.st5
{
font-family: Arial;
font-size: 8pt;
color: #ff0000;
}<br>span.st6
{
font-family: Arial;
font-size: 8pt;
color: #00ff00;
}<br>span.st7
{
font-family: Arial;
font-size: 8pt;
color: #000080;
}<br>span.st8
{
font-family: Symbol;
font-size: 8pt;
color: #000080;
}<br>span.st9
{
font-family: Consolas;
font-size: 8pt;
color: #000000;
}<br>span.st10
{
font-family: Comic Sans MS;
font-size: 8pt;
color: #000000;
}<br>span.st11
{
font-family: Comic Sans MS;
font-size: 16pt;
color: #000000;
}<br>span.st12
{
font-family: Arial;
font-size: 32pt;
color: #000000;
}<br>span.st13
{
font-family: Times New Roman;
font-size: 12pt;
color: #000000;
}<br>-->
**Here is a title**
This document has all possible options on it except for picking every single font size so instead here is the smallest font size which is 6
and here is the largest font size which is 150
*italics*and underlined and **bold**
**red**
**green**
**blue**
- **·****List one**
- **·****list two**
- **·****list three**
Arial font
Consolas font
Comic  sans
font size 16 double default size whih is 8
font size 32 which is quadruple default of 8
This block is
left aligned
this block is
center aligned
This block is
right aligned
![]([ATTACH:4])Wiki page - User: AyaNova Administrator
and more:
![]([ATTACH:4])
and more
![]([ATTACH:4])
=========================
Untitled document<!--<br>span.st1
{
font-family: Times New Roman;
font-size: 20pt;
color: #000000;
}<br>span.st2
{
font-family: Times New Roman;
font-size: 18pt;
color: #000000;
}<br>span.st3
{
font-family: Times New Roman;
font-size: 10pt;
color: #000000;
}<br>span.st4
{
font-family: Times New Roman;
font-size: 24pt;
color: #000000;
}<br>span.st5
{
font-family: Times New Roman;
font-size: 12pt;
color: #000000;
}<br>-->
Wiki page - User: Eva Alexander - ALL REGIONS
Here is some under title text
Here is another title
Here is some more under title text.
Some more lines
like this one
and this one
*
*/
#endregion sample
#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 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 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 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
}