Friday, April 25, 2025

Handling Dimension Data: Validating Defaults and Offsets in Code

 Hi everyone,

Recently, I encountered a requirement to create a journal entry against a vendor. However, there’s an important condition: if the vendor has a matching policy enabled, the system should restrict creating a ledger journal for that vendor.

To handle this, I implemented a validation that triggers whenever a Vendor ID is selected at the journal line level. This check ensures that if the vendor has a matching policy, the system will block the action and notify the user accordingly.

In this post, I’ll Walk you through:

  • How I implemented the vendor validation logic

  • How default and offset dimension validation works

The SegmentedEntryControl is used to input ledger accounts and financial dimension combinations. To enforce custom validation logic, follow these steps:​

  1. Create a CoC Extension for SegmentedEntryControl: Use the Chain of Command to extend the SegmentedEntryControl class.

  2. Override the validate () Method: Within your extension, override the validate () method to include your custom validation logic.

  3. Implement Vendor Matching Policy Check: In your overridden method, retrieve the selected Vendor ID and check if the vendor has a matching policy enabled. If so, prevent the creation of a ledger journal.

Here's a sample implementation:

[ExtensionOf(classStr(SegmentedEntryControl))]
 final class SegmentedEntryControl_Extension
{
    public boolean validate()
    {
        boolean isValid = true;
       
        DimensionControlSegment segment;
        VendTable  VendTable;
        LedgerJournalName LedgerJournalName;

        isValid = next validate();

       //Common table = formRefDataSource.cursor();
        str journalName = dimensionController.parmJournalName();;
       // LedgerJournalTrans ledgerJournalLine = table;
        Ynv_LedgerJournalName = LedgerJournalName::find(journalName);
        EnumName accountType = accountTypeEnumType;
        int number = dimensionController.parmAccountType();
        ModuleInventCustVend model = dimensionController.parmCustVend();

        if (currentControlInfo && number == 2)//&& ledgerJournalLine.AccountType == LedgerJournalACType::Vend)
        {
            // Print segment error messages
            for (int ind = 1; ind <= currentControlInfo.parmSegments().lastIndex();ind++)
            {
                segment = currentControlInfo.parmSegments().value(ind);                

                VendTable = VendTable::find(segment.parmValue());

                if ((VendTable.MatchingPolicy == PurchMatchingPolicyWithNotSetOption::ThreeWayMatch || VendTable.MatchingPolicy  == PurchMatchingPolicyWithNotSetOption::TwoWayMatch))
                {
                    throw Error (strFmt("Invoice journal does not create without purchase order of this %1 vendor",VendTable.AccountNum));
                  
                    isValid =false;
                }
                else if(VendTable.MatchingPolicy == PurchMatchingPolicyWithNotSetOption::NotSet)
                {
                    if((Vend Parameters::find().MatchingPolicy == PurchMatchingPolicyOption::ThreeWayMatch || VendParameters::find().MatchingPolicy == PurchMatchingPolicyOption::TwoWayMatch))
                    {
                        throw Error(strFmt("Invoice journal does not create without purchase order of this %1 vendor",_VendTable.AccountNum));
                      
                        isValid =false;
                    }
                }

            }
        }
        return isValid;
    }

}

The validate() method in the SegmentedEntryControl class can be overridden using Chain of Command (CoC) to apply custom validation logic to both the Ledger Dimension and Offset Dimension fields in Dynamics 365 Finance and Operations. This approach ensures that your validation logic is consistently applied across different segmented entry controls.

No comments:

Post a Comment