Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Unanswered

PurchLines validation when confirming the oder

(1) ShareShare
ReportReport
Posted on by 1,493
Hi,

So the requirement is to do some validations on each sales line before confirming the order.
if the enum XType value is Must, then an error should be returned.
However, if the XType value is option, then a warning should appear but, the process should proceed.

I did this, but i have two issues/concerns:

1. Is this the best place to perform such validation? and if it's the best place, shall i use _calledFrom for anything?
2.  i want all warnings to appear, but currently the first warning would only be returned and it won't continue and return all warnings. So for example if the Xtype is optional for all lines in the sales order, then i want all warnings to appear, so that after confirming the order, the user can look at all warnings and amend the value


[ExtensionOf(classStr(PurchFormLetter_Confirmation))]
final class PurchFormLetter_ConfirmationX_Extension
{
    public boolean  validate(Object _calledFrom)
    {
        boolean ret;
        
        ret = next validate(_calledFrom);
        if(ret)
        {
            PurchLine purchLine;
            while select purchLine where purchLine.PurchId == this.PurchTable().PurchId
            {
                TableX tableX;
                select firstonly tableX where tableX.ItemId == purchLine.ItemId;
                if(tableX)
                {
                    this.validateFirstField(purchLine, tableX);
                    this.validateSecondField(purchLine, tableX);
                }
            }
        }
        return ret;
    }
    public void validateFirstField(PurchLine _purchLine, TableX _tableX)
    {
        if(_tableX.FirstField == XType::Must && _purchLine.FirstField== '')
        {
            throw error(strFmt(/The FirstField for itemId: %1,  is must be filled/, _purchLine.ItemId));
        }
        else if(_tableX.FirstField == XType::Optional && _purchLine.FirstField== '')
        {
            checkFailed(strFmt(/The FirstField for itemId: %1,  is preferred be filled/, _purchLine.ItemId));
        }
    }
    public void validateSecondField(PurchLine _purchLine, TableX _tableX)
    {
        if(_tableX.SecondField == XType::Must && _purchLine.SecondField == '')
        {
            throw error(strFmt(/The SecondField for itemId: %1,  is must be filled/, _purchLine.ItemId));
        }
        else if(_tableX.SecondField == XType::Optional && _purchLine.SecondField == '')
        {
            checkFailed(strFmt(/The SecondField for itemId: %1,  is preferred be filled/, _purchLine.ItemId));
        }
    }
}
  • André Arnaud de Calavon Profile Picture
    293,278 Super User 2025 Season 1 on at
    PurchLines validation when confirming the oder
    Hi IntegrationBeginner,
     
    You provided a lot of details. I'm getting lost. You have another question about being able to choose lines being part of the confirmation. Let's focus here on the warnings to get them on the form.
     
    Instead of having the validations in coding as extension of class PurchFormLetter_Confirmation, you can extend or replace the form menu item button control calling the confirmation. You can then perform the validations on the form and in that way have the warnings and error messages on the form instead of in the action center.
  • .. Profile Picture
    1,493 on at
    PurchLines validation when confirming the oder
     

    Hi Andre,

    1. Yes when the dialog appears, notifications go to action center. I tried the code below as you suggested but still i got the same result, could it be that I need to change where i placed the code? I mean maybe i should put the validation on the dialog itself before it closes in this case?
     
    [ExtensionOf(classStr(PurchFormLetter_PurchOrder))]
    final class PurchFormLetter_PurchOrderX_Extension
    {
        private boolean must = false;
        private List    warnings= new List(Types::String);

        public boolean  validate(Object _calledFrom)
        {
            boolean ret;
            
            ret = next validate(_calledFrom);
            if(ret)
            {
                PurchLine purchLine;
                while select purchLine where purchLine.PurchId == this.PurchTable().PurchId
                {
                    TableX tableX;
                    select firstonly tableX where tableX.ItemId == purchLine.ItemId;
                    if(tableX)
                    {
                        this.validateFirstField(purchLine, tableX);
                        this.validateSecondField(purchLine, tableX);
                    }
                }
                
                if(warnings && warnings.elements())
                {
                    ListEnumerator listEnumerator = warnings.getEnumerator();
                    if(listEnumerator)
                    {
                        while(listEnumerator.moveNext())
                        {
                            warning(listEnumerator.current());
                        }
                    }
                }
               if(must)
               {
                  throw error("fix all errors");
               }
            }
            return ret;
        }
     
        public void validateFirstField(PurchLine _purchLine, TableX _tableX)
        {
            if(_tableX.FirstField == XType::Must && _purchLine.FirstField== '')
            {
                 error(strFmt("The FirstField for itemId: %1,  is must be filled", _purchLine.ItemId));
                 must = true;
            }
            else if(_tableX.FirstField == XType::Optional && _purchLine.FirstField== '')
            {
                //warning(strFmt("The FirstField for itemId: %1,  is preferred be filled", _purchLine.ItemId));
                warnings.addEnd(strFmt("The FirstField for itemId: %1,  is preferred be filled", _purchLine.ItemId));
            }
        }
        public void validateSecondField(PurchLine _purchLine, TableX _tableX)
        {
            if(_tableX.SecondField == XType::Must && _purchLine.SecondField == '')
            {
                error(strFmt("The SecondField for itemId: %1,  is must be filled", _purchLine.ItemId));
                must = true;
            }
            else if(_tableX.SecondField == XType::Optional && _purchLine.SecondField == '')
            {
                //warning(strFmt("The SecondField for itemId: %1,  is preferred be filled", _purchLine.ItemId));
                warnings.addEnd(strFmt("The SecondField for itemId: %1,  is preferred be filled", _purchLine.ItemId));
            }
        }
    }

    2. I've noticed that in PurchOrders, I can't choose which Lines to confirm even though there is PurchParmTable and PurchParmLine. So is it safe to always loop through PurchLine like what I'm doing now? or would there be a case where we can choose which purchLines to confirm from the UI?

    3. You've noticed that i put a similar question to sales order (https://community.dynamics.com/forums/thread/details/?threadid=c70b065b-022c-ee11-bdf4-000d3a55bb34). In sales orders i can choose which lines to confirm, so i now realized that putting this is wrong when doing validations
     
    while select salesLine where salesLine.SalesId == this.salesTable().SalesId
    {
    }

    and I will replace it with this, so that the validation works on the lines that were selected to be confirmed
    SalesLine      salesLine;
    SalesParmLine  salesParmLine;
    SalesParmTable salesParmTableLocal;
    
    select salesParmTableLocal where salesParmTableLocal.ParmId == this.salesParmUpdate().ParmId;
    
    while select FirstField, SecondField, ItemId from salesLine where salesLine.SalesId == this.salesTable().SalesId
        exists join salesParmLine where salesParmLine.SalesLineRecId == salesLine.RecId
        && salesParmLine.ParmId == salesParmTableLocal.ParmId
        && salesParmLine.TableRefId == salesParmTableLocal.TableRefId
    {
    }
    I've noticed that SalesParmLine gets filled in both, when i click confirm now(without dialog) and when i click confirmation (where dialog appears)
    So my question is, is it safe to always use SalesParmLine instead of looping SalesLine incase of clicking confirmation without dialog??
  • André Arnaud de Calavon Profile Picture
    293,278 Super User 2025 Season 1 on at
    PurchLines validation when confirming the oder
    Thanks for the screenshots. The issue is fully clear now. In case the application thinks that some actions are performed without a form reference, it would end up in the action center. In this case, I would then expect all warnings in the action center or all on the form. I do agree with you that this is inconsistent.
    You can try to store all messages in variables and use a loop at the end of the validation process to raise all warnings and errors at the same time. Not sure if this would solve it, but I would try such approach myself as workaround. 
  • .. Profile Picture
    1,493 on at
    PurchLines validation when confirming the oder
    Hi Andre,

    here's the output when i click on confirmation  -- I should be seeing four warnings, but only one appeared on the UI, and the rest of the three warnings appeared in notifications in action center




    and here's the output when i click on confirm


  • André Arnaud de Calavon Profile Picture
    293,278 Super User 2025 Season 1 on at
    PurchLines validation when confirming the oder
    Hi Integration beginner,
     
    Can you verify if there is an additional button to show more warnings. On the form itself (yellow bar) it will initially show one warning, but you can expand it in case there are more lines. If you need a bit more help, please share a screenshot of the screen including the warning.
  • .. Profile Picture
    1,493 on at
    PurchLines validation when confirming the oder
    Hi Andre,

    I did it like this, however I'm facing an issue.

    you know that confirmation gets called from two menu items, Confirm and Confirmation... where in confirmation a dialog is opened.


    I've noticed that in the case where only warnings are returned, when i click confirm, all warnings appear on the purch order form. But when i click "Confirmation" only one warning appear on the form. why?? I mean if let's say 3 warnings are returned one of them appear on the UI, while the three appear as notifications in action center, why not all of them appear in the form similar to when clicking confirm button.

    **in case there was an error, all warnings appear in both cases as expected
     
    [ExtensionOf(classStr(PurchFormLetter_PurchOrder))]
    final class PurchFormLetter_PurchOrderX_Extension
    {
        private boolean must = false;

        public boolean  validate(Object _calledFrom)
        {
            boolean ret;
            
            ret = next validate(_calledFrom);
            if(ret)
            {
                PurchLine purchLine;
                while select purchLine where purchLine.PurchId == this.PurchTable().PurchId
                {
                    TableX tableX;
                    select firstonly tableX where tableX.ItemId == purchLine.ItemId;
                    if(tableX)
                    {
                        this.validateFirstField(purchLine, tableX);
                        this.validateSecondField(purchLine, tableX);
                    }
                }
     
               if(must)
               {
                  throw error("fix all errors");
               }
            }
            return ret;
        }
     
        public void validateFirstField(PurchLine _purchLine, TableX _tableX)
        {
            if(_tableX.FirstField == XType::Must && _purchLine.FirstField== '')
            {
                 error(strFmt("The FirstField for itemId: %1,  is must be filled", _purchLine.ItemId));
                 must = true;
            }
            else if(_tableX.FirstField == XType::Optional && _purchLine.FirstField== '')
            {
                warning(strFmt("The FirstField for itemId: %1,  is preferred be filled", _purchLine.ItemId));
            }
        }
        public void validateSecondField(PurchLine _purchLine, TableX _tableX)
        {
            if(_tableX.SecondField == XType::Must && _purchLine.SecondField == '')
            {
                error(strFmt("The SecondField for itemId: %1,  is must be filled", _purchLine.ItemId));
                must = true;
            }
            else if(_tableX.SecondField == XType::Optional && _purchLine.SecondField == '')
            {
                warning(strFmt("The SecondField for itemId: %1,  is preferred be filled", _purchLine.ItemId));
            }
        }
    }
  • André Arnaud de Calavon Profile Picture
    293,278 Super User 2025 Season 1 on at
    PurchLines validation when confirming the oder
    Hi IntegrationBeginner,
     
    Instead if using the throw error, use just an error and warning statement. This will ensure that the loop will continue. To be able to block the user when there is an error, you can use another boolean variable that will be set to true in case of the error. After the loop, you can then evaluate if the boolean is set to true. Then you can use a throw command and inform the user that he needs to solve the error before he can continue. 

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Daivat Vartak – Community Spotlight

We are honored to recognize Daivat Vartak as our March 2025 Community…

Announcing Our 2025 Season 1 Super Users!

A new season of Super Users has arrived, and we are so grateful for the daily…

Kudos to the February Top 10 Community Stars!

Thanks for all your good work in the Community!

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 293,278 Super User 2025 Season 1

#2
Martin Dráb Profile Picture

Martin Dráb 232,011 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156 Moderator

Leaderboard

Product updates

Dynamics 365 release plans