🌟 ExportAllTheThings - Export Your Custom Objects

What the app template looks like:
{
    "AllowVersions": true,
    "PersonalizationNotLoaded": false,
    "HasOrphans": false,
    "Layout": {
        "name": "App",
        "guid": "2dcd1674-5e34-4d98-b493-c75747027376",
        "caption": "ExportAllTheThings",
        "viewType": "Apps",
        "pageType": "Responsive",
        "components": [
            {
                "parentId": null,
                "id": "42b8f86a-e989-476f-bd72-c27b58f14dad",
                "sourceTypeId": "metafx-panel-card",
                "model": {
                    "guid": "42b8f86a-e989-476f-bd72-c27b58f14dad",
                    "title": "Downloads",
                    "id": "metafx-panel-card-42b8f",
                    "bodyComponents": [
                        {
                            "id": "5609002a-b234-4242-8c7c-3e7ef3500ece",
                            "sourceTypeId": "metafx-div",
                            "model": {
                                "guid": "5609002a-b234-4242-8c7c-3e7ef3500ece",
                                "id": "rowTemplate",
                                "labelText": "PluginName"
                            },
                            "parentId": "42b8f86a-e989-476f-bd72-c27b58f14dad",
                            "components": [
                                {
                                    "id": "987433d4-9110-4151-9a3f-b65285a227c6",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "987433d4-9110-4151-9a3f-b65285a227c6",
                                        "flexBasis": "25%",
                                        "id": "lcTemplate",
                                        "orientation": "horizontal"
                                    },
                                    "parentId": "5609002a-b234-4242-8c7c-3e7ef3500ece",
                                    "components": [
                                        {
                                            "id": "0529688d-9a5c-4dbc-97b2-c41466c616db",
                                            "sourceTypeId": "erp-button",
                                            "model": {
                                                "guid": "0529688d-9a5c-4dbc-97b2-c41466c616db",
                                                "labelText": "Download",
                                                "id": "btnDownload"
                                            },
                                            "parentId": "987433d4-9110-4151-9a3f-b65285a227c6",
                                            "components": []
                                        }
                                    ]
                                },
                                {
                                    "id": "78a17344-9a59-4d21-9556-3efd40dfc0b3",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "78a17344-9a59-4d21-9556-3efd40dfc0b3",
                                        "flexBasis": "75%",
                                        "id": "rcTemplate"
                                    },
                                    "parentId": "5609002a-b234-4242-8c7c-3e7ef3500ece",
                                    "components": [
                                        {
                                            "id": "73014d32-0641-4a20-a31b-c0c733a955c8",
                                            "sourceTypeId": "erp-text-box",
                                            "model": {
                                                "guid": "73014d32-0641-4a20-a31b-c0c733a955c8",
                                                "labelText": "Sample Plugin Description",
                                                "id": "txtPluginDesc",
                                                "personalizable": false,
                                                "customizable": false,
                                                "disabled": true,
                                                "width": 1000
                                            },
                                            "parentId": "78a17344-9a59-4d21-9556-3efd40dfc0b3",
                                            "components": []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                },
                "layoutData": {
                    "flexLayout": true,
                    "hostId": "App"
                }
            }
        ],
        "navigation": {
            "dataSetId": "",
            "pageCaption": "",
            "tabId": "",
            "enable": false,
            "parentPage": "",
            "epBinding": "",
            "epBindingLevel": 0,
            "epBindingPeerOrder": 0
        },
        "width": 1440
    },
    "Events": [
        {
            "trigger": {
                "hook": "onClick",
                "type": "Control",
                "target": "btnDownload"
            },
            "actions": [
                {
                    "type": "file-transfer-erp",
                    "param": {
                        "specialFolder": 5,
                        "transferType": "download",
                        "company": "MS67964",
                        "serverPath": "EATT://TemplatePath",
                        "clientPath": "Wut"
                    }
                }
            ],
            "id": "btnDownload_onClick",
            "customizable": true,
            "disable": false
        }
    ],
    "ToolBar": [],
    "DataViews": [],
    "Rules": [],
    "References": null,
    "Pages": [],
    "Properties": null,
    "Wasm": null,
    "IsLayerDisabled": false,
    "ConfiguratorInfo": null,
    "ApplicationStrings": null,
    "ServerErrorCode": null,
    "ServerErrors": null,
    "Orphans": []
}

What the app looks like after processing:
{
    "AllowVersions": true,
    "PersonalizationNotLoaded": false,
    "HasOrphans": false,
    "Layout": {
        "name": "App",
        "guid": "2dcd1674-5e34-4d98-b493-c75747027376",
        "caption": "ExportAllTheThings",
        "viewType": "Apps",
        "pageType": "Responsive",
        "components": [
            {
                "parentId": null,
                "id": "42b8f86a-e989-476f-bd72-c27b58f14dad",
                "sourceTypeId": "metafx-panel-card",
                "model": {
                    "guid": "42b8f86a-e989-476f-bd72-c27b58f14dad",
                    "title": "Downloads",
                    "id": "metafx-panel-card-42b8f",
                    "bodyComponents": [
                        {
                            "id": "d52bc555-7fa5-4f2e-a489-1ce407541918",
                            "sourceTypeId": "metafx-div",
                            "model": {
                                "guid": "d52bc555-7fa5-4f2e-a489-1ce407541918",
                                "id": "rowExportAllCustomBAQs",
                                "labelText": "ExportAllCustomBAQs"
                            },
                            "parentId": "42b8f86a-e989-476f-bd72-c27b58f14dad",
                            "components": [
                                {
                                    "id": "8831fa29-6c81-4fd0-a31a-3cc55c024951",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "8831fa29-6c81-4fd0-a31a-3cc55c024951",
                                        "flexBasis": "25%",
                                        "id": "lcExportAllCustomBAQs",
                                        "orientation": "horizontal"
                                    },
                                    "parentId": "d52bc555-7fa5-4f2e-a489-1ce407541918",
                                    "components": [
                                        {
                                            "id": "f1fe3052-e11f-450f-84c2-3157fba6df96",
                                            "sourceTypeId": "erp-button",
                                            "model": {
                                                "guid": "f1fe3052-e11f-450f-84c2-3157fba6df96",
                                                "labelText": "Download",
                                                "id": "btnExportAllCustomBAQs"
                                            },
                                            "parentId": "f1fe3052-e11f-450f-84c2-3157fba6df96",
                                            "components": []
                                        }
                                    ]
                                },
                                {
                                    "id": "e46e0b25-ff15-4b7e-9ebd-fd03e9b52686",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "e46e0b25-ff15-4b7e-9ebd-fd03e9b52686",
                                        "flexBasis": "75%",
                                        "id": "rcExportAllCustomBAQs"
                                    },
                                    "parentId": "d52bc555-7fa5-4f2e-a489-1ce407541918",
                                    "components": [
                                        {
                                            "id": "6a6d8e35-3ada-41ae-a3be-ddd47c97c93e",
                                            "sourceTypeId": "erp-text-box",
                                            "model": {
                                                "guid": "6a6d8e35-3ada-41ae-a3be-ddd47c97c93e",
                                                "labelText": "This plugin downloads all custom BAQs.",
                                                "id": "txtExportAllCustomBAQsDescription",
                                                "personalizable": false,
                                                "customizable": false,
                                                "disabled": true,
                                                "width": 1000
                                            },
                                            "parentId": "6a6d8e35-3ada-41ae-a3be-ddd47c97c93e",
                                            "components": []
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            "id": "367530f3-8706-4f37-a61d-70b8b478f76d",
                            "sourceTypeId": "metafx-div",
                            "model": {
                                "guid": "367530f3-8706-4f37-a61d-70b8b478f76d",
                                "id": "rowExportAllFunctionLibraries",
                                "labelText": "ExportAllFunctionLibraries"
                            },
                            "parentId": "42b8f86a-e989-476f-bd72-c27b58f14dad",
                            "components": [
                                {
                                    "id": "6d2b6cd6-6d2f-4efc-b6a6-94e85105565d",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "6d2b6cd6-6d2f-4efc-b6a6-94e85105565d",
                                        "flexBasis": "25%",
                                        "id": "lcExportAllFunctionLibraries",
                                        "orientation": "horizontal"
                                    },
                                    "parentId": "367530f3-8706-4f37-a61d-70b8b478f76d",
                                    "components": [
                                        {
                                            "id": "8383ab8d-91af-48de-89b4-4286c4aa4018",
                                            "sourceTypeId": "erp-button",
                                            "model": {
                                                "guid": "8383ab8d-91af-48de-89b4-4286c4aa4018",
                                                "labelText": "Download",
                                                "id": "btnExportAllFunctionLibraries"
                                            },
                                            "parentId": "8383ab8d-91af-48de-89b4-4286c4aa4018",
                                            "components": []
                                        }
                                    ]
                                },
                                {
                                    "id": "7cfcf13f-3a9d-4291-8e10-e048fa757f1e",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "7cfcf13f-3a9d-4291-8e10-e048fa757f1e",
                                        "flexBasis": "75%",
                                        "id": "rcExportAllFunctionLibraries"
                                    },
                                    "parentId": "367530f3-8706-4f37-a61d-70b8b478f76d",
                                    "components": [
                                        {
                                            "id": "2c4ed096-c8b6-4d9b-8220-bd293270e38a",
                                            "sourceTypeId": "erp-text-box",
                                            "model": {
                                                "guid": "2c4ed096-c8b6-4d9b-8220-bd293270e38a",
                                                "labelText": "This plugin downloads all Function Libraries.",
                                                "id": "txtExportAllFunctionLibrariesDescription",
                                                "personalizable": false,
                                                "customizable": false,
                                                "disabled": true,
                                                "width": 1000
                                            },
                                            "parentId": "2c4ed096-c8b6-4d9b-8220-bd293270e38a",
                                            "components": []
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            "id": "3f32cbc8-d3c0-45a4-9226-db58d9ab11fe",
                            "sourceTypeId": "metafx-div",
                            "model": {
                                "guid": "3f32cbc8-d3c0-45a4-9226-db58d9ab11fe",
                                "id": "rowExportAllUDCodes",
                                "labelText": "ExportAllUDCodes"
                            },
                            "parentId": "42b8f86a-e989-476f-bd72-c27b58f14dad",
                            "components": [
                                {
                                    "id": "c4a6e44a-2968-4051-98b9-1a47f83cbd71",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "c4a6e44a-2968-4051-98b9-1a47f83cbd71",
                                        "flexBasis": "25%",
                                        "id": "lcExportAllUDCodes",
                                        "orientation": "horizontal"
                                    },
                                    "parentId": "3f32cbc8-d3c0-45a4-9226-db58d9ab11fe",
                                    "components": [
                                        {
                                            "id": "c4386dc7-dcb4-46bf-b1e9-bb5fec53c42b",
                                            "sourceTypeId": "erp-button",
                                            "model": {
                                                "guid": "c4386dc7-dcb4-46bf-b1e9-bb5fec53c42b",
                                                "labelText": "Download",
                                                "id": "btnExportAllUDCodes"
                                            },
                                            "parentId": "c4386dc7-dcb4-46bf-b1e9-bb5fec53c42b",
                                            "components": []
                                        }
                                    ]
                                },
                                {
                                    "id": "94e283ed-bc24-4d1a-aeec-2c6b21910cd0",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "94e283ed-bc24-4d1a-aeec-2c6b21910cd0",
                                        "flexBasis": "75%",
                                        "id": "rcExportAllUDCodes"
                                    },
                                    "parentId": "3f32cbc8-d3c0-45a4-9226-db58d9ab11fe",
                                    "components": [
                                        {
                                            "id": "5f9bd722-3530-4047-b957-c3e7ae89b05a",
                                            "sourceTypeId": "erp-text-box",
                                            "model": {
                                                "guid": "5f9bd722-3530-4047-b957-c3e7ae89b05a",
                                                "labelText": "This plugin exports all UD Codes. (User Codes)",
                                                "id": "txtExportAllUDCodesDescription",
                                                "personalizable": false,
                                                "customizable": false,
                                                "disabled": true,
                                                "width": 1000
                                            },
                                            "parentId": "5f9bd722-3530-4047-b957-c3e7ae89b05a",
                                            "components": []
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            "id": "583cbebc-45a2-4df7-b57a-36e824f0748e",
                            "sourceTypeId": "metafx-div",
                            "model": {
                                "guid": "583cbebc-45a2-4df7-b57a-36e824f0748e",
                                "id": "rowExportDataDirectivesByTable",
                                "labelText": "ExportDataDirectivesByTable"
                            },
                            "parentId": "42b8f86a-e989-476f-bd72-c27b58f14dad",
                            "components": [
                                {
                                    "id": "8a02fad0-1d8c-4651-a89a-2697fea1bb25",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "8a02fad0-1d8c-4651-a89a-2697fea1bb25",
                                        "flexBasis": "25%",
                                        "id": "lcExportDataDirectivesByTable",
                                        "orientation": "horizontal"
                                    },
                                    "parentId": "583cbebc-45a2-4df7-b57a-36e824f0748e",
                                    "components": [
                                        {
                                            "id": "db6f90b1-b5b1-4c95-b0b7-0975530c983d",
                                            "sourceTypeId": "erp-button",
                                            "model": {
                                                "guid": "db6f90b1-b5b1-4c95-b0b7-0975530c983d",
                                                "labelText": "Download",
                                                "id": "btnExportDataDirectivesByTable"
                                            },
                                            "parentId": "db6f90b1-b5b1-4c95-b0b7-0975530c983d",
                                            "components": []
                                        }
                                    ]
                                },
                                {
                                    "id": "be8821d8-6e1f-4f09-a7a5-5a16eba47eb0",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "be8821d8-6e1f-4f09-a7a5-5a16eba47eb0",
                                        "flexBasis": "75%",
                                        "id": "rcExportDataDirectivesByTable"
                                    },
                                    "parentId": "583cbebc-45a2-4df7-b57a-36e824f0748e",
                                    "components": [
                                        {
                                            "id": "b410145c-45d3-4ea4-8585-1fb0f1015049",
                                            "sourceTypeId": "erp-text-box",
                                            "model": {
                                                "guid": "b410145c-45d3-4ea4-8585-1fb0f1015049",
                                                "labelText": "This plugin downloads all Data Directives by \"Table\".",
                                                "id": "txtExportDataDirectivesByTableDescription",
                                                "personalizable": false,
                                                "customizable": false,
                                                "disabled": true,
                                                "width": 1000
                                            },
                                            "parentId": "b410145c-45d3-4ea4-8585-1fb0f1015049",
                                            "components": []
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            "id": "6188857e-2d60-4974-83a2-dfd8f27dee35",
                            "sourceTypeId": "metafx-div",
                            "model": {
                                "guid": "6188857e-2d60-4974-83a2-dfd8f27dee35",
                                "id": "rowExportDirectivesByGroups",
                                "labelText": "ExportDirectivesByGroups"
                            },
                            "parentId": "42b8f86a-e989-476f-bd72-c27b58f14dad",
                            "components": [
                                {
                                    "id": "f93ba304-a937-4bed-9587-797e0b9bba5b",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "f93ba304-a937-4bed-9587-797e0b9bba5b",
                                        "flexBasis": "25%",
                                        "id": "lcExportDirectivesByGroups",
                                        "orientation": "horizontal"
                                    },
                                    "parentId": "6188857e-2d60-4974-83a2-dfd8f27dee35",
                                    "components": [
                                        {
                                            "id": "6f02f787-fdc7-4ef8-9a78-8e29bb07677a",
                                            "sourceTypeId": "erp-button",
                                            "model": {
                                                "guid": "6f02f787-fdc7-4ef8-9a78-8e29bb07677a",
                                                "labelText": "Download",
                                                "id": "btnExportDirectivesByGroups"
                                            },
                                            "parentId": "6f02f787-fdc7-4ef8-9a78-8e29bb07677a",
                                            "components": []
                                        }
                                    ]
                                },
                                {
                                    "id": "96d869ee-42d5-4c37-875e-dd084a436870",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "96d869ee-42d5-4c37-875e-dd084a436870",
                                        "flexBasis": "75%",
                                        "id": "rcExportDirectivesByGroups"
                                    },
                                    "parentId": "6188857e-2d60-4974-83a2-dfd8f27dee35",
                                    "components": [
                                        {
                                            "id": "14cd63f5-eceb-44ed-aad2-d26ff2177d8d",
                                            "sourceTypeId": "erp-text-box",
                                            "model": {
                                                "guid": "14cd63f5-eceb-44ed-aad2-d26ff2177d8d",
                                                "labelText": "This plugin downloads all Method AND Data Directives by \"Group\".",
                                                "id": "txtExportDirectivesByGroupsDescription",
                                                "personalizable": false,
                                                "customizable": false,
                                                "disabled": true,
                                                "width": 1000
                                            },
                                            "parentId": "14cd63f5-eceb-44ed-aad2-d26ff2177d8d",
                                            "components": []
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            "id": "8683c36a-037d-4274-8977-bda5752765bc",
                            "sourceTypeId": "metafx-div",
                            "model": {
                                "guid": "8683c36a-037d-4274-8977-bda5752765bc",
                                "id": "rowExportMethodDirectivesByService",
                                "labelText": "ExportMethodDirectivesByService"
                            },
                            "parentId": "42b8f86a-e989-476f-bd72-c27b58f14dad",
                            "components": [
                                {
                                    "id": "31dc605d-89dd-4306-bce8-22c83611492f",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "31dc605d-89dd-4306-bce8-22c83611492f",
                                        "flexBasis": "25%",
                                        "id": "lcExportMethodDirectivesByService",
                                        "orientation": "horizontal"
                                    },
                                    "parentId": "8683c36a-037d-4274-8977-bda5752765bc",
                                    "components": [
                                        {
                                            "id": "9cd30016-e3f6-4fc8-a363-157821f3fb11",
                                            "sourceTypeId": "erp-button",
                                            "model": {
                                                "guid": "9cd30016-e3f6-4fc8-a363-157821f3fb11",
                                                "labelText": "Download",
                                                "id": "btnExportMethodDirectivesByService"
                                            },
                                            "parentId": "9cd30016-e3f6-4fc8-a363-157821f3fb11",
                                            "components": []
                                        }
                                    ]
                                },
                                {
                                    "id": "666e6ff3-431a-4a14-86de-a3eb90592f37",
                                    "sourceTypeId": "metafx-col",
                                    "model": {
                                        "guid": "666e6ff3-431a-4a14-86de-a3eb90592f37",
                                        "flexBasis": "75%",
                                        "id": "rcExportMethodDirectivesByService"
                                    },
                                    "parentId": "8683c36a-037d-4274-8977-bda5752765bc",
                                    "components": [
                                        {
                                            "id": "396d9630-1685-4f0f-8752-039c4c34a339",
                                            "sourceTypeId": "erp-text-box",
                                            "model": {
                                                "guid": "396d9630-1685-4f0f-8752-039c4c34a339",
                                                "labelText": "This plugin downloads all Method Directives by \"Service\".",
                                                "id": "txtExportMethodDirectivesByServiceDescription",
                                                "personalizable": false,
                                                "customizable": false,
                                                "disabled": true,
                                                "width": 1000
                                            },
                                            "parentId": "396d9630-1685-4f0f-8752-039c4c34a339",
                                            "components": []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                },
                "layoutData": {
                    "flexLayout": true,
                    "hostId": "App"
                }
            }
        ],
        "navigation": {
            "dataSetId": "",
            "pageCaption": "",
            "tabId": "",
            "enable": false,
            "parentPage": "",
            "epBinding": "",
            "epBindingLevel": 0,
            "epBindingPeerOrder": 0
        },
        "width": 1440
    },
    "Events": [
        {
            "trigger": {
                "hook": "onClick",
                "type": "Control",
                "target": "btnExportAllCustomBAQs"
            },
            "actions": [
                {
                    "type": "file-transfer-erp",
                    "param": {
                        "specialFolder": 5,
                        "transferType": "download",
                        "company": "MS67964",
                        "serverPath": "EATT://ExportAllCustomBAQs",
                        "clientPath": "ExportAllCustomBAQs.zip"
                    }
                }
            ],
            "id": "btnExportAllCustomBAQs_onClick",
            "customizable": true,
            "disable": false
        },
        {
            "trigger": {
                "hook": "onClick",
                "type": "Control",
                "target": "btnExportAllFunctionLibraries"
            },
            "actions": [
                {
                    "type": "file-transfer-erp",
                    "param": {
                        "specialFolder": 5,
                        "transferType": "download",
                        "company": "MS67964",
                        "serverPath": "EATT://ExportAllFunctionLibraries",
                        "clientPath": "ExportAllFunctionLibraries.zip"
                    }
                }
            ],
            "id": "btnExportAllFunctionLibraries_onClick",
            "customizable": true,
            "disable": false
        },
        {
            "trigger": {
                "hook": "onClick",
                "type": "Control",
                "target": "btnExportAllUDCodes"
            },
            "actions": [
                {
                    "type": "file-transfer-erp",
                    "param": {
                        "specialFolder": 5,
                        "transferType": "download",
                        "company": "MS67964",
                        "serverPath": "EATT://ExportAllUDCodes",
                        "clientPath": "ExportAllUDCodes.zip"
                    }
                }
            ],
            "id": "btnExportAllUDCodes_onClick",
            "customizable": true,
            "disable": false
        },
        {
            "trigger": {
                "hook": "onClick",
                "type": "Control",
                "target": "btnExportDataDirectivesByTable"
            },
            "actions": [
                {
                    "type": "file-transfer-erp",
                    "param": {
                        "specialFolder": 5,
                        "transferType": "download",
                        "company": "MS67964",
                        "serverPath": "EATT://ExportDataDirectivesByTable",
                        "clientPath": "ExportDataDirectivesByTable.zip"
                    }
                }
            ],
            "id": "btnExportDataDirectivesByTable_onClick",
            "customizable": true,
            "disable": false
        },
        {
            "trigger": {
                "hook": "onClick",
                "type": "Control",
                "target": "btnExportDirectivesByGroups"
            },
            "actions": [
                {
                    "type": "file-transfer-erp",
                    "param": {
                        "specialFolder": 5,
                        "transferType": "download",
                        "company": "MS67964",
                        "serverPath": "EATT://ExportDirectivesByGroups",
                        "clientPath": "ExportDirectivesByGroups.zip"
                    }
                }
            ],
            "id": "btnExportDirectivesByGroups_onClick",
            "customizable": true,
            "disable": false
        },
        {
            "trigger": {
                "hook": "onClick",
                "type": "Control",
                "target": "btnExportMethodDirectivesByService"
            },
            "actions": [
                {
                    "type": "file-transfer-erp",
                    "param": {
                        "specialFolder": 5,
                        "transferType": "download",
                        "company": "MS67964",
                        "serverPath": "EATT://ExportMethodDirectivesByService",
                        "clientPath": "ExportMethodDirectivesByService.zip"
                    }
                }
            ],
            "id": "btnExportMethodDirectivesByService_onClick",
            "customizable": true,
            "disable": false
        }
    ],
    "ToolBar": [],
    "DataViews": [],
    "Rules": [],
    "References": null,
    "Pages": [],
    "Properties": null,
    "Wasm": null,
    "IsLayerDisabled": false,
    "ConfiguratorInfo": null,
    "ApplicationStrings": null,
    "ServerErrorCode": null,
    "ServerErrors": null,
    "Orphans": []
}


BPM on Ice.Lib.MetaFX.GetApp
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Directive Type:  Method -> Post Processing
* Directive BO:    Ice.Lib.MetaFX.GetApp
* Directive Name:  InterceptGetAppRequest
* Directive Desc:  Intercepts a request for a template, forward it to the appropriate place.
* Directive Group: ExportAllTheThings
* ==========================================================================================
* 
* Hi Mom!
*
* CHANGELOG:
* 08/26/2024 | klincecum | Kevin Lincecum | Initial Implementation
* 08/29/2024 | klincecum | Kevin Lincecum | Cleanup & Comments For Release
*
* ==========================================================================================
*/

//If we are in app studio, we only want to edit the template, not a dynamically generated app.
if(request.properties.mode == "AppStudio") return; //Bye

if(request.id == "Ice.UI.ExportAllTheThingsTemplate")
{
    //Where we are going to call
    string FunctionLibrary = "ExportAllTheThings";
    string FunctionID = "GetApp";

    try
    {
      //Call the function with the request and template data. This is one of the reasons we are doing this in post so the system will retrieve it for us.
      var response = InvokeFunction(FunctionLibrary, FunctionID,  JsonConvert.SerializeObject(request), JsonConvert.SerializeObject(result));
 
       
      //So y'all can see what was returned better
      var responseUnwrapped = new
      {
          Success = (bool)response[0],
          ListErrorJson = (string)response[1],
          appJson = (string)response[2]
      };
      
      //If we succeeded, we are done. Parse the Json into tokens and pass it back. The serializer will take care of it from here.
      if(responseUnwrapped.Success) //Success
      {
          result = JToken.Parse(responseUnwrapped.appJson);
          return; //Done. Stop Processing.
      }
      
      
      //Failure
      if(!String.IsNullOrEmpty(responseUnwrapped.ListErrorJson))
      {
          //If we have errors, pass them along with the exception.
          throw new BLException(responseUnwrapped.ListErrorJson);
      }
      else
      {
          //We didn't have any errors, so we'll pass back "something" useful lol.
          throw new BLException($"Unknown error from function: {FunctionLibrary}.{FunctionID}");
      }

    }
    catch (Exception ex)
    {
        //We will just rethrow anything. Catches our exceptions above, as well as unknowns.
        throw ex;
    }
}
BPM on Ice.Lib.FileTransfer.DownloadFileForCompany
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Directive Type:  Method -> Pre Processing
* Directive BO:    Ice.Lib.FileTransfer.DownloadFileForCompany
* Directive Name:  InterceptFileDownloadForCompanyRequest
* Directive Desc:  Intercepts the call to download a file if a custom url is used, and routes
*                  it appropriately.
* Directive Group: ExportAllTheThings
* ==========================================================================================
* 
* Hi Mom!
*
* CHANGELOG:
* 08/26/2024 | klincecum | Kevin Lincecum | Initial Implementation
* 08/30/2024 | klincecum | Kevin Lincecum | Cleanup & Comments For Release
*
* ==========================================================================================
*/

//We are only interested in requests that the server path starts with "EATT://"
if(serverPath.StartsWith("EATT://"))
{
    try
    {
        //Get the plugin name
        string plugin = serverPath.Split("//")[1];
        
        //Call the plugin (function)
        var response = InvokeFunction("ExportAllTheThings", plugin);
        
        //So y'all can see what was returned better
        var responseUnwrapped = new
        {
            Success = (bool)response[0],
            ListErrorJson = (string)response[1],
            ZipBase64 = (string)response[2]
        };
    
    
        //If we succeeded, we are done. Convert the Base64 Data from the plugin (function) to a byte array and return it. 
        if(responseUnwrapped.Success) //Success
        {
            if(!String.IsNullOrEmpty(responseUnwrapped.ZipBase64))
            {
              result = Convert.FromBase64String(responseUnwrapped.ZipBase64);
              MarkCallCompleted();
            }
            
            return; //Done. Stop Processing.
        }
        
        //Failure
        
        //Create an exception
        var exception = new BLException( "Failure running plugin with path: \"" + serverPath + "\"" );
        
        if(!String.IsNullOrEmpty(responseUnwrapped.ListErrorJson))
        {
            //If we have errors, pass them along with the exception.
            exception.Data.Add("ErrorList", responseUnwrapped.ListErrorJson);
        }
        
        //Bam!
        throw exception;
            
    }    
    catch (Exception ex)
    {
        //We will just rethrow anything. Catches our exceptions above, as well as unknowns.
        throw new BLException(ex.ToString());
    }
}

ExportAllTheThings.GetApp
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    GetApp
* Description: This function parses a template app and builds a full app based off of the
*              plugins found in this library. These plugins export things as "Zip" Files.
* ==========================================================================================
* 
* INPUTS:
*   STRING: Request        -> The request for the app from the client   
*   STRING: TemplateData   -> The json data for the template app
*
* OUTPUTS:
*   BOOL:   Success        -> Function Success / Failure
*   STRING: ListErrorsJson -> Json Serialized List<Exception>
*   STRING: appJson        -> Kinetic app Json data
*
* CHANGELOG:
* 08/26/2024 | klincecum | Kevin Lincecum | Initial Implementation
* 08/30/2024 | klincecum | Kevin Lincecum | Cleanup & Comments For Release
*
* ==========================================================================================
*/

  //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  
  
  
  //Use Newtonsoft to copy a token
  Func<JToken, JToken> DuplicateToken = (token) => JToken.Parse(token.ToString());


  try
  {
  //****

      //Create a dictionary of "plugins" to build the app with
      Dictionary<string, string> pluginDictionary = new Dictionary<string, string>();
    
      //Load the plugins into the dictionary
      CallService<Ice.Contracts.EfxLibraryDesignerSvcContract>(efxLD =>
      {
          //We are loading plugins from this libary, so get a list of the functions.
          var functionLibrary = efxLD.GetLibrary(LibraryID);
          
          //Populate the plugins dictionary. Only chose functions that begin with "Export".
          pluginDictionary = functionLibrary.EfxFunction.Where(f => f.FunctionID.StartsWith("Export")).ToDictionary(f1 => f1.FunctionID, f2 => f2.Description);
      });
    

      //Parse the template data.
      var app = JToken.Parse(TemplateData);
      
      //Get the body template section we are interested in. 
      var bodyComponentsTemplate = app["Layout"]["components"][0]["model"]["bodyComponents"];
      
      //Clear template data from the array.
      app["Layout"]["components"][0]["model"]["bodyComponents"] = new JArray();
      
      
      //Get the event template section we are interested in.
      var eventTemplate = app["Events"][0];
      
      //Clear template data from the array.
      app["Events"] = new JArray();
      
      
      //We are doing rows down the page. Get that section.
      var rowTemplate = bodyComponentsTemplate[0];
      
      //We will build a new row for each plugin.
      foreach(var func in pluginDictionary)
      {
          var newRow = DuplicateToken(rowTemplate);
      
          //Row
          newRow["id"] = Guid.NewGuid();
          newRow["model"]["guid"] = newRow["id"];
          newRow["model"]["id"] = $"row{func.Key}";
          newRow["model"]["labelText"] = func.Key;

          //Left Column Components
          newRow["components"][0]["id"] = Guid.NewGuid();
          newRow["components"][0]["model"]["guid"] = newRow["components"][0]["id"];
          newRow["components"][0]["model"]["id"] = $"lc{func.Key}";
          newRow["components"][0]["parentId"] = newRow["id"];
      
          //Button
          newRow["components"][0]["components"][0]["id"] = Guid.NewGuid();
          newRow["components"][0]["components"][0]["model"]["guid"] = newRow["components"][0]["components"][0]["id"];
          newRow["components"][0]["components"][0]["model"]["id"] = $"btn{func.Key}";
          newRow["components"][0]["components"][0]["parentId"] = newRow["components"][0]["components"][0]["id"];
      
          //Right Column Components
          newRow["components"][1]["id"] = Guid.NewGuid();
          newRow["components"][1]["model"]["guid"] = newRow["components"][1]["id"];
          newRow["components"][1]["model"]["id"] = $"rc{func.Key}";
          newRow["components"][1]["parentId"] = newRow["id"];
      
          //Plugin Description
          newRow["components"][1]["components"][0]["id"] = Guid.NewGuid();
          newRow["components"][1]["components"][0]["model"]["guid"] = newRow["components"][1]["components"][0]["id"];
          newRow["components"][1]["components"][0]["model"]["id"] = $"txt{func.Key}Description";
          newRow["components"][1]["components"][0]["model"]["labelText"] = func.Value;
          newRow["components"][1]["components"][0]["parentId"] = newRow["components"][1]["components"][0]["id"];
      
      
          //Add row to app.
          ((JArray)app["Layout"]["components"][0]["model"]["bodyComponents"]).Add(newRow);
          
      
          //Events
          var newEvent = DuplicateToken(eventTemplate);
      
          //Add Event for each button / plugin.
          newEvent["trigger"]["target"] = $"btn{func.Key}";
          newEvent["actions"][0]["param"]["serverPath"] = $"EATT://{func.Key}";
          newEvent["actions"][0]["param"]["clientPath"] = $"{func.Key}.zip";
          newEvent["id"] = $"btn{func.Key}_onClick";
      
          //Add event to app.
          ((JArray)app["Events"]).Add(newEvent);
      
      }
      
      //Get the json for the app and return it.
      appJson = app.ToString();
      
      Success = true; //Woot!

  }
  catch (Exception ex)
  {
      Success = false; //Meh
      ListErrorJson = AddExceptionToList(ex, ListErrorJson);
  }
ExportAllTheThings.ZipFiles
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    ZipFiles    
* Description: This is a utility function to "Zip" files.
* ==========================================================================================
* 
* INPUTS:
*   STRING: fileDictionaryJson -> Json Encoded Dictionary<string, string> where the first
*                                 string is the filename, and the second is a Base64
*                                 endoded byte array with the file data.
*
* OUTPUTS:
*   STRING: ZipBase64          -> Base64 Encoded Byte Array
*
* CHANGELOG:
* 08/26/2024 | klincecum | Kevin Lincecum | Initial Implementation
* 08/30/2024 | klincecum | Kevin Lincecum | Cleanup & Comments For Release
*
* ==========================================================================================
*/


  Func<Dictionary<string, string>, byte[]> ZipByteArray = (fileDict) =>
  {
      byte[] retBytes = null;
      
      using (MemoryStream zipMS = new MemoryStream())
      {
          using (ZipArchive zipArchive = new ZipArchive(zipMS, ZipArchiveMode.Create, true))
          {
              foreach(var file in fileDict)
              {
                  var zipArchiveEntry = zipArchive.CreateEntry(file.Key, CompressionLevel.NoCompression);
                  
                  using (var zipStream = zipArchiveEntry.Open())
                  {
                      byte[] fileBytes = Convert.FromBase64String(file.Value);
                  
                      zipStream.Write(fileBytes, 0, fileBytes.Length);
                  }
              }
          }
          
          zipMS.Flush();
          retBytes = zipMS.ToArray();
      };
      
      return retBytes;    
  };


  Dictionary<string, string> fileDictionary = new Dictionary<string, string>();
    
  try
  {
      fileDictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(fileDictionaryJson); 
  }
  catch {}
  
  if(fileDictionary.Count() < 1) return; //Get out of here
  
  byte[] zipBytes = ZipByteArray(fileDictionary);

  ZipBase64 = Convert.ToBase64String(zipBytes);  
ExportAllTheThings.ExportAllCustomBAQs
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    ExportAllCustomBAQs
* Description: This plugin downloads all custom BAQs.
* ==========================================================================================
* 
* INPUTS: NONE
*
* OUTPUTS:
*   BOOL:   Success        -> Function Success / Failure
*   STRING: ListErrorsJson -> Json Serialized List<Exception>
*   STRING: ZipBase64      -> Base64 Encoded Byte Array
*
* CHANGELOG:
* 08/26/2024 | klincecum | Kevin Lincecum | Initial Implementation
* 08/30/2024 | klincecum | Kevin Lincecum | Cleanup & Comments For Release
*
* ==========================================================================================
*/
  //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.BAQDesignerSvcContract>(baqD =>
     {
     
        //Files we will be adding to the zip file 
        Dictionary<string, string> mainZipFileDictionary = new Dictionary<string, string>();
     
        //Get all BAQs that are not marked "System".
        bool more = false;
        BAQDesignerListTableset baqListTS = baqD.GetList("SystemFlag=false", 0, 1, out more);
        
        //Loop through the list.
        foreach(DynamicQueryDesignerListRow item in baqListTS.DynamicQueryDesignerList)
        {
            try
            {
                //Export the BAQ and get the binary data.
                Dictionary<string, string> options = new Dictionary<string, string>();
                List<string> logResult = new List<string>(); //Needed for export call.
                
                byte[] itemBytes = baqD.ExportBaq(item.QueryID, ref options, out logResult);
                
                //Convert the data to a Base64 encoded string.
                string itemBase64 = Convert.ToBase64String(itemBytes);
                
                //Add the data as a file in the zip.
                mainZipFileDictionary.Add($"{item.QueryID}.baq", itemBase64);
            }
            catch (Exception iEx)
            {
                //Continue processing on error, but add errors to the errors list.
                iEx.Data.Add("QueryID", item.QueryID);
                ListErrorJson = AddExceptionToList(iEx, ListErrorJson);
            }            
        }
        
        //Zip the files
        string fileDictionaryJson = JsonConvert.SerializeObject(mainZipFileDictionary);
        
        //Return the zip file data as a Base64 encoded string.
        ZipBase64 = ThisLib.ZipFiles(fileDictionaryJson);
     
     }); 
     
     Success = true;
     
  //****   
  }
  catch (Exception ex)
  {
      Success = false;
      ListErrorJson = AddExceptionToList(ex, ListErrorJson);
  }
  finally
  {
      //Maybe later?
  }
ExportAllTheThings.ExportAllFunctionLibraries
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    ExportAllFunctionLibraries
* Description: This plugin downloads all Function Libraries.
* ==========================================================================================
* 
* INPUTS: NONE
*
* OUTPUTS:
*   BOOL:   Success        -> Function Success / Failure
*   STRING: ListErrorsJson -> Json Serialized List<Exception>
*   STRING: ZipBase64      -> Base64 Encoded Byte Array
*
* CHANGELOG:
* 08/26/2024 | klincecum | Kevin Lincecum | Initial Implementation
* 08/30/2024 | klincecum | Kevin Lincecum | Cleanup & Comments For Release
*
* ==========================================================================================
*/

  //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

  //Can't make this damn thing directly, wtf?
  Func<(int kind, string startsWith, int rollOutMode, int status), Ice.Lib.EfxLibraryDesigner.LibrarySearchOptions> CreateLibrarySearchOptions = (input) =>
  {
      return JsonConvert.DeserializeObject<Ice.Lib.EfxLibraryDesigner.LibrarySearchOptions>( JsonConvert.SerializeObject(new {input.kind, input.startsWith, input.rollOutMode, input.status}) );
  };


  try
  {
  //****
  
     CallService<Ice.Contracts.EfxLibraryDesignerSvcContract>(efxLD =>
     {
        //Files we will be adding to the zip file     
        Dictionary<string, string> mainZipFileDictionary = new Dictionary<string, string>(); 
     
        //Get all Function Libraries
        var librarySearchOptions = CreateLibrarySearchOptions((kind: 1, startsWith: "", rollOutMode: 2, status: 2));
    
        EfxLibrarySearchTableset libraries = efxLD.GetLibraryList(librarySearchOptions);
        
        EfxLibraryTableset defaults = efxLD.GetDefaults();
        
        System.Version version = new System.Version($"{defaults.EfxLibrary.FirstOrDefault().EpicorVersion}.{defaults.EfxLibrary.FirstOrDefault().Revision}");
        
        //Loop through the list.
        foreach(var item in libraries.EfxLibraryList)
        {
            try
            {
                //Export the Library and get the binary data.
                var exportOptions = new Ice.Lib.EfxLibraryDesigner.ExportOptions()
                {
                    Mode = 0, Format = (Ice.Lib.EfxLibraryDesigner.ExportFileFormat)1, Package = null, PackageVersion = version, Publisher = Session.UserID, InstallAsHidden = false
                };

                byte[] itemBytes = efxLD.ExportLibrary(item.LibraryID, exportOptions);
                
                //Convert the data to a Base64 encoded string.
                string itemBase64 = Convert.ToBase64String(itemBytes);
                
                //Add the data as a file in the zip.
                mainZipFileDictionary.Add($"{item.LibraryID}.efxj", itemBase64);

            }
            catch (Exception iEx)
            {
                //Continue processing on error, but add errors to the errors list.
                iEx.Data.Add("LibraryID", item.LibraryID);
                ListErrorJson = AddExceptionToList(iEx, ListErrorJson);
            }
        }
        
        //Zip the files
        string fileDictionaryJson = JsonConvert.SerializeObject(mainZipFileDictionary);
        
        //Return the zip file data as a Base64 encoded string.
        ZipBase64 = ThisLib.ZipFiles(fileDictionaryJson);

     });
     
     Success = true;
    
     
  //****
  }
  catch (Exception ex)
  {
      Success = false;
      ListErrorJson = AddExceptionToList(ex, ListErrorJson);
  }
 finally
 {
      //Maybe later?
 }
ExportAllTheThings.ExportAllUDCodes
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    ExportAllUDCodes
* Description: This plugin exports all UD Codes. (User Codes)
* ==========================================================================================
* 
* INPUTS: NONE
*
* OUTPUTS:
*   BOOL:   Success        -> Function Success / Failure
*   STRING: ListErrorsJson -> Json Serialized List<Exception>
*   STRING: ZipBase64      -> Base64 Encoded Byte Array
*
* CHANGELOG:
* 08/26/2024 | klincecum | Kevin Lincecum | Initial Implementation
* 08/30/2024 | klincecum | Kevin Lincecum | Cleanup & Comments For Release
*
* ==========================================================================================
*/

  //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
  
  //Serialize a whole Tableset to B64 
  Func<IceTableset, string> GetTablesetBytesAsB64 = (ts) =>
  {
      string tempJson = JsonConvert.SerializeObject(ts, Formatting.Indented);
        
      byte[] tempBytes = System.Text.Encoding.UTF8.GetBytes(tempJson);
        
      return Convert.ToBase64String(tempBytes);
  };
 
 
  try
  {
  //****
  
     CallService<Ice.Contracts.UserCodesSvcContract>(udCode =>
     {
     
        //Files we will be adding to the zip file     
        Dictionary<string, string> mainZipFileDictionary = new Dictionary<string, string>();

        //Get All UD Codes
        bool morePages = false;
        UserCodesTableset udCodeTS = udCode.GetRows("", "", 0, 0, out morePages);
      
        //Add all to zip file
        mainZipFileDictionary.Add("AllCodes.json", GetTablesetBytesAsB64(udCodeTS));

      
        //Get Distinct List of UDCode Types
        var udCodeTypes = udCodeTS.UDCodeType.Select(x => x.CodeTypeID).Distinct().ToList();
        
        
        //Add Individual codes by CodeTypeID to zip file        
        foreach(var codeType in udCodeTypes)
        {
            //Need something to dump it into
            UserCodesTableset tempUDCodeTS = new UserCodesTableset();
            
            //Filter to the individual CodeTypeID and cheat using Newtonsoft to do the copy
            UDCodesTable filteredUDCodesTable = JsonConvert.DeserializeObject<UDCodesTable>(JsonConvert.SerializeObject(udCodeTS.UDCodes.Where(x => x.CodeTypeID == codeType)));
            UDCodeTypeTable filteredUDCodeTypeTable = JsonConvert.DeserializeObject<UDCodeTypeTable>(JsonConvert.SerializeObject(udCodeTS.UDCodeType.Where(x => x.CodeTypeID == codeType)));
            
            //Add the ranges back to the TS
            tempUDCodeTS.UDCodes.AddRange(filteredUDCodesTable);
            tempUDCodeTS.UDCodeType.AddRange(filteredUDCodeTypeTable);
            
            //Zip the files
            Dictionary<string, string> perCodeTypeFileDictionary = new Dictionary<string, string>();
            
            perCodeTypeFileDictionary.Add($"{codeType}.json", GetTablesetBytesAsB64(tempUDCodeTS));
            
            string perCodefileDictionaryJson = JsonConvert.SerializeObject(perCodeTypeFileDictionary);
        
            string perCodeZipBase64 = ThisLib.ZipFiles(perCodefileDictionaryJson);
            
            //Add to the MAIN zip file
            mainZipFileDictionary.Add($"{codeType}.zip", perCodeZipBase64);
        }

        //Zip the files (The main one)
        string fileDictionaryJson = JsonConvert.SerializeObject(mainZipFileDictionary);
        
        //Return the zip file data as a Base64 encoded string.
        ZipBase64 = ThisLib.ZipFiles(fileDictionaryJson);
     
     }); 
     
     Success = true;
     
  //****   
  }
  catch (Exception ex)
  {
      Success = false;
      ListErrorJson = AddExceptionToList(ex, ListErrorJson);
  }
  finally
  {
      //Maybe later?
  }
ExportAllTheThings.ExportDataDirectivesByTable
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    ExportDataDirectivesByTable
* Description: This plugin downloads all Data Directives by "Table".
* ==========================================================================================
* 
* INPUTS: NONE
*
* OUTPUTS:
*   BOOL:   Success        -> Function Success / Failure
*   STRING: ListErrorsJson -> Json Serialized List<Exception>
*   STRING: ZipBase64      -> Base64 Encoded Byte Array
*
* CHANGELOG:
* 08/26/2024 | klincecum | Kevin Lincecum | Initial Implementation
* 08/30/2024 | klincecum | Kevin Lincecum | Cleanup & Comments For Release
*
* ==========================================================================================
*/

  //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.BpMethodSvcContract>(bpMethod =>
     {
        //Files we will be adding to the zip file     
        Dictionary<string, string> mainZipFileDictionary = new Dictionary<string, string>(); 
     
        //Get All Data Directives
        bool morePages = false;
        Ice.Tablesets.BpMethodListTableset methodTS = bpMethod.GetList("Source = 'DB'", 0, 0, out morePages);
        
        //Create a Distinct List of Data Directive Methods
        var methodsList = methodTS.BpMethodList.Select(x => new { x.SystemCode, x.BusinessObject }).ToList().Distinct();
        
        //Loop through the list.
        foreach(var item in methodsList)
        {
            try
            {
                 //Export the Data Directive
                 byte[] itemBytes = bpMethod.ExportByTable(item.SystemCode, item.BusinessObject).Data;
                      
                 //Convert the data to a Base64 encoded string.           
                 string itemBase64 = Convert.ToBase64String(itemBytes);
                 
                 //Add the data as a file in the zip.           
                 mainZipFileDictionary.Add($"{item.SystemCode}.{item.BusinessObject}.bpm", itemBase64);
            }
            catch (Exception iEx)
            {
                //Continue processing on error, but add errors to the errors list.
                iEx.Data.Add("Table", $"{item.SystemCode}.{item.BusinessObject}.bpm");
                ListErrorJson = AddExceptionToList(iEx, ListErrorJson);
            }          
        }
        
        //Zip the files
        string fileDictionaryJson = JsonConvert.SerializeObject(mainZipFileDictionary);
        
        //Return the zip file data as a Base64 encoded string.
        ZipBase64 = ThisLib.ZipFiles(fileDictionaryJson);
     
     }); 
     
     Success = true;
    
     
  //****   
  }
  catch (Exception ex)
  {
      Success = false;
      ListErrorJson = AddExceptionToList(ex, ListErrorJson);
  }
  finally
  {
      //Maybe later?
  }
ExportAllTheThings.ExportDirectivesByGroups
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    ExportDirectivesByGroups
* Description: This plugin downloads all Method AND Data Directives by "Group".
* ==========================================================================================
* 
* INPUTS: NONE
*
* OUTPUTS:
*   BOOL:   Success        -> Function Success / Failure
*   STRING: ListErrorsJson -> Json Serialized List<Exception>
*   STRING: ZipBase64      -> Base64 Encoded Byte Array
*
* CHANGELOG:
* 08/26/2024 | klincecum | Kevin Lincecum | Initial Implementation
* 08/30/2024 | klincecum | Kevin Lincecum | Cleanup & Comments For Release
*
* ==========================================================================================
*/

//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.BpMethodSvcContract>(bpMethod =>
     {
        //Files we will be adding to the zip file
        Dictionary<string, string> mainZipFileDictionary = new Dictionary<string, string>();
        
        //Get All Directive Groups 
        List<string> groupList = bpMethod.GetDirectiveGroups("BO,DB").ToList();
        
        //Loop through the list.
        foreach(var item in groupList)
        {
            try
            {
                //Export the group and get the binary data.
                byte[] itemBytes = bpMethod.ExportByDirectiveGroup(item).Data;
                
                //Convert the data to a Base64 encoded string.                
                string itemBase64 = Convert.ToBase64String(itemBytes);
               
                //Create an appropriate file name.
                string filename = String.IsNullOrEmpty(item) ? "Ungrouped" : item;

                //Add the data as a file in the zip.           
                mainZipFileDictionary.Add($"{filename}.bpm", itemBase64);
            
            }
            catch (Exception iEx)
            {
                //Continue processing on error, but add errors to the errors list.
                iEx.Data.Add("Group", item);
                ListErrorJson = AddExceptionToList(iEx, ListErrorJson);
            }           
        }
        
        //Zip the files
        string fileDictionaryJson = JsonConvert.SerializeObject(mainZipFileDictionary);
        
        //Return the zip file data as a Base64 encoded string.
        ZipBase64 = ThisLib.ZipFiles(fileDictionaryJson);
     
     }); 
     
     Success = true;
     
  //****   
  }
  catch (Exception ex)
  {
      Success = false;
      ListErrorJson = AddExceptionToList(ex, ListErrorJson);
  }
  finally
  {
      //Maybe later?
  }
ExportAllTheThings.ExportMethodDirectivesByService
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    ExportMethodDirectivesByService
* Description: This plugin downloads all Method Directives by "Service".
* ==========================================================================================
* 
* INPUTS: NONE
*
* OUTPUTS:
*   BOOL:   Success        -> Function Success / Failure
*   STRING: ListErrorsJson -> Json Serialized List<Exception>
*   STRING: ZipBase64      -> Base64 Encoded Byte Array
*
* CHANGELOG:
* 08/26/2024 | klincecum | Kevin Lincecum | Initial Implementation
* 08/30/2024 | klincecum | Kevin Lincecum | Cleanup & Comments For Release
*
* ==========================================================================================
*/

  //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.BpMethodSvcContract>(bpMethod =>
     {
        //Files we will be adding to the zip file
        Dictionary<string, string> mainZipFileDictionary = new Dictionary<string, string>(); 
     
        //Get all Directives for a "Service". (Also exclude BAQ BPMs)
        bool morePages = false;
        Ice.Tablesets.BpMethodListTableset methodTS = bpMethod.GetList("Source = 'BO' AND ObjectNS <> ''", 0, 0, out morePages);
        
        //Create a unique list to process.
        var methodsList = methodTS.BpMethodList.Select(x => new { x.SystemCode, x.ObjectNS, x.BusinessObject }).ToList().Distinct();
        
        //Loop through the list.
        foreach(var item in methodsList)
        {
            try
            {
                //Export the directive and get the binary data.
                byte[] zipMethodBytes = bpMethod.ExportByService(item.SystemCode, item.ObjectNS, item.BusinessObject).Data;
                
                //Convert the data to a Base64 encoded string.                
                string methodZipBase64 = Convert.ToBase64String(zipMethodBytes);

                //Add the data as a file in the zip.
                mainZipFileDictionary.Add($"{item.SystemCode}.{item.ObjectNS}.{item.BusinessObject}.bpm", methodZipBase64);
            }
            catch (Exception iEx)
            {
                //Continue processing on error, but add errors to the errors list.
                iEx.Data.Add("Service", $"{item.SystemCode}.{item.ObjectNS}.{item.BusinessObject}");
                ListErrorJson = AddExceptionToList(iEx, ListErrorJson);
            }             
        }
        
        //Zip the files
        string fileDictionaryJson = JsonConvert.SerializeObject(mainZipFileDictionary);
        
        //Return the zip file data as a Base64 encoded string.
        ZipBase64 = ThisLib.ZipFiles(fileDictionaryJson);
     
     }); 
     
     Success = true;
     
  //****   
  }
  catch (Exception ex)
  {
      Success = false;
      ListErrorJson = AddExceptionToList(ex, ListErrorJson);
  }
  finally
  {
      //Maybe later?
  }

New 04 Sep 2024

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?
  }

New 23 Sep 2024

ExportAllTheThings.ExportAllUDColumns
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    ExportAllUDColumns
* Description: This plugin downloads all user defined column definitions.
* ==========================================================================================
* 
* INPUTS: NONE
*
* OUTPUTS:
*   BOOL:   Success        -> Function Success / Failure
*   STRING: ListErrorsJson -> Json Serialized List<Exception>
*   STRING: ZipBase64      -> Base64 Encoded Byte Array
*
* CHANGELOG:
* 2024/09/09 | 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
 
  //Serialize a whole Tableset to B64 
  Func<IceTableset, string> GetTablesetBytesAsB64 = (ts) =>
  {
      string tempJson = JsonConvert.SerializeObject(ts, Formatting.Indented);
        
      byte[] tempBytes = System.Text.Encoding.UTF8.GetBytes(tempJson);
        
      return Convert.ToBase64String(tempBytes);
  };
  
  
  try
  {
  //****
  
     CallService<Ice.Contracts.ZDataTableSvcContract>(zdt =>
     {
     
        //Files we will be adding to the zip file 
        Dictionary<string, string> mainZipFileDictionary = new Dictionary<string, string>();
     
        //Get all User Defined Columns
        bool more = false;
        Ice.Tablesets.ZDataTableTableset zdtTS = zdt.GetRows("TableType = 'UD' BY DataTableID", "", "", "", "", "", "", 0, 0, out more);
        
        //Add all to zip file
        mainZipFileDictionary.Add("AllUDColumns.json", GetTablesetBytesAsB64(zdtTS));
        
        
        //Get Distinct List of UD Tables
        var udExtensionTables = zdtTS.ZDataTable.Select(x => x.DataTableID).Distinct().ToList();        
        
        
        
        //Loop through the list.
        foreach(string item in udExtensionTables)
        {
            try
            {
                //Get the table data
                Ice.Tablesets.ZDataTableTableset tempZDataTableTS = zdt.GetRows($"DataTableID = '{item}' BY DataTableID", "", "", "", "", "", "", 0, 0, out more); 
            
            
                //Add all to zip file
                mainZipFileDictionary.Add($"{item}.json", GetTablesetBytesAsB64(tempZDataTableTS));
            
            }
            catch (Exception iEx)
            {
                //Continue processing on error, but add errors to the errors list.
                iEx.Data.Add("DataTableID", item);
                ListErrorJson = AddExceptionToList(iEx, ListErrorJson);
            }            
        }
        
        //Zip the files
        string fileDictionaryJson = JsonConvert.SerializeObject(mainZipFileDictionary);
        
        //Return the zip file data as a Base64 encoded string.
        ZipBase64 = ThisLib.ZipFiles(fileDictionaryJson);
     
     }); 
     
     Success = true;
     
  //****   
  }
  catch (Exception ex)
  {
      Success = false;
      ListErrorJson = AddExceptionToList(ex, ListErrorJson);
  }
  finally
  {
      //Maybe later?
  }
ExportAllTheThings.ExportClassicFormCustomizations
/*
* ==========================================================================================
* AUTHOR:    Kevin Lincecum
* COPYRIGHT: Kevin Lincecum 2024
* LICENSE:   MIT
* ==========================================================================================
* Library:     ExportAllTheThings
* Function:    ExportClassicFormCustomizations
* Description: This plugin downloads all classic form customizations.
* ==========================================================================================
* 
* INPUTS: NONE
*
* OUTPUTS:
*   BOOL:   Success        -> Function Success / Failure
*   STRING: ListErrorsJson -> Json Serialized List<Exception>
*   STRING: ZipBase64      -> Base64 Encoded Byte Array
*
* CHANGELOG:
* 2024/09/09 | 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
 
  //Serialize a whole Tableset to B64 
  Func<IceTableset, string> GetTablesetBytesAsB64 = (ts) =>
  {
      string tempJson = JsonConvert.SerializeObject(ts, Formatting.Indented);
        
      byte[] tempBytes = System.Text.Encoding.UTF8.GetBytes(tempJson);
        
      return Convert.ToBase64String(tempBytes);
  };
  
  
  try
  {
  //****
  
     CallService<Ice.Contracts.GenXDataSvcContract>(genXData =>
     {
        //Files we will be adding to the zip file 
        Dictionary<string, string> mainZipFileDictionary = new Dictionary<string, string>();
     
        //Get a list of customizations. Using Db context, because GetList returns too much data.
        var customizations = Db.XXXDef.Where(x => x.ProductID == "EP" && x.TypeCode == "Customization" && x.Company != "000000" ).Select(x => new { x.Company, Form = x.Key2, Name = x.Key1, x.Key3}).ToList();
        
        //Loop through the list..
        foreach(var item in customizations)
        {
            try
            {
                //Get the table data
                string cgCCode = "";
                GenXDataTableset genXDataTS = genXData.GetByID(item.Company, "EP", "Customization", cgCCode, item.Name, item.Form, item.Key3);   
 
            
                //Add all to zip file
                mainZipFileDictionary.Add($"{item.Company}/{item.Form}.{item.Name}.json", GetTablesetBytesAsB64(genXDataTS));
            
            }
            catch (Exception iEx)
            {
                //Continue processing on error, but add errors to the errors list.
                iEx.Data.Add("Company.FormID.Name", $"{item.Company}{item.Form}.{item.Name}");
                ListErrorJson = AddExceptionToList(iEx, ListErrorJson);
            }            
        }
     
        
        //Zip the files
        string fileDictionaryJson = JsonConvert.SerializeObject(mainZipFileDictionary);
        
        //Return the zip file data as a Base64 encoded string.
        ZipBase64 = ThisLib.ZipFiles(fileDictionaryJson);
     });
     
     
     
     Success = true;
     
  //****   
  }
  catch (Exception ex)
  {
      Success = false;
      ListErrorJson = AddExceptionToList(ex, ListErrorJson);
  }
  finally
  {
      //Maybe later?
  }
3 Likes