Finding orphaned Records in tables using RefRecId

Dynamics AX makes us the RefRecId, RefTable and RefCompany data pattern in a number of tables the system to provide flexible linking from a common/generic table such as WorkflowWorkitemTable to a variety of specific tables such as PurchReq or PurchTable.

Examples of this include Workflowtables, DocuRef, SpecTrans,  etc…

From time to time you may want to identify which of the records in these tables have become “orphaned” i.e. the documents that they refer to no longer exist. To do this in a fairly generic way you can make use SysDictTable’s makeRecord functionality as below (Using DocuRef as an example)

static void Check_Orphans(Args _args)
{
SpecTrans specTrans;
DocuRef docuref;
counter i;
Common record;
SysDictTable table;

while select forupdate * from docuref// where SpecTrans.RefTableId == 865 && SpecTrans.RefCompany==’an’// 866 for Debtors
{
table = new SysDictTable(docuref.RefTableId);
changeCompany(docuref.RefCompanyId)
{
record = table.makeRecord();
select firstonly * from record where record.RecId == docuref.RefRecId;
if(!record.RecId)
{
info(strFmt(“Record %1 has been orphaned”, docuref.caption()));
//Delete if necessary over here…
i++;
}
}
}
info(strFmt(“%1 orphaned records found”,i));
}

I hope you find this a useful trick in your AX wanderings.

Workflow: User Selectable Approver

A question that has come across on a number of occassions on the Dynamics Community forum is how can one allow the creator of a document to select an approver to approve the document. We did do a variation on this request for a client a couple of years ago, so here is one way to do it.

Summary

1. Create a custom field to store the approver on the record you are workflowing
2. Allow the user to populate this field (either directly on the record’s form, or via a pop-up request) on submission.
3. Create a custom participant provider that can resolve the user selected in #2
4. Modify your configuration to use this participant provider.

Details
For this example I will make use of the PurchReqTable and its workflows

1. Create Custom Approver field

  1. Open the AOT, Data Dictionary, expand Tables, locate PurchReqTable. Expand the node and expand the fields node.
  2. Right Click on fields, click new -> String
  3. Rename your field (e.g. ChosenApprover) and provide a suitable Label

C1

2. Allow the user to populate this field
Option A – Allow modification directly on the form:

  1. Open the AOT, expand the forms node, locate and expand the PurchReqTable node.
  2. Right click on data sources, click “open in new window”
  3. Expand the PurchReqTable datasource, expand the fields node
  4. Drag the “Chosen Approver” field to a relevant place on your form E.G. Designs->Design->Tabl->TabPageDetails->TabDetails->TabPageheader->TabHeader->TabPageHeaderGeneral->HeaderAdministration

C2

Option B:

  1. Locate the Class behind your workflow’s Submit button. E.G. PurchReqWorkflow.
  2. Before the code line “if (ret && purchReqWorkflow.dialogOk())’ add code to prompt the submitter to enter a user.
  3. Save the selected user to the PurchReqTable

C3

3. Create a custom participant provider to resolve the ChosenApprover

  1. Open the AOT, right click on Classes, click “New Class”
  2. Rename Your class to “ChosenApproverParticipantProvider”
  3. Edit the class declarationand implement the “WorkflowParticipantProvider” interface
    E.g. class ChosenApproverParticipantProvider implements WorkflowParticipantProvider
  4. Create a new method called “getParticipantToken” with the following code to present a single resolution option to the users…
    public WorkflowParticipantTokenList getParticipantTokens()
    {
    WorkflowParticipantTokenList tokens = WorkflowParticipantTokenList::construct();
    ;
    tokens.add(“CHOSENAPPROVER”, “User selected Approver”);
    return tokens;
    }
  5. Create a new method to resolve the token above called “resolve” with the following code (this code assumes that the provider will only be used from a purchase requisition and will not have resolution options other than “chosenApprover”, also it assumes that all requisitions will have the ChosenApprover field filled in:
    public WorkflowUserList resolve(WorkflowContext _context,
    WorkflowParticipantToken _participantTokenName)
    {
    PurchReqTable purchReqTable;
    WorkflowUserList userList = WorkflowUserList::construct(); //Retrieve the requisition from the workflow context
    purchReqTable = PurchReqTable::find(_context.parmRecId());
    userList.add(PurchReqTable.ChosenApprover); return userList;
    }
  6. Save your class.
  7. Expand the Workflow node in the AOT, expand “providers”, right click on “participantProviders” and click “New Participant Assignment Provider”
  8. Rename the Provider to ChosenApproverParticipantProvider (similar to your class name)
  9. Right click on the provider, click properties.
  10. Provide a suitable label for the provider e.g. “Chosen approver provider”
  11. If your record is a cross company table select AssociationType of “Global”
  12. Choose “No” under “available for all workflow types” as this provider assumes that a PurchaseRequisition is being used.
  13. Under “ProviderClass” enter the name of your class created above. “ChosenApproverParticipantProvider”
    C4
  14. Associate your provider with the PurchReqWorkflow type: On expand your “ChosenApproverParticipantProvider” AOT node, right click on “workflow types”, click “new workflow type”. Right click on the newly created node, click properties, select the relevant workflow type under the “workflowType” Option. E.G. PurchReqReview
    C5
  15. Save the ParticipantProvider.

4. Modify your configuration to use this participant provider.

  1. Perform a CIL compile and close and open AX client for your changes to take effect.
  2. Navigate to your workflow configuration and click “edit”. E.G. Procurement and Sourcing -> Setup -> Procurement and sourcing workflows -> Select PurchReqReview configuration.
  3. Locate the node that you would like to assign to your Chosen User. Click assignment in the toolbar.
  4. On the assignment type tab, select Participant
  5. Click on the “Role Based” tab.
  6. Under type of participant select “Chosen Approver Provider”
  7. Under Participant select “User selected Approver”
  8. Save and close your workflow
  9. Ensure you activate the workflow version you just created!

All done! Test and enjoy!