danielejdm / D365-ConfigurableEntityCloner

This solution allows for configurable cloning of entities/records, link-entities (child), relationships, associations, connections and attributes, in Dynamics 365, at any depth level.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

D365 Configurable Entity/Record Cloner

This solution allows for configurable cloning of entities/records, link-entities (child), relationships, associations, connections and attributes, in Dynamics 365, at any depth level.

Description

There are sometimes use cases where cloning of record(s), relationship(s) and associaton(s) is required. The idea behind this solution came as a result of some requirements needed for a project, where various record cloning functionalities with specific rules were required, such as cloning an account with some fields, associated contacts, annotations, etc.
The goal was to have a single component with the ability to configure cloning information and thus provide a No-Code/Low-Code solution.

Features

  • Configurable cloning of entities and sub-entities (child entities).
  • Configurable cloning of associations (n:m relationships).
  • Configurable cloning of connections and connected records.
  • Configurable set of fields to be cloned.
  • Automatically skipping of fields not valid for being set in creation.
  • Modularization of configurations (splitting).

Getting started

Prerequisites

Dynamics 365 v9.2+

Install

Download the managed or unmanaged solution and import it in your environment.

Configure

  • Create a configuration record for each needed cloning functionality. image

  • Provide a meaningful name.

  • Provide the xml representing entities, filters, relationships, associations, attributes, etc. for cloning a specific entity.

  • The root entity cannot be an intersect-entity (entity for the n:m relations).

  • The attribute link-type in the FetchXml has no effect:

    • The action always applies an outer join.
  • The cloner module skips all the system fields not valid for creation (i.e.: createdon, createdby, statecode, etc.).

Sample Config Xml

<fetch>
  <entity name="account" >
    <attribute name="name" />
    <attribute name="accountnumber" />
    <filter>
      <condition attribute="statecode" operator="eq" value="0" />
    </filter>
    <link-entity name="new_new_ddentity_account" from="accountid" to="accountid" intersect="true">
      <attribute name="new_ddentityid" />
      <attribute name="accountid" />
      <link-entity name="new_ddentity" from="new_ddentityid" to="new_ddentityid" intersect="true" clone-behaviour="clone">
          <attribute name="new_name" />
          <filter> 
            <condition attribute='statecode' operator='eq' value='0' /> 
          </filter> 
      </link-entity>
    </link-entity>
    <link-entity name="contact" from="parentcustomerid" to="accountid" >
      <attribute name="address1_city" />
      <attribute name="address1_country" />
      <attribute name="address1_line1" />
      <link-entity name="annotation" from="objectid" to="contactid" >
        <attribute name="filename" />
      </link-entity>
    </link-entity>
    <link-entity name="phonecall" from="regardingobjectid" to="accountid" >
      <attribute name="subject" />
      <filter> 
        <condition attribute='statecode' operator='eq' value='0' /> 
      </filter> 
    </link-entity>
  </entity>
</fetch>

Config Xml - Properties

  • clone-behaviour (required only for intersect-entity): associate/clone
    • clone -> the associated entity is cloned and the clone is associated to the new parent
    • associate (default) -> the associated entity is not cloned: it is associated to the new parent

Config Xml - Connections

The connections (entity connection) are represented with the following xml-block:

    <fetch>
      <entity name="connection">
        <attribute name="record1roleid" />
        <attribute name="record2roleid" />
        <attribute name="record2id" />
        <attribute name="record1id" />
        <attribute name="record2objecttypecode" />
        <attribute name="record1objecttypecode" />
        <filter>
          [<condition attribute="record1roleid" operator="eq" value="<Id of the Role1>" />]
          [<condition attribute="record2roleid" operator="eq" value="<Id of the Role2>" />]
        </filter>
        <link-entity name="contact" from="contactid" to="record2id">
          <attribute name="address1_composite" />
          <attribute name="firstname" />
          <attribute name="fullname" />
        </link-entity>
        <link-entity name="account" from="accountid" to="record1id">
          <attribute name="address1_composite" />
          <attribute name="name" />
        </link-entity>
      </entity>
    </fetch>
  • the following attributes for the connection entity are all required:
    • record1roleid
    • record2roleid
    • record2id
    • record1id
    • record2objecttypecode
    • record1objecttypecode
  • the two linked entities are necessary for providing information of the entities that are connected and will be cloned
  • in the filter for the connection entity we can insert the id of the role1 and role2 for which we want to look
  • the associated entities (xml-blocks for record1 and record2) do not support filters (for the moment)
  • connections do not support link-entity (for the moment): a connection is always the leaf of a branch in the xml

Config Xml - Modularization

It is possible to modularize Config-Xml to allow splittig of configurations and reuse the single configuration. Below an example of config modularization:

  • Config1
    <fetch>
     <entity name='contact' >
       <attribute name='firstname' />
       <attribute name='lastname' />
       <filter>
         <condition attribute='statuscode' operator='eq' value='1' />
         <condition attribute='contactid' operator='eq' value='@id' />
       </filter>
       <link-entity name='annotation' from='objectid' to='contactid' >
         <attribute name='subject' />
       </link-entity>
     </entity>
   </fetch>
  • Config2
   <fetch>
    <entity name='account'>
      <attribute name='address1_composite' />
      <attribute name='name' />
      <filter>
        <condition attribute='accountid' operator='eq' value='@id' />
      </filter>
      <link-entity name='contact' from='parentcustomerid' to='accountid' merge-config-id='{config1.Id}' />
    </entity>
  </fetch>
  • The Config1 can be used stand-alone or can be integrated into another Config-Xml (in the example, Config2).
  • The attribute merge-config-id contains the Guid of the Config-Xml that has to be integrated in the Config2 (in the example, Config1).
  • After merging, the config-xml looks like following:
  <fetch>
    <entity name="account" >
      <attribute name="address1_composite" />
      <attribute name="name" />
      <filter>
        <condition attribute="accountid" operator="eq" value="@id" />
      </filter>
      <link-entity name="contact" from="parentcustomerid" to="accountid" >
        <attribute name="firstname" />
        <attribute name="lastname" />
        <filter>
          <condition attribute="statuscode" operator="eq" value="1" />
        </filter>
        <link-entity name="annotation" from="objectid" to="contactid" >
          <attribute name="subject" />
        </link-entity>
      </link-entity>
    </entity>
  </fetch>

Usage

  • Integrate the action CloneEntityFromFetch where you want to trigger it (Workflow, Javascript function, etc.).
  • Configure the parameters:
    • RootRecordInfo:
      • Url of the root entity (parameter Record Url (Dynamic) in Workflow configuration) or
      • Guid of the root entity as string
    • EntityName: schema name of the root entity. This parameter is required if the parameter RootRecordInfo is a simple guid (not an url).
    • Configuration: EntityReference to the configuration record.

Note

  • This solution is work in progress:
    • it will be update frequently
    • it is not fully tested: if you find any bug, please open an issue or push a fix on a new branch
  • Technically the solution should allow an unlimited number of levels for link-entities, however always consider the 2-minute limit for running Plugins/CWAs. Analyze the amount of data involved in fetching.

Back matter

Acknowledgements

Thanks to all who helped inspire this solution.

License

This project is licensed under the GPLv3.

About

This solution allows for configurable cloning of entities/records, link-entities (child), relationships, associations, connections and attributes, in Dynamics 365, at any depth level.

License:GNU General Public License v3.0


Languages

Language:C# 100.0%