D365 F&O - Adding custom entities to Case Management

Case management is a generic cross module solution where you can log cases with or without a defined process and keep a information. A case can be related to a number of various entities in the solution.
There are 11 case categories where you can group processes:
  • General
  • Sales
  • Purchase
  • Service
  • Project
  • Production
  • Collections
  • Audit
  • Human Resources
  • FMLA
  • Product Change
You also have 27 entities you can associate the case with:
  • None
  • Lead
  • Opportunity
  • Customer
  • Vendor
  • Prospect
  • Project
  • Sales order
  • Purchase order
  • Worker
  • Service order
  • Item
  • Customer transaction
  • Expense report
  • Expense report line
  • Vendor invoice
  • Vendor invoice line
  • Purchase order line
  • Returned order
  • Case
  • Product
  • BOM/Formula
  • Route
  • Production order
  • Quality order
  • Customer invoice
  • Customer invoice line

Both categories and entities can be extended.
We also added a lot of other entities to our standard expansion solution to our customers. For example, I created new entity 'Contract'.

 
For the above created entity, I will explain the steps one by one.
1. Add your entities to the Entity type BaseEnum (CaseEntityType).

Extend 'CaseEntityType' enum. Add your entity type. I added new element 'Contract'.

 

2. Make the Association Provider class (contractAssociationProvider) be able to look up the data for the new entity

using System.ComponentModel.Composition;

/// <summary>
/// Plug in for case associations.
/// </summary>
[ExportMetadataAttribute('CaseIAssociation', 'Contract'), ExportAttribute('Dynamics.AX.Application.CaseIAssociation')]
class contractAssociationProvider  implements CaseIAssociation
{
    public void insertCaseAssociation(CaseAssociation _caseAssociation)
    {
    }

    public SelectableDataArea getLinkedCompany(RefRecId _parentRecId)
    {
        Contract contractTable;
        select firstonly DataAreaId from contractTable where contractTable.RecId == _parentRecId;

        return contractTable.company();
    }

    public CaseAssociationLinkId getLinkedId(RefRecId _parentRecId)
    {
        Contract contractTable;
        select firstonly ContractNum from contractTable where contractTable.RecId == _parentRecId;

        return contractTable.ContractNum;
    }

    public RefRecId getRecIdWithNaturalKey(CaseAssociationLinkId _naturalKey)
    {
        Contract contractTable;
        select firstonly RecId from contractTable where contractTable.ContractNum == _naturalKey;

        return contractTable.RecId;
    }

    public CaseLinkedName getLinkedName(RefRecId _parentRecId)
    {
        Contract contractTable;
        select PropertyId from contractTable where contractTable.RecId == _parentRecId;

        return contractTable.PropertyId;
    }

    public str getJumpRefMenuItem(args _args, CaseAssociation _association)
    {
        Contract contractTable;
        select firstonly * from contractTable where contractTable.RecId == _association.RefRecId;

        _args.record(contractTable);
        return menuitemdisplaystr(Contract);
    }

    public void performLookup(FormStringControl callerControl, CaseAssociation _caseAssociation)
    {
        SysTableLookup oSysTableLookup = SysTableLookup::newParameters(tablenum(Contract), callerControl);

        Query oQuery = new Query();
        QueryBuildDataSource oqbds = oQuery.addDataSource(tablenum(Contract));

        oSysTableLookup.addLookupfield(fieldnum(Contract, ContractNum));
        oSysTableLookup.addLookupfield(fieldnum(Contract, PropertyId));
        oSysTableLookup.addLookupfield(fieldnum(Contract, CustAccount));    
        oSysTableLookup.addLookupMethod(tableMethodStr(Contract, custName));    
        oSysTableLookup.parmQuery(oQuery);
        oSysTableLookup.performFormLookup();
    }

    /// <summary>
    /// Subscribes to the <c>CaseAssociation.getCaseEntityType()</c> event.
    /// </summary>
    /// <param name="_refTableId">
    /// The table ID of the table associated with the case.
    /// </param>
    /// <param name = "_eventArgs">
    /// The arguments for the event.
    /// </param>
    [SubscribesTo(tableStr(CaseAssociation), delegatestr(CaseAssociation, getCaseEntityType))]
    public static void getCaseEntityType(TableId _refTableId, CaseAssociationGetEntityTypeEventArgs _eventArgs)
    {
        if (_refTableId == tableNum(Contract))
        {
            _eventArgs.parmEntityType(CaseEntityType::Contract);
        }
    }

}

3. Create relations from the case association table (CaseAssociation) to the new entity tables

Extend 'CaseAssociation' table. Create relation to custom entity. Set the parameter “UseDefaultRoleNames” to “Yes”.


4. Create new form 'CaseInformation_Contract'. Add custom entity as datasource.

Create display menuitem for the created form. I named as ' CaseInformation_Contract'

5. Add dynamic form to the 'CaseDetail' form

  • Extend 'CaseDetail' form. Add the 'CaseInformation_Contract' form part in Case Details --> Design --> Tab --> TabPageDetails --> TabHeader --> AssociationsTabPage --> Group_MoreInformation
  • Add new form part in this group. Link our 'CaseInformation_Contract' menuitem.
The properties of form part as below.



6. Create EventHandler class (contrCaseDetailEventHandler) for custom entity. 

class contrCaseDetailEventHandler
{

    

    /// <summary>
    /// Post event handler for <c>CaseDetail</c> form's <c>showMoreInformation</c> method.
    /// </summary>
    /// <param name="_args">A <c>XppPrePostArgs</c> instance.</param>
    [PostHandlerFor(formStr(CaseDetail), formMethodStr(CaseDetail, showMoreInformation))]
    public static void CaseDetail_Post_showMoreInformation(XppPrePostArgs _args)
    {
        FormRun formRun = _args.getThis();
        DictClass dictClass = new DictClass(classIdGet(formRun));
        CaseAssociation caseAssociation = formRun.dataSource(formdatasourcestr(CaseDetail, CaseAssociation)).cursor() as CaseAssociation;

        boolean showContrTable     = (caseAssociation.EntityType == CaseEntityType::Contract);
        
        boolean showMoreInformationGroup = (showContrTable);

        
        formRun.design().controlName(formControlStr(CaseDetail, caseMoreInformation_Contract)).visible(showContrTable);

        formRun.design().controlName(formControlStr(CaseDetail, caseMoreInformation_None)).visible(!showMoreInformationGroup);
    }

}

7. Add the form actions to create and view related cases

Add ' Create Case' menuitem in custom form. 

8. Build the changes and check the association of new entity in case association.


Comments

  1. Really very great information for that post, am amazed and then more new information are get after refer that post. I like that post.
    CRM Software in Dubai
    CRM Software
    CRM Software in UAE
    Best CRM Software
    CRM Software for Small Business

    ReplyDelete

Post a Comment

Popular posts from this blog

Microsoft Dynamics CRM Time zones

Dynamics 365 user/audit logs