477 lines
17 KiB
C#
477 lines
17 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 ICSharpCode.SharpZipLib.Zip;
|
|
|
|
namespace AyaNova.Plugin.Dump
|
|
{
|
|
class Dump : IAyaNovaPlugin
|
|
{
|
|
|
|
#region Plugin interface
|
|
System.Resources.ResourceManager resman = null;
|
|
private static List<RootObjectTypes> ObjectsWeCanDealWith = null;
|
|
|
|
|
|
public string PluginName
|
|
{
|
|
get { return "DBDump export database"; }
|
|
}
|
|
|
|
public string PluginVersion
|
|
{
|
|
get { return "7.5"; }
|
|
}
|
|
|
|
public string About
|
|
{
|
|
get
|
|
{
|
|
return "AyaNova DBDump plugin\r\n" +
|
|
"Built " + AyaNova.PlugIn.Dump.Timestamp.BuildAt.ToString() + "\r\n" +
|
|
"Copyright 2018 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("This DBDump plugin requires AyaNova version 7.5 or newer");
|
|
return false;
|
|
}
|
|
|
|
if (AyaNovaVersion.Minor < 5)
|
|
{
|
|
MessageBox.Show("This DBDump plugin requires AyaNova version 7.5 or newer");
|
|
return false;
|
|
}
|
|
|
|
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("DBDump", "Dump database to export file", 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 (!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 could 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 could result in damaged data. ***");
|
|
}
|
|
|
|
//Only one command
|
|
DumpIt();
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <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 void DumpIt()
|
|
{
|
|
|
|
string dumpname = "ayanova.data.dump." + DateTime.Now.ToString("yyyy-MM-d--HH-mm-ss");
|
|
string dumpfolder = string.Empty;
|
|
#if(DEBUG)
|
|
dumpfolder = @"c:\temp";
|
|
#else
|
|
MessageBox.Show("Select a location to dump AyaNova data");
|
|
using (var folderDialog = new FolderBrowserDialog())
|
|
{
|
|
if (folderDialog.ShowDialog() == DialogResult.OK)
|
|
{
|
|
dumpfolder = folderDialog.SelectedPath;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
//create a temporary folder to generate JSON in
|
|
string tempArchiveFolder = dumpfolder + Path.DirectorySeparatorChar + dumpname;
|
|
string zipName = dumpfolder + Path.DirectorySeparatorChar + dumpname + ".zip";
|
|
makeFolderIfNotExist(tempArchiveFolder, true);
|
|
|
|
//Show progress form
|
|
|
|
ProgressForm progress = new ProgressForm();
|
|
progress.Show();
|
|
progress.StartedImport();
|
|
progress.Append("Dumping data to " + tempArchiveFolder);
|
|
|
|
|
|
//DUMP IT!
|
|
dumpGlobalSettings(tempArchiveFolder, progress);
|
|
dumpLocales(tempArchiveFolder, progress);
|
|
dumpRegions(tempArchiveFolder, progress);
|
|
dumpSeedNumbers(tempArchiveFolder, progress);
|
|
dumpClients(tempArchiveFolder, progress);
|
|
dumpHeadOffices(tempArchiveFolder, progress);
|
|
|
|
|
|
|
|
progress.Append("Zipping up archive");
|
|
FastZip fastZip = new FastZip();
|
|
fastZip.CreateZip(zipName, tempArchiveFolder, true, null);
|
|
|
|
progress.Append("Cleaning up temporary folder");
|
|
Directory.Delete(tempArchiveFolder, true);
|
|
|
|
progress.Append("Dump completed");
|
|
progress.FinishedImport();
|
|
|
|
//-----------------------------------
|
|
//endof method
|
|
}
|
|
|
|
|
|
|
|
|
|
#region Object dump methods
|
|
|
|
#region Global settings
|
|
private void dumpGlobalSettings(string tempArchiveFolder, ProgressForm progress)
|
|
{
|
|
List<string> objectExcludeProperties = new List<string>(standardExcludePropertiesList);
|
|
progress.Append("Dumping Global Settings");
|
|
DumpObjectToFolder(tempArchiveFolder, AyaBizUtils.GlobalSettings, "globalsettings", objectExcludeProperties);
|
|
}
|
|
#endregion globalsettings
|
|
|
|
#region locales
|
|
private void dumpLocales(string tempArchiveFolder, 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, "locale." + EnsureValidFileName(i.Locale), objectExcludeProperties, "GZTW.AyaNova.BLL.Locale");
|
|
}
|
|
}
|
|
}
|
|
#endregion locales
|
|
|
|
#region REGIONS
|
|
private void dumpRegions(string tempArchiveFolder, ProgressForm progress)
|
|
{
|
|
List<string> objectExcludeProperties = new List<string>(standardExcludePropertiesList);
|
|
objectExcludeProperties.Add("ContractName");
|
|
objectExcludeProperties.Add("uiHasTechNotes");
|
|
RegionList l = RegionList.GetList(string.Empty);
|
|
progress.Append("Dumping " + l.Count.ToString() + " Regions");
|
|
foreach (RegionList.RegionListInfo i in l)
|
|
{
|
|
|
|
Region o = Region.GetItem(i.LT_Region_Label_Name.Value);
|
|
DumpObjectToFolder(tempArchiveFolder, o, "region." + o.ID.ToString(), objectExcludeProperties);
|
|
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#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 dumpSeedNumbers(string tempArchiveFolder, 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, "GZTW.AyaNova.BLL.Seed");
|
|
}
|
|
#endregion globalsettings
|
|
|
|
#region clients
|
|
private void dumpClients(string tempArchiveFolder, ProgressForm progress)
|
|
{
|
|
List<string> objectExcludeProperties = new List<string>(standardExcludePropertiesList);
|
|
objectExcludeProperties.Add("ContractName");
|
|
objectExcludeProperties.Add("uiHasTechNotes");
|
|
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);
|
|
|
|
}
|
|
}
|
|
#endregion clients
|
|
|
|
#region headoffices
|
|
private void dumpHeadOffices(string tempArchiveFolder, ProgressForm progress)
|
|
{
|
|
List<string> excludes = new List<string>(standardExcludePropertiesList);
|
|
//excludes.Add("ContractInEffect");
|
|
//excludes.Add("uiHasTechNotes");
|
|
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);
|
|
}
|
|
}
|
|
#endregion clients
|
|
|
|
|
|
|
|
#endregion object dump methods
|
|
|
|
|
|
#region Dump
|
|
|
|
/// <summary>
|
|
/// Write out the object properties as JSON
|
|
/// </summary>
|
|
/// <param name="tempArchiveFolder"></param>
|
|
/// <param name="o"></param>
|
|
private void DumpObjectToFolder(string tempArchiveFolder, object o, string objectFileName, List<string> excludeProperties, string forceTypeString = "")
|
|
{
|
|
|
|
var typestring = o.GetType().ToString();
|
|
if (!string.IsNullOrWhiteSpace(forceTypeString))
|
|
{
|
|
typestring = forceTypeString;
|
|
}
|
|
|
|
var dumpFolder = tempArchiveFolder + Path.DirectorySeparatorChar + typestring;
|
|
makeFolderIfNotExist(dumpFolder);
|
|
|
|
var outputFileName = dumpFolder + Path.DirectorySeparatorChar + objectFileName + ".json";
|
|
|
|
JsonSerializer serializer = new JsonSerializer();
|
|
serializer.NullValueHandling = NullValueHandling.Include;
|
|
serializer.ContractResolver = new ExcludeNamedPropertiesContractResolver(excludeProperties);
|
|
serializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
|
|
|
|
|
|
#if(DEBUG)
|
|
serializer.Formatting = Formatting.Indented;
|
|
#endif
|
|
// serializer.Converters.Add(new JavaScriptDateTimeConverter());
|
|
// serializer.NullValueHandling = NullValueHandling.Ignore;
|
|
|
|
//generate file name, should be ID of object plus .json
|
|
|
|
|
|
using (StreamWriter sw = new StreamWriter(outputFileName))
|
|
using (JsonWriter writer = new JsonTextWriter(sw))
|
|
{
|
|
serializer.Serialize(writer, o);
|
|
// {"ExpiryDate":new Date(1230375600000),"Price":0}
|
|
}
|
|
}
|
|
|
|
#endregion dump
|
|
|
|
#region Utility methods
|
|
|
|
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
|
|
|
|
#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
|
|
|
|
|
|
//eoc
|
|
|
|
|
|
|
|
}
|
|
|
|
//eons
|
|
}
|