Archive customization (preview)

This article describes how the archive feature in Microsoft Dynamics 365 finance and operations apps supports customization. The archival framework supports extensions to include custom table fields and custom tables in supported functional scenarios.

Add custom fields in history tables and business intelligence entities

Custom fields that are added to a standard table must be added to the corresponding history table and the business intelligence (BI) entity. The customized BI entity must be refreshed in Dataverse to archive data with Dataverse long term retention.

History tables

Transactions records are moved to the history tables. The schema of a history table must match its corresponding live table. All columns in the live table must be present in its mirrored history table.

Column exclusion rule: SysRowVersion and SysDataState columns are added by the platform and managed by using table metadata properties. These columns don't have to be added to the history tables.

Business entity

Dataverse interacts with finance and Operations. These virtual entities are used to retrieve data from the finance and operations database and save it to the corresponding tables in the Dataverse long term retention.

Important

Don't add relationships between the entities.

Step 1: Add fields to the history table via extensions

The archival framework requires that all live table columns are mirrored in the corresponding history tables. Use table extensions to add the custom fields to history tables. For more information about how to add fields to history tables through extension in finance and operations apps, see Add fields to tables through extension.

Step 2: Add fields to BI entities via extensions

Additional fields that are added to live tables must be added to the corresponding BI entities.

Step 3: Refresh the virtual entity in Dataverse

The customized business entity must be refreshed in Dataverse to archive data in the Dataverse long-term retention store.

Add new tables to the archive scenario

Additional tables can be included in the archive scenario if they have a direct or indirect relationship with the main live table.

To create a history table that corresponds to the live table in the archive scope, follow these steps.

  1. Create a new history table that mirrors all fields from the corresponding live table, including all metadata properties on the live table. See the column exclusion rule earlier in this article.
  2. Don't mirror indexes from the live table in the history table. For most history tables, a clustered index on the RecId column is sufficient. Create an additional index to improve query performance as required and to maintain foreign key relationships.
  3. Extend the ArchiveAutomationJobRequestCreator class for a scenario to add the new table to archive table chart.

Code example

The following example shows how to customize the General ledger archive job request creator class to add a new table.

