Sometimes the field users want to report on does not actually belong where they want to see it.
Classic Dynamics 365 behavior.
In this example, a seller marks individual Opportunity or Quote lines as Strategic Offering = Yes/No. Each line also has a Business Unit, like Consulting, Software, Services, or Training.
Leadership does not want to open every line item to understand what kind of strategic work is on the deal. They want a clean summary directly on the Opportunity header.
So we use Power Automate to roll up the line-level data into an Opportunity-level multi-select field.
Because naturally, the truth lives on the line, but the dashboard wants it on the header.
1. What this is for
This solution is for automatically updating an Opportunity header summary field based on related Opportunity Lines or Quote Lines.
The pattern is simple:
If any line for a Business Unit has Strategic Offering = Yes,
select the matching Strategic Offering value on the Opportunity header.For example, imagine an Opportunity has these lines:
Line 1
- Business Unit: Consulting
- Strategic Offering: Yes
Line 2
- Business Unit: Software
- Strategic Offering: No
Line 3
- Business Unit: Services
- Strategic Offering: Yes
The Opportunity header should show:
Strategic - Consulting
Strategic - ServicesIt should not show Software because the Software line is not marked as Strategic Offering.
The seller does not manually maintain the Opportunity header field. Power Automate does.
The Opportunity header is just the summary. The line records are the source of truth.
2. When to use it, and when not to
Use this pattern when the real decision happens at the line level, but users need to report from the Opportunity level.
This works well when:
- One Opportunity can include multiple Business Units.
- Each product or quote line can have a different flag value.
- Leadership needs a filterable field on the Opportunity.
- The header field needs to stay in sync automatically.
- Users should not manually maintain the parent summary field.
Do not use this pattern when:
- The Opportunity can only ever have one Business Unit.
- The header value is truly manually owned by users.
- The line records do not contain enough information to calculate the summary.
- You only need the information in one report and not in Dynamics views or forms.
The big rule: every source line must have the fields needed to calculate the rollup.
For this example, each relevant line needs:
Strategic Offering
Business UnitIf the line says Strategic Offering = Yes but does not have Business Unit, the flow knows something is strategic, but it does not know whether to select:
Strategic - Consultingor:
Strategic - SoftwareAsk me how I know.
3. Pre-flight checklist
Before you build the flow, confirm the data model.
You need the following fields.
Opportunity Line
- Strategic Offering
- Type: Yes/No
- Default: No
- Purpose: This is the line-level flag the seller or configurator sets.
Opportunity Line Business Unit
- Type: Choice or lookup
- Purpose: Tells the flow which Business Unit the line belongs to.
Quote Line
- Strategic Offering
- Type: Yes/No
- Default: No
- Purpose: This is the same line-level flag, but on the quote line.
Quote Line Business Unit
- Type: Choice or lookup
- Purpose: Required for quote-side rollup logic.
Opportunity Strategic Offering Summary
- Type: Multi-select Choice
- Purpose: This is the header-level summary field populated by Power Automate.
Opportunity Primary Quote
- Type: Lookup
- Purpose: Determines whether the flow should use Opportunity Lines or Quote Lines.
The source-of-truth rule is important:
Before a Primary Quote exists:
Opportunity Lines drive the Opportunity header.
After a Primary Quote exists:
Quote Lines from the Primary Quote drive the Opportunity header.This means the Quote Line needs Business Unit too.
Consultant law #12: if the rollup is “by Business Unit,” the source data better include Business Unit.
4. Step-by-step build
The cleanest build is a recalculation pattern.
That means the flow does not simply look at the one line that changed and add or remove one value.
Instead, it does this:
Something changed.
Go look at all current source-of-truth lines.
Find every Business Unit with Strategic Offering = Yes.
Rebuild the Opportunity header from scratch.This is safer because multiple lines can belong to the same Business Unit.
For example, say an Opportunity has these lines:
Line 1
- Business Unit: Consulting
- Strategic Offering: Yes
Line 2
- Business Unit: Consulting
- Strategic Offering: Yes
If Line 1 changes to No, the Opportunity should still show:
Strategic - Consultingbecause Line 2 is still Yes.
Do not be a hero with one-line add/remove logic. Recalculate from the current data.
Step 1: Create the Opportunity Line flow
Create a Dataverse automated cloud flow.
Use this trigger:
When a row is added or modifiedUse the Opportunity Line table.
Trigger when these columns change:
Strategic Offering
Business UnitThis flow handles the pre-quote scenario.
The logic is:
When an Opportunity Line is created or Strategic Offering/Business Unit changes,
get the related Opportunity.
If the Opportunity has a Primary Quote:
stop.
If the Opportunity does not have a Primary Quote:
recalculate the Opportunity header from Opportunity Lines.Once a Primary Quote exists, Opportunity Lines are no longer the source of truth.
Step 2: Get the related Opportunity
Use the Opportunity lookup from the Opportunity Line to retrieve the parent Opportunity.
This lets the flow check:
Does this Opportunity have a Primary Quote?If the lookup value is not available directly from the trigger, add a step to get the Opportunity Line first, then use the Opportunity lookup from that retrieved row.
Tiny Power Automate reality check: sometimes the field you need exists, but not in the trigger output where you expected it. Very humbling. Very on brand.
Step 3: Check for Primary Quote
Add a condition:
Primary Quote exists?If Yes, terminate the flow.
Reason:
Quote Lines should control the header once a Primary Quote exists.If No, continue.
This is the control point that prevents Opportunity Lines and Quote Lines from fighting over the same header field.
No automation cage match required.
Step 4: List Opportunity Lines where Strategic Offering = Yes
List all Opportunity Lines related to the Opportunity where:
Strategic Offering = Yes
Business Unit is not blankYou can use OData or FetchXML.
Example FetchXML:
<fetch mapping="logical" no-lock="true">
<entity name="opportunityproduct">
<attribute name="new_businessunitcode" />
<filter type="and">
<condition attribute="opportunityid" operator="eq" value="[Opportunity Id]" />
<condition attribute="new_isstrategicoffering" operator="eq" value="1" />
<condition attribute="new_businessunitcode" operator="not-null" />
</filter>
<order attribute="new_businessunitcode" />
</entity>
</fetch>Replace the field names with your actual logical names.
The point of this query is not to get every line. It is only getting the lines that matter for the rollup:
Related to this Opportunity
Strategic Offering = Yes
Business Unit has dataStep 5: Map Business Units to header values
Now map each line Business Unit to the matching Opportunity header option.
Example mappings:
Consulting
- Line value: Consulting
- Header value: Strategic - Consulting
Software
- Line value: Software
- Header value: Strategic - Software
Services
- Line value: Services
- Header value: Strategic - Services
Training
- Line value: Training
- Header value: Strategic - Training
In Power Automate, this can be a Switch.
Example logic:
If Business Unit = Consulting
append Strategic - Consulting option value
If Business Unit = Software
append Strategic - Software option value
If Business Unit = Services
append Strategic - Services option valueImportant: if the Opportunity header field is a multi-select Choice, the flow usually needs to write the numeric option values, not the display labels.
So the final value should look like:
100000000,100000001not:
Strategic - Consulting; Strategic - SoftwareThe UI displays the labels. The flow writes the values.
Step 6: Remove duplicates
If there are three Consulting lines marked Strategic Offering = Yes, the Opportunity header should still only show:
Strategic - Consultingone time.
Use a distinct or union pattern to remove duplicate values before updating the Opportunity.
Future You will thank you.
Step 7: Update the Opportunity header
If at least one strategic Business Unit was found, update the Opportunity multi-select field.
Example:
Strategic Offering Summary = 100000000,100000001If no lines are marked Strategic Offering = Yes, clear the header field.
This matters because users can change a line from Yes back to No. The header needs to reflect the current line data, not whatever was true three flow runs ago.
5. Quote Line flow
The Quote Line flow follows the same pattern, but it uses Quote Lines from the Primary Quote.
The logic is:
When a Quote Line is created or changed,
get the related Quote.
Get the related Opportunity.
Check the Opportunity’s Primary Quote.
If this Quote is not the Primary Quote:
stop.
If this Quote is the Primary Quote:
list all Quote Lines from the Primary Quote where Strategic Offering = Yes.
Map Business Units to Opportunity header values.
Update the Opportunity header.Example FetchXML:
<fetch mapping="logical" distinct="true" no-lock="true">
<entity name="quotedetail">
<attribute name="new_businessunitcode" />
<filter type="and">
<condition attribute="quoteid" operator="eq" value="[Primary Quote Id]" />
<condition attribute="new_isstrategicoffering" operator="eq" value="1" />
<condition attribute="new_businessunitcode" operator="not-null" />
</filter>
<order attribute="new_businessunitcode" />
</entity>
</fetch>Make sure the FetchXML goes in the Fetch Xml Query field, not the Filter rows field.
If you paste <fetch> into Filter rows, Power Automate will reject it immediately because Filter rows expects OData syntax.
A very rude but technically correct little error.
6. Common gotchas
Gotcha 1: Quote Line does not have Business Unit
This is the biggest data model issue.
If the flow needs to summarize by Business Unit, then Quote Line needs Business Unit.
Bad setup:
Quote Line
- Strategic Offering exists
- Business Unit does not exist
Good setup:
Quote Line
- Strategic Offering exists
- Business Unit exists
Without Business Unit on Quote Line, the flow cannot tell which header value to select.
It can only tell:
This quote line is strategic.But it cannot tell:
Strategic for which Business Unit?That is not a Power Automate problem. That is a missing source data problem.
Gotcha 2: Opportunity Lines and Quote Lines both trying to update the header
Do not let both line sources fight over the same Opportunity field.
Use this rule:
No Primary Quote:
Opportunity Lines control the header.
Primary Quote exists:
Primary Quote Lines control the header.The Opportunity Line flow should terminate once Primary Quote exists.
The Quote Line flow should only update the Opportunity if the Quote is the Primary Quote.
Gotcha 3: Primary Quote changes
If users can change the Primary Quote, you may need a third flow.
Trigger when:
Opportunity Primary Quote changesThen recalculate the Opportunity header based on the new Primary Quote’s lines.
Example:
Quote A
Strategic - ConsultingQuote B
Strategic - SoftwareWhen Primary Quote changes from Quote A to Quote B, the Opportunity header should change too.
Gotcha 4: Multi-select Choice values are not labels
This burns people.
The form shows:
Strategic - ConsultingBut the flow may need to write:
100000000For multiple selections:
100000000,100000001If you build a pretty string like:
Strategic - Consulting; Strategic - Softwarethat only works if the target field is text.
For a multi-select Choice, map to option values.
Gotcha 5: Blank Row ID on Get Opportunity
When using Get a row by ID, the Row ID must be the record GUID.
For the parent Opportunity, use the Opportunity lookup value from the line, not the Opportunity name.
If Power Automate says the Row ID is null or empty, the flow is not receiving the GUID you think it is.
Go check the trigger output. It is annoying. It is also usually the fastest fix.
Gotcha 6: Only updating from the changed line
This one is sneaky.
A line changes from Yes to No, so it feels natural to remove that Business Unit from the header.
But what if another line for the same Business Unit is still Yes?
Example:
Line 1
- Business Unit: Consulting
- Strategic Offering: No
Line 2
- Business Unit: Consulting
- Strategic Offering: Yes
The header should still show:
Strategic - ConsultingThis is why the flow should recalculate from all current source lines, not just react to the changed line.
Ask me how I know.
7. Validation checklist
Test small first.
Start with one Opportunity and one line. Then layer on complexity.
Opportunity Line scenarios
Use these when no Primary Quote exists.
Test 1: One Yes line
Setup:
Consulting = YesExpected result:
Header shows Strategic - ConsultingTest 2: One Yes and one No line
Setup:
Consulting = Yes
Software = NoExpected result:
Header shows Strategic - Consulting onlyTest 3: Flip No to Yes
Setup:
Change Software from No to YesExpected result:
Header adds Strategic - SoftwareTest 4: Flip Yes back to No
Setup:
Change Software back to NoExpected result:
Header removes Strategic - SoftwareTest 5: Duplicate same-BU lines
Setup:
Two Consulting lines = YesExpected result:
Header shows Strategic - Consulting only onceTest 6: One same-BU line remains Yes
Setup:
Two Consulting lines = Yes
Change one Consulting line to NoExpected result:
Header still shows Strategic - ConsultingTest 7: All lines No
Setup:
All Strategic Offering values = NoExpected result:
Header clearsQuote Line scenarios
Use these once a Primary Quote exists.
Test 1: Primary Quote line Yes
Setup:
Primary Quote has Consulting = YesExpected result:
Header shows Strategic - ConsultingTest 2: Quote line No to Yes
Setup:
Change Software from No to YesExpected result:
Header adds Strategic - SoftwareTest 3: Quote line Yes to No
Setup:
Change Software back to NoExpected result:
Header removes Strategic - SoftwareTest 4: Opportunity Lines ignored
Setup:
Opportunity Line Services = Yes
Primary Quote Consulting = YesExpected result:
Header shows Strategic - Consulting onlyTest 5: Non-primary Quote ignored
Setup:
Non-primary Quote Software = Yes
Primary Quote Consulting = YesExpected result:
Header does not include Strategic - SoftwareTest 6: Primary Quote changes
Setup:
Change Primary Quote from Quote A to Quote BExpected result:
Header recalculates from Quote BTest 7: No Yes quote lines
Setup:
Primary Quote has all lines = NoExpected result:
Header clearsThe validation rule is simple:
The Opportunity header should always match the current source-of-truth lines.Not the line that triggered the flow.
Not the old quote.
Not the field value from before lunch.
The current source-of-truth lines.
8. Real scenario
A company sells across multiple Business Units.
A seller is building an Opportunity with two Opportunity Lines.
Opportunity Line 1
- Business Unit: Consulting
- Strategic Offering: Yes
Opportunity Line 2
- Business Unit: Software
- Strategic Offering: No
The Opportunity header shows:
Strategic - ConsultingLater, the seller creates a Primary Quote.
Now the Primary Quote has two Quote Lines.
Quote Line 1
- Business Unit: Consulting
- Strategic Offering: No
Quote Line 2
- Business Unit: Software
- Strategic Offering: Yes
The Opportunity header should now show:
Strategic - SoftwareThat is the point of the automation.
The Opportunity header is not the source of truth. It is the summary.
The line records are the source of truth.
Final takeaway
This is not just a “when this field changes, update that field” flow.
It is a line-to-header rollup pattern.
The flow needs to:
Find the correct source lines.
Filter to Strategic Offering = Yes.
Group by Business Unit.
Map those Business Units to header choices.
Update the Opportunity header.
Clear anything that no longer applies.Build it this way and the header stays clean, reporting stays useful, and nobody has to manually maintain a summary field that was absolutely going to be wrong by Friday.