🌟 ExportAllTheThings - Export Your Custom Objects

4 Likes

Done. Not in the library yet, but here ya go…

ExportAllTheThings.ExportAllKineticCustomLayers
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    ExportAllKineticCustomLayers
* Description: This plugin downloads all custom Kinetic layers.
* ==========================================================================================
* 
* INPUTS: NONE
*
* OUTPUTS:
*   BOOL:   Success        -> Function Success / Failure
*   STRING: ListErrorsJson -> Json Serialized List<Exception>
*   STRING: ZipBase64      -> Base64 Encoded Byte Array
*
* CHANGELOG:
* 09/04/2024 | klincecum | Kevin Lincecum | Initial Implementation
*
* ==========================================================================================
*/
  //Helper Functions Section----------------------------------------------------------------------------------------------------------------------------------------->
  Func<Exception, string, string> AddExceptionToList = (exception, exceptionListJson) =>
  {
      List<Exception> exceptionList = new List<Exception>(){exception};
      if(!String.IsNullOrEmpty(exceptionListJson)) { try { exceptionList.AddRange( JsonConvert.DeserializeObject<List<Exception>>(exceptionListJson) ); } catch {} }
      return JsonConvert.SerializeObject(exceptionList);
  };
  //<-----------------------------------------------------------------------------------------------------------------------------------------Helper Functions Section
 
 
  try
  {
  //****
  
     CallService<Ice.Contracts.MetaFXSvcContract>(metaFX =>
     {
        //Create a request to list the apps       
        var request = new Epicor.MetaFX.Core.Models.Applications.ApplicationRequest()
        {
            Type = "view",
            SubType = "",
            SearchText = "",
            IncludeAllLayers = true
        };

        //Get a list of apps
        List<Epicor.MetaFX.Core.Models.Applications.Application> applications = metaFX.GetApplications(request);
        
        //Create an export request list 
        List<Epicor.MetaFX.Core.Models.Layers.EpMetaFxLayerForApplication> applicationList = new List<Epicor.MetaFX.Core.Models.Layers.EpMetaFxLayerForApplication>();

        //Loop through the list and add custom apps to the export list
        foreach(var item in applications.Where(x => x.SystemFlag == false))
        {
            applicationList.Add(new Epicor.MetaFX.Core.Models.Layers.EpMetaFxLayerForApplication() { Id = item.Id });
        }
        
        //Export the apps and return the zip file data as a Base64 encoded string.
        ZipBase64 = metaFX.ExportLayers(applicationList);
     }); 
     
     Success = true;
     
  //****   
  }
  catch (Exception ex)
  {
      Success = false;
      ListErrorJson = AddExceptionToList(ex, ListErrorJson);
  }
  finally
  {
      //Maybe later?
  }
ExportAllTheThings.ExportAllKineticSystemLayers
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    ExportAllKineticSystemLayers
* Description: This plugin downloads all system Kinetic layers.
* ==========================================================================================
* 
* INPUTS: NONE
*
* OUTPUTS:
*   BOOL:   Success        -> Function Success / Failure
*   STRING: ListErrorsJson -> Json Serialized List<Exception>
*   STRING: ZipBase64      -> Base64 Encoded Byte Array
*
* CHANGELOG:
* 09/04/2024 | klincecum | Kevin Lincecum | Initial Implementation
*
* ==========================================================================================
*/
  //Helper Functions Section----------------------------------------------------------------------------------------------------------------------------------------->
  Func<Exception, string, string> AddExceptionToList = (exception, exceptionListJson) =>
  {
      List<Exception> exceptionList = new List<Exception>(){exception};
      if(!String.IsNullOrEmpty(exceptionListJson)) { try { exceptionList.AddRange( JsonConvert.DeserializeObject<List<Exception>>(exceptionListJson) ); } catch {} }
      return JsonConvert.SerializeObject(exceptionList);
  };
  //<-----------------------------------------------------------------------------------------------------------------------------------------Helper Functions Section
 
 
  try
  {
  //****
  
     CallService<Ice.Contracts.MetaFXSvcContract>(metaFX =>
     {
        //Create a request to list the apps       
        var request = new Epicor.MetaFX.Core.Models.Applications.ApplicationRequest()
        {
            Type = "view",
            SubType = "",
            SearchText = "",
            IncludeAllLayers = true
        };

        //Get a list of apps
        List<Epicor.MetaFX.Core.Models.Applications.Application> applications = metaFX.GetApplications(request);
        
        //Create an export request list 
        List<Epicor.MetaFX.Core.Models.Layers.EpMetaFxLayerForApplication> applicationList = new List<Epicor.MetaFX.Core.Models.Layers.EpMetaFxLayerForApplication>();

        //Loop through the list and add custom apps to the export list
        foreach(var item in applications.Where(x => x.SystemFlag == true))
        {
            applicationList.Add(new Epicor.MetaFX.Core.Models.Layers.EpMetaFxLayerForApplication() { Id = item.Id });
        }
        
        //Export the apps and return the zip file data as a Base64 encoded string.
        ZipBase64 = metaFX.ExportLayers(applicationList);
     }); 
     
     Success = true;
     
  //****   
  }
  catch (Exception ex)
  {
      Success = false;
      ListErrorJson = AddExceptionToList(ex, ListErrorJson);
  }
  finally
  {
      //Maybe later?
  }
2 Likes

In the library at the top, and on github.

1 Like

I have been a big advocate of just splitting custom stuff from the std db. Just having a setting in either your database settings or server settings that allows you to define what custom dB everthing is pointing to is a sensible approach. I have seen this approach used successfully with other software

I hope Epicor continue down the path of the common dB.

Data related to ud tables may be of concern, not really sure how to explain what I mean there, but if we are only talking about just the definition of the fields should be OK…

Having everything custom in a separate dB then allows you to compare customs pretty easily Compare and Synchronize the Data of Two Databases - SQL Server Data Tools (SSDT) | Microsoft Learn

Which makes the upgrade process a lot easier not to mention development against the demo dB @Mark_Wonsil :grin:

Awesome work @klincecum

2 Likes

UD fields → Done, not posted yet

Classic Form Customizations → Done, not posted yet

Form customizations are currently exported as rows tablesets, because putting it the xml export format is hard. Will revisit. (maybe? :rofl: )

1 Like

It’s a real nice templating system that lets him do this so quickly.

2 Likes

I just found this. I think its gonna really help us thanks. We go live end of October, we have a basedata environment which is supposed to be our starting point for cutovcer, as well as various test and dev environments which a number of remote consultants have been working on customizations in. just tracking down what’s custom, and what’s missing in each envirnoment is a chore; hopefully this helps!

2 Likes

Has anybody actually tried it?

@klincecum
Perhaps I’m missing something but functionally, how is this different than the Solution Workbench?
That’s been my go to for Dev to Prod deployments.
No shade, just trying to understand.

No problem Rick.

1 → This is a demo of a concept for doing a dynamic app in Kinetic.
2 → Depends on your use cases.

I didn’t build this into a fully featured product, the plugins are all or nothing, but I use it for backups for development.

Solution workbench leaves a lot to be desired for that.

I also plan to reuse the functions as part of some devops practices.


Example → I’ve been working on a bunch of function libraries. The CFO calls and says he needs new data in pilot to test some stuff. Previously, I had to go figure out what I was working on and export all that stuff out manually.

Now I open the app, click the export libraries button, and get my zip. Then I push his data.
I can import what I want back in later at my discretion.


Plan to use the backend of this (or something based on the same concepts) for versioning and storage at some point.

3 Likes

Added those today. Sorry, had them done on the 9th :rofl:

Been busy.

3 Likes

Or someone else goes ahead and restores without mentioning it, wiping out a week of work :sob:

1 Like

the addams family dark GIF

1 Like

Well as for the song choice, @Mark_Wonsil always told me to go for the brass ring..

@Banderson can check his sound, and @hmwillett can die laughing.

For the rest of you, I’m sorry.

I tried.

5 Likes

Any suggestions as to why I’m not seeing the app in Menu Maintenance App Search?

1 Like

I don’t know, I’ve never imported one myself. I can try to import it into my live later to see how it goes.

Ok, what I had to do was open the base in App Studio, and publish it. Then it showed up in menu maintenance.

Ah. It showed Published=true so didn’t try that. Worked! Thanks!

FYI - Export ALL Custom Report Data gives Invalid Company error.

1 Like