using Microsoft.Dynamics.Archive.Contracts; 
[ExtensionOf(classStr(LedgerArchiveAutomationJobRequestCreator] 
final class LedgerArchiveAutomationJobRequestCreator_GeneralLedger_Extension 
{
    public ArchiveJobPostRequest createPostJobRequestForArchiveTrans(LedgerArchiveTrans _archiveTrans 
    { 
        ArchiveJobPostRequest postRequest = next createPostJobRequestForArchiveTrans(_archiveTrans; 
        ArchiveServiceArchiveJobPostRequestBuilder builder = 
            ArchiveServiceArchiveJobPostRequestBuilder::createFromArchiveJobPostRequest(postRequest; 

        // Use builder to add more live tables, history tables, join conditions and where conditions (if needed 
        // Example: Adding my new general ledger table to archive table graph 
        var generalJournalAccountEntryTable = new DictTable(tableNum(GeneralJournalAccountEntry; 
        var generalJournalAccountEntryTableName = generalJournalAccountEntryTable.name(DbBackend::Sql; 
        var newMyNewGeneralLedgerTable = new DictTable(tableNum(MyNewGeneralLedgerTable; 
        var newMyNewGeneralLedgerTableName = newMyNewGeneralLedgerTable.name(DbBackend::Sql; 
        var newMyNewGeneralLedgerTableHistory = new DictTable(tableNum(MyNewGeneralLedgerTableHistory; 
        var newMyNewGeneralLedgerTableHistoryName = newMyNewGeneralLedgerTableHistory.name(DbBackend::Sql; 
        var myNewGeneralLedgerTableSourceTable = ArchiveServiceSourceTableConfiguration::newForSourceTable( 
            newMyNewGeneralLedgerTableName, 
            newMyNewGeneralLedgerTableHistoryName, 
            tableStr(MyNewGeneralLedgerTableBiEntity; 

        // Add parent table 
        myNewGeneralLedgerTableSourceTable.parmParentSourceTableName(generalJournalAccountEntryTableName; 
        builder.addSourceTableForLongTermRetention(myNewGeneralLedgerTableSourceTable 
            .addJoinCondition(newMyNewGeneralLedgerTableName, 
            newMyNewGeneralLedgerTable.fieldName(fieldNum(MyNewGeneralLedgerTable, GeneralJournalAccountEntry, DbBackend::Sql, 
            generalJournalAccountEntryTable.fieldName(fieldNum(GeneralJournalAccountEntry, RecId, DbBackend::Sql; 

        return builder.completeArchiveJobPostRequest(; 

Finance and operations table names in live, history, and Dataverse-managed data lake tables

Scenario Live table History table BI entity Dataverse-managed data lake table
Finance General ledger GENERALJOURNALACCOUNTENTRY GENERALJOURNALACCOUNTENTRYHISTORY GeneraljournalaccountentryBiEntity mserp_GeneraljournalaccountentryBiEntity
GENERALJOURNALACCOUNTENTRY_W GENERALJOURNALACCOUNTENTRYHISTORY_W GeneraljournalaccountentrywBiEntity mserp_GeneraljournalaccountentrywBiEntity
GENERALJOURNALENTRY GENERALJOURNALENTRYHISTORY cus mserp_GeneraljournalentryBiEntity
GENERALJOURNALENTRY_W GENERALJOURNALENTRYHISTORY_W GeneraljournalentrywBiEntity mserp_GeneraljournalentrywBiEntity
LEDGERCONSOLIDATEHISTREF LEDGERCONSOLIDATEHISTREFHISTORY LedgerconsolidatehistrefBiEntity mserp_LedgerconsolidatehistrefBiEntity
LEDGERENTRY LEDGERENTRYHISTORY LedgerentryBiEntity mserp_LedgerentryBiEntity
LEDGERENTRYJOURNAL LEDGERENTRYJOURNALHISTORY LedgerentryjournalBiEntity mserp_LedgerentryjournalBiEntity
LEDGERENTRYJOURNALIZING LEDGERENTRYJOURNALIZINGHISTORY LedgerentryjournalizingBiEntity mserp_LedgerentryjournalizingBiEntity
LEDGERTRANSSETTLEMENT LEDGERTRANSSETTLEMENTHISTORY LedgertranssettlementBiEntity mserp_LedgertranssettlementBiEntity
SUBLEDGERVOUCHERGENERALJOURNALENTRY SUBLEDGERVOUCHERGENERALJOURNALENTRYHISTORY SubledgervouchergeneraljournalentryBiEntity mserp_SubledgervouchergeneraljournalentryBiEntity
Supply Chain Management Sales order MCRRETURNSALESTABLE MCRRETURNSALESTABLEHISTORY McrreturnsalestableBiEntity mserp_McrreturnsalestableBiEntity
MCRSALESLINE MCRSALESLINEHISTORY McrsaleslineBiEntity mserp_McrsaleslineBiEntity
MCRSALESTABLE MCRSALESTABLEHISTORY McrsalestableBiEntity mserp_McrsalestableBiEntity
RETAILSALESLINE RETAILSALESLINEHISTORY RetailsaleslineBiEntity mserp_RetailsaleslineBiEntity
RETAILSALESTABLE RETAILSALESTABLEHISTORY RetailsalestableBiEntity mserp_RetailsalestableBiEntity
SALESLINE SALESLINEHISTORY SaleslineBiEntity mserp_SaleslineBiEntity
SALESLINE_BR SALESLINEHISTORY_BR SaleslinebrBiEntity mserp_SaleslinebrBiEntity
SALESLINE_IN SALESLINEHISTORY_IN SaleslineinBiEntity mserp_SaleslineinBiEntity
SALESLINE_W SALESLINEHISTORY_W SaleslinewBiEntity mserp_SaleslinewBiEntity
SALESTABLE SALESTABLEHISTORY SalestableBiEntity mserp_SalestableBiEntity
SALESTABLE_BR SALESTABLEHISTORY_BR SalestablebrBiEntity mserp_SalestablebrBiEntity
SALESTABLE_RU SALESTABLEHISTORY_RU SalestableruBiEntity mserp_SalestableruBiEntity
SALESTABLE_W SALESTABLEHISTORY_W SalestablewBiEntity mserp_SalestablewBiEntity
Supply Chain Management Inventory transaction INVENTTRANSARCHIVE INVENTTRANSARCHIVEHISTORY InventtransarchiveBiEntity mserp_InventTransArchiveBiEntity
Supply Chain Management Inventory Journal INVENTJOURNALTABLE INVENTJOURNALTABLEHISTORY InventjournaltableBiEntity mserp_InventjournaltableBiEntity
INVENTJOURNALTABLE_IN INVENTJOURNALTABLE_INHISTORY InventjournaltableinBiEntity mserp_InventjournaltableinBiEntity
INVENTJOURNALTRANS INVENTJOURNALTRANSHISTORY InventjournaltransBiEntity mserp_InventjournaltransBiEntity
INVENTJOURNALTRANS_IN INVENTJOURNALTRANS_INHISTORY InventjournaltransinBiEntity mserp_InventjournaltransinBiEntity
Finance Tax Trans TAXTRANS TAXTRANSHISTORY TaxtransBiEntity mserp_TaxtransBiEntity
TAXTRANS_BR TAXTRANSHISTORY_BR TaxtransbrBiEntity mserp_TaxtransbrBiEntity
TAXTRANSGENERALJOURNALACCOUNTENTRY TAXTRANSGENERALJOURNALACCOUNTENTRYHISTORY TaxtransgeneraljournalaccountentryBiEntity mserp_TaxtransgeneraljournalaccountentryBiEntity
TAXTRANS_IN TAXTRANSHISTORY_IN TaxtransinBiEntity mserp_TaxtransinBiEntity
TAXTRANS_IT TAXTRANSHISTORY_IT TaxtransitBiEntity mserp_TaxtransitBiEntity
TAXTRANS_REPORTING TAXTRANSHISTORY_REPORTING TaxtransreportingBiEntity mserp_TaxtransreportingBiEntity
TAXTRANS_RU TAXTRANSHISTORY_RU TaxtransruBiEntity mserp_TaxtransruBiEntity
TAXTRANSSUBLEDGERJOURNALACCOUNTENTRY TAXTRANSSUBLEDGERJOURNALACCOUNTENTRYHISTORY TaxtranssubledgerjournalaccountentryBiEntity mserp_TaxtranssubledgerjournalaccountentryBiEntity
TAXTRANS_TH TAXTRANSHISTORY_TH TaxtransthBiEntity mserp_TaxtransthBiEntity
TAXTRANS_W TAXTRANSHISTORY_W TaxtranswBiEntity mserp_TaxtranswBiEntity