web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

No record found.

News and Announcements icon
Community site session details

Community site session details

Session Id :
Customer experience | Sales, Customer Insights,...
Answered

Opportunity stages

(4) ShareShare
ReportReport
Posted on by 217
Hello,
 
How can I go about the  below.
 
For an opp record, I have a sales stage.  In that stage I have about 5 stages.  I need logic so that users can't go to the next stage withouth answering yes to all questions in that stage first. I can't mark them required because then the user can't make any other changes on the form and save it.  So I need to find a way to put logic in place that would not make those fields required, but prevent the user from moving to next stage if not all yeses.  Also to show a message letting the user know that they must first mark all fields in current stage before moving to next stage.
 
Any help is appreciated.  Thank you.
I have the same question (0)
  • Suggested answer
    Holly Huffman Profile Picture
    6,554 Super User 2026 Season 1 on at
    Good morning, afternoon, or evening :) depending on your location!
     
    To implement a conditional validation in Dynamics 365 without marking fields as "required," which would block other edits - you could achieve this by using business rules or JavaScript within the form.
     
    1. Using Business Rules (No-Code Option)
      • Create a business rule that checks if all necessary fields in the current stage are marked "Yes."
      • If any are missing, set a notification message on the form stating that all must be marked "Yes" before proceeding.
      • Additionally, you can disable the field that controls moving to the next stage until all conditions are met.
    2. Using JavaScript (More Flexible Option)
      • Write a script that runs when the user attempts to move stages.
      • Check if all required fields have a "Yes" value.
      • If any are missing, display a validation message and prevent the stage change.
      • Optionally, you can disable the stage transition button using setDisabled(true) if conditions aren’t met.
     
    Hope this helps!
  • Verified answer
    Tom_Gioielli Profile Picture
    3,084 Super User 2026 Season 1 on at
    Hi there!
     
    There is an important distinction to make between fields being required on a table, and a field being required in a Business Process Flow.
     
    Marking a field as required in the business process flow means a user cannot move to the next stage until that field has been populated. It does not mean the same thing as marking the field as required on the table or through JavaScript or Business Rules (so definitely don't do that).
     
    While building your Business Process Flow, check the box marked as "Required" on the fields in question. You'll find that the fields are only required to progress in the BPF and they are not required on your form.
     
    If this answer helped, please consider marking as verified.
  • Suggested answer
    Daivat Vartak (v-9davar) Profile Picture
    7,841 Moderator on at
    Part (1/3)
     
    Hello CU31101219-0,
     

    You can achieve this using a combination of Business Rules and Client-Side Scripting (JavaScript) in Dynamics 365. Here's a breakdown of how you can implement this logic:

    Approach 1: Using Business Rules (Simpler, but with Limitations)

    Business Rules are easier to configure but have limitations in controlling UI flow and displaying specific messages at the exact moment of stage change.

    1. Create a Business Rule on the Opportunity Entity:

      • Go to Settings > Customizations > Customize the System.
      • Expand Entities and select the Opportunity entity.
      • Go to the Business Rules tab.
      • Click + New. 

    2. Define the Scope: Set the scope of the Business Rule to Entity or All Forms depending on where you want this logic to apply.

    3. Create Conditions and Actions for Each Sales Stage: For each sales stage where you have these "Yes/No" questions:

      • Condition:

        • Check if the Sales Stage field is equal to your current stage value (e.g., "Qualification").
        • Add additional conditions to check if any of your "Yes/No" questions in that stage are answered as "No". 

      • Action (If any "No" is selected):

        • Show Error Message: Use the "Show Error Message" action.

          • Select the Sales Stage field.
          • Enter a message like: "Please ensure all questions in the [Current Stage Name] stage are answered with 'Yes' before moving to the next stage." 

        • Set Field Value (Optional but Recommended for Prevention):

          • Set the Sales Stage field back to the previous stage value. This will prevent the user from actually moving forward. You'll need a way to determine the previous stage. This can be tricky with just Business Rules. You might need a temporary field to store the previous stage.

          •  
           
         

    4. Repeat for Each Relevant Sales Stage: Create similar conditions and actions for each of your 5 stages within the main Sales Stage.

    5. Save and Activate the Business Rule.

     

    Limitations of Business Rules for this Scenario:

    • Timing of Message: The error message might not appear exactly when the user tries to move to the next stage. It might appear when they try to save the record.
    • Determining Previous Stage: Reliably setting the Sales Stage back to the previous value using only Business Rules can be complex.
    • User Experience: It might not be the most intuitive user experience.
     
    Cont...(2/3)
     
    Regards,
    Daivat Vartak
  • Suggested answer
    Daivat Vartak (v-9davar) Profile Picture
    7,841 Moderator on at
    Part (2/3)
     

    Approach 2: Using Client-Side Scripting (JavaScript) - Recommended for Better Control and UX

    Client-Side Scripting provides more granular control over the form behavior and allows you to execute logic precisely when the Sales Stage changes.

    1. Add JavaScript Web Resource:

      • Go to Settings > Customizations > Customize the System.
      • Click Web Resources.
      • Click + New.
      • Give it a descriptive Name (e.g., opportunity_salesstage_validation.js).
      • Set the Type to Script (JScript).
      • Click Text Editor and paste your JavaScript code (see example below).
      • Save and Publish the Web Resource. 

    2. Attach the Web Resource to the Opportunity Form:

       

      • Go to Settings > Customizations > Customize the System.
      • Expand Entities and select the Opportunity entity.
      • Expand Forms and open the main Opportunity form(s).
      • In the Form Editor, click Form Properties.
      • In the "Form Libraries" section, click + Add.
      • Lookup and select the Web Resource you created.
      • Click Add.
      • Go to the Events tab.
      • In the "Event Handlers" section, click + Add.
      • Set the Control to the Sales Stage field (the field that represents your overall sales stage).
      • Set the Event to OnChange.
      • Set the Handler to the function name in your JavaScript code that will handle the validation (e.g., validateSalesStage).
      • Check the Enabled box.
      • Optionally, check Pass execution context as first parameter.
      • Click OK.
      • Save and Publish the Form.

      •  

    Example JavaScript Code (opportunity_salesstage_validation.js):

    function validateSalesStage(executionContext) {
        var formContext = executionContext.getFormContext();
        var salesStageControl = formContext.getAttribute("salesstage"); // Replace "salesstage" with the actual schema name of your Sales Stage field
        var currentStageValue = salesStageControl.getValue();
        var previousStageValue = formContext.getAttribute("previousstage").getValue(); // Assuming you have a field to store the previous stage
        // Define the stages and their associated Yes/No question fields
        var stageQuestions = {
            "Qualify": ["new_question1_qualify", "new_question2_qualify", "new_question3_qualify"], // Replace with your actual field schema names
            "Develop": ["new_question1_develop", "new_question2_develop"],
            "Propose": ["new_question1_propose", "new_question2_propose", "new_question3_propose", "new_question4_propose"],
            // Add other stages and their question fields
        };
        // Function to check if all questions in a stage are "Yes"
        function areAllYes(stageName) {
            if (stageQuestions.hasOwnProperty(stageName)) {
                var questions = stageQuestions[stageName];
                for (var i = 0; i < questions.length; i++) {
                    var answer = formContext.getAttribute(questions[i]).getValue();
                    if (answer !== true) { // Assuming "Yes" is stored as true (boolean)
                        return false;
                    }
                }
                return true;
            }
            return true; // If no questions for the stage, allow progression
        }
        // Get the stage display name (for the error message)
        var stageOptions = salesStageControl.getOptions();
        var currentStageDisplayName = "";
        for (var i = 0; i < stageOptions.length; i++) {
            if (stageOptions[i].value === currentStageValue) {
                currentStageDisplayName = stageOptions[i].text;
                break;
            }
        }
        // Logic to prevent moving to the next stage
        if (previousStageValue && currentStageValue !== previousStageValue) {
            var previousStageDisplayName = "";
            for (var i = 0; i < stageOptions.length; i++) {
                if (stageOptions[i].value === previousStageValue) {
                    previousStageDisplayName = stageOptions[i].text;
                    break;
                }
            }
            if (!areAllYes(previousStageDisplayName)) {
                Xrm.AlertDialog({
                    title: "Validation Error",
                    text: "Please ensure all questions in the '" + previousStageDisplayName + "' stage are answered with 'Yes' before moving to '" + currentStageDisplayName + "'."
                }).then(function () {
                    salesStageControl.setValue(previousStageValue); // Revert to the previous stage
                });
            }
        }
        // Store the current stage value for the next OnChange event
        formContext.getAttribute("previousstage").setValue(currentStageValue);
    }
    // Optional: Add an "OnLoad" event to initialize the "previousstage" field
    function initializePreviousStage(executionContext) {
        var formContext = executionContext.getFormContext();
        var currentStageValue = formContext.getAttribute("salesstage").getValue();
        formContext.getAttribute("previousstage").setValue(currentStageValue);
    }

     

    Explanation of the JavaScript Code:

    • validateSalesStage(executionContext): This function will be triggered when the Sales Stage field changes.
    • formContext: Gets the form context to interact with form elements.
    • salesStageControl: Gets the control for the Sales Stage field.
    • currentStageValue: Gets the currently selected Sales Stage value.
    • previousStageValue: Gets the value of a temporary field (you'll need to create this) to store the previous Sales Stage.
    • stageQuestions: An object that maps your Sales Stage display names (or values) to an array of the schema names of the "Yes/No" question fields for that stage. You need to replace the placeholder field names with your actual schema names.
    • areAllYes(stageName): This helper function checks if all the "Yes/No" fields associated with a given stage have a value of true (assuming "Yes" is stored as a boolean true). Adjust the answer !== true condition if your "Yes/No" fields use a different data type or value.
    • Logic:

      • It checks if there was a previous stage and if the current stage is different.
      • It calls areAllYes() for the previous stage.
      • If not all questions in the previous stage were "Yes," it displays an error message using Xrm.AlertDialog and then sets the Sales Stage back to the previousStageValue. 

    • Storing Previous Stage: The code assumes you have a hidden field on the form (schema name: previousstage) to store the value of the Sales Stage before it was changed. You'll need to add this field to your form and potentially set its value on load.
    • initializePreviousStage(executionContext) (Optional): This function can be attached to the form's OnLoad event to initialize the previousstage field with the initial Sales Stage value.
    • Logic:

      • It checks if there was a previous stage and if the current stage is different.
      • It calls areAllYes() for the previous stage.
      • If not all questions in the previous stage were "Yes," it displays an error message using Xrm.AlertDialog and then sets the Sales Stage back to the previousStageValue. 

      •  
    • Storing Previous Stage: The code assumes you have a hidden field on the form (schema name: previousstage) to store the value of the Sales Stage before it was changed. You'll need to add this field to your form and potentially set its value on load.
    • initializePreviousStage(executionContext) (Optional): This function can be attached to the form's OnLoad event to initialize the previousstage field with the initial Sales Stage value.

    •  
     
    Cont.. (3/3)
     
    Regards,
    Daivat Vartak

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

Introducing the 2026 Season 1 community Super Users

Congratulations to our 2026 Super Stars!

Meet the Microsoft Dynamics 365 Contact Center Champions

We are thrilled to have these Champions in our Community!

Congratulations to the March Top 10 Community Leaders

These are the community rock stars!

Leaderboard > Customer experience | Sales, Customer Insights, CRM

#1
ManoVerse Profile Picture

ManoVerse 192 Super User 2026 Season 1

#2
11manish Profile Picture

11manish 129

#3
CU11031447-0 Profile Picture

CU11031447-0 100

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans