Tuesday, August 11, 2026

Dynamics 365 Sales Product Relationships: Substitute vs Cross-Sell Explained

Product relationships in Dynamics 365 Sales help sellers discover alternatives and complementary products while working on opportunities, quotes, orders and invoices. The most common confusion is between Substitute and Cross-sell—and whether selecting a substitute automatically replaces the original product.

Quick answer: A substitute is an alternative to the original product, while a cross-sell is an additional related product. In the standard Dynamics 365 Sales experience, both appear as suggestions. Selecting a substitute adds it to the transaction; it does not automatically remove or replace the original line.

What are product relationships?

Dynamics 365 Sales supports four relationship types: Accessory, Cross-sell, Substitute and Up-sell. Microsoft describes these relationships as suggestions shown to sellers during opportunity or order management. A relationship can be created for a product or product bundle, but not for a product family. See Microsoft Learn: Define related products.

Substitute vs cross-sell vs up-sell vs accessory

Relationship Functional meaning Example Expected seller action
Substitute An alternative when the original product is unavailable or unsuitable. Filter Model B instead of discontinued Filter Model A. Add the substitute and remove the original if replacement is intended.
Cross-sell A related product sold in addition to the selected product. Add a maintenance kit with a machine. Keep the original and add the related product.
Up-sell A higher-value alternative to the selected product. Offer a premium machine model instead of the standard model. Discuss the higher-value option with the customer.
Accessory A supporting item used with the main product. Add a mounting bracket for the selected equipment. Add the accessory when required.

It also supports relationship direction. Cross-sell and Substitute can be unidirectional or bidirectional, while Accessory and Up-sell are unidirectional. This matters when deciding whether Product A should suggest Product B only, or whether each product should suggest the other.

How to configure product relationships

  1. Open the Sales Hub app.
  2. Select Change area and open App Settings.
  3. Under Product Catalog, select Families and products.
  4. Open the product for which suggestions should be configured.
  5. Open the Related tab and select Product Relationships.
  6. Select New Product Relationship.
  7. Select the related product, relationship type and direction.
  8. Save and close the relationship.

The product being configured can be in Draft, Active or Under Revision state.

How sellers use Suggestions

On an opportunity

  1. Open the opportunity and go to the product grid.
  2. Select the existing product.
  3. Select Suggestions.
  4. Choose one or more related products and select OK.

On a quote, order or invoice

  1. Open the transaction and locate the Products section.
  2. Select a product and choose More commands > Suggestions.
  3. Select the related products to add and select OK.

The process is the same for quotes, orders and invoices. See Add products to quotes, orders or invoices.

Why does a substitute not replace the original product?

This is standard behaviour. Microsoft’s documented action is to select related products from the Suggestions pane and add them to the transaction. The relationship classifies the recommendation; it does not execute replacement logic.

Therefore, if the seller intends to replace Product A with Product B, the functional process is:

  1. Add Product B from Suggestions.
  2. Confirm its unit, quantity, price and other line details.
  3. Remove Product A manually.

If the business requires one-click replacement, that would be a custom solution—for example, a command that creates the substitute line, copies approved values and removes the original only after validation. Ensure that the design also account for quantities, pricing, discounts, bundles, tax, inventory, integrations and approvals.

Practical functional example

Assume a spare-parts business sells Pump Model A.

  • Pump Model B is configured as a bidirectional substitute because either model can serve as the alternative.
  • Maintenance Kit is configured as a cross-sell because it is sold in addition to the pump.
  • Premium Pump Model C is configured as a unidirectional up-sell from Model A.
  • Mounting Bracket is configured as a unidirectional accessory.

When Model A is selected, the seller can review all four options in Suggestions and decide what matches the customer’s need. Dynamics 365 assists the decision but does not make it on the seller’s behalf.

Frequently asked questions

Does Substitute automatically replace a product?

No. It appears as a suggestion and is added when selected. The original line must be removed separately in the standard experience.

Can relationships be defined on product families?

No. Microsoft states that related products can be added to a product or product bundle, but not to product families.

Where are product relationships stored in Dataverse?

They are represented by the Product Relationship (ProductSubstitute) table, which stores the relationship type between two products. See Product catalog tables.

D365 Sales Product Relationships vs F&O

If your organization uses both Dynamics 365 Sales and Dynamics 365 Supply Chain Management, an obvious question arises: If substitute, cross-sell or alternative products are already maintained in F&O, can Dynamics 365 Sales automatically use those relationships?

The short answer is: Not out of the box.

Dynamics 365 F&O has its own concepts for alternative products, cross-selling and up-selling. However, Microsoft does not currently provide a standard Dual-write map that automatically converts F&O product relationships into Dynamics 365 Sales Product Relationships..

Product relationships in Dynamics 365 Sales: Substitute, Cross-sell, Up-sell and Accessory

Have you implemented product relationships in your Dynamics 365 Sales solution? Share your experience or questions in the comments.

 

Wednesday, July 15, 2026

How to sort a view by multiple columns (user personal view)

A system view can be sorted by multiple columns and published. However the user is stuck with this, unless you know this trick. Read on!

Consider you are on the Accounts list and you want to sort the list based on Address 1: City first and then by the Account Name field.
  • Click on Address 1: City header column and sort based on your preference (A-Z or Z-A).
  • Now hold the Shift key on the keyboard and then click on the Account Name header column and sort based on your preference.
  • If you want to add another column to this list, continue holding the Shift key and click on the 3rd column header and sort it.
Hope this helps!

How to enable In-App Notification in Dynamics 365 CE

In-app notifications allow Dynamics 365 users to receive contextual messages directly within a model-driven app such as Dynamics 365 Sales, Customer Service, or Field Service.

In-App notifications in Dynamics 365
Notifications can appear as:

  • Toast notifications on the right side of the application.

  • Notification centre messages accessed through the bell icon.

Notifications remain in the notification centre until the user dismisses them or they expire. The default expiry period is 14 days, although this can be changed when the notification is created.

How to Enable In-App Notifications

The feature must be enabled separately for each model-driven app.

  1. Go to make.powerapps.com.

  2. Open the solution containing the model-driven app.

  3. Select the app and choose Edit.

  4. Open Settings.

  5. Select Features.

  6. Enable In-app notifications.

  7. Save and publish the app.

The notification setting is stored at the individual model-driven app level.

How Notifications Are Created

Notifications can be generated using:

  • Power Automate.

  • JavaScript or the Dataverse Web API.

  • A plug-in or custom integration.

  • The Dataverse SendAppNotification action.

  • Direct creation of records in the Notification table.

Notifications created through SendAppNotification are stored in the Dataverse Notification table, with the logical name appnotification.

Required Security Privileges

There are 4 tables to keep in mind so notifications work smoothly.

  • Notification (appnotification): This is where notifications are stored.

  • Model-Driven App User Setting (appusersetting): The table stores app-specific settings and preferences for each user.
  • Setting Definition (settingdefinition): This table contains the definition of notification-related settings that the model-driven app reads. The user needs Read and Append To privileges because the Model-driven App User Setting record references the relevant Setting Definition record.
  • Send In-App Notification (prvSendAppNotification): To send notifications to others.

Assign the following Privileges


Notification

  • Create, Read and Delete
  • The close or cross button deletes the individual appnotification record. Without Delete access, users may see the close button but be unable to dismiss individual notifications.
  • You may give User, BU or ORG level depending on the access you want to assign.

Model-driven App User Setting

  • Create, Read, Write and Append.

  • These are ORG level access.


Setting Definition

  • Read and Append To

  • These are ORG level access.


Send In-App Notification

  • ORG level access under Miscellaneous privileges tab.

These privileges allow the notification bell, notification centre and user notification settings to work correctly.

To sse “Dismiss All”, the user requires:

  • Model-driven App User Setting

  • Setting Definition

Dismiss All does not immediately delete every notification record. It updates the user setting so that older notifications are no longer retrieved.

Hope this helps!

Thursday, February 19, 2026

Field Service pricing vs ERP pricing: How to turn off the Clash

In Dynamics 365 Field Service, pricing and cost can be calculated by Field Service itself (using features like price lists, products, services, agreement pricing, etc. within Field Service). However if you'd like, you can always disable it.

This happened in one of our environments that a solution dependency was created. When I looked, there was a solution installed with the name: msdyn_FieldServiceDisablePricingComponents

I tried looking at sources from where I can download and install this solution. However, this simple setting in Field Service solves it.

When people say “install the Field Service Disable Pricing Components solution”, they’re usually referring to a built-in capability controlled by Field Service Settings, not a separate managed solution you import into Dataverse.

The practical outcome:
  • Field Service stops calculating price and/or cost
  • Another system becomes the source of truth (e.g., Project Operations, Finance & Operations, or an ERP)

Prerequisites


Before you change settings, make sure you have:
  • Administrator rights to the Power Platform environment (System Administrator / Field Service Admin equivalent).
  • Dynamics 365 Field Service installed in the environment.
  • Access to the Field Service app and the Settings area.

Step-by-step: Disable pricing components


Step 1: Sign in
  • Open the browser.
  • Sign in to your Dynamics 365 Field Service instance.

Step 2: Open Field Service Settings
  • Go to the Field Service app.
  • In the sitemap (left navigation), switch to Settings (typically near the bottom).
  • Under General, select Field Service Settings.

Step 3: Change Work Order / Booking pricing options
  • Open the Work Order / Booking tab.
  • Update these settings:
    • Calculate Price = No
    • Calculate Cost = No
  • Select Save & Close.
That’s it—Field Service will stop calculating those values internally.

Tuesday, January 20, 2026

Find what’s hiding a field in Dynamics 365: Step-by-Step with PowerApps Live Monitor

A Little Background


A field (msdyn_customergroupid / Customer Group) exists in Dataverse for the Account table, but it is not showing on the Account form in a Dynamics 365 model-driven app. Our requirement was to show this on the form and I know that we had made it visible on the Account form.

However, after a deployment we noticed that it wasn't the case. Now it could be because on various reasons:
  • The field is hidden on the form level.
  • Column security profile was implemented.
  • There is a business rule, due to which it was hidden.
  • There is a script, due to which the field was hidden.


Our Approach


The easiest way to rule out the problem is to start with the simplest reason and work your way up.

Step 1 - To check if field was hidden on the form


We checked if the field was hidden on the form? It wasn't. That was easy.

Now, to check Business Rules and Script was a hard road for us because we had 20+ rules and many functions written on form load.

Step 2 - Run quick form-runtime checks (console logic)


We used simple client checks to classify the problem.
This is the fastest way to know whether you’re dealing with design-time vs runtime.
Click F12 > Console and run these commands:

Xrm.Page.getControl("msdyn_customergroupid")
If the call returns null, the field is not on the form. For us, tt returned the Control means something must be hiding it.

Xrm.Page.getControl("msdyn_customergroupid").getVisible()
If it returns a control, something must be hiding it. We ran the below command to confirm:
It returned FALSE.

Step 3 - Use PowerApps Live monitor to capture the visibility change


When I opened the PowerApps Live Monitor and performed the steps within the App, I captured a Live monitor event:
  • dataSource: Forms.FormChecker.ControlStateChange
  • controlName: msdyn_customergroupid
  • visible before: true
  • visible after: false

And the call stack included:
  • M.setVisible(...)
  • pbl_c3f86e4e73b7ed1183ff6045bd8c93df(...)
  • Mscrm.BusinessRulesScript.Initialize(...)


Key Finding:


The field was initially visible, then explicitly hidden at runtime by a business rule script.
This pattern indicates the visibility change came from a Business Rule (Power Apps compiles business rules into runtime scripts, commonly visible as pbl_<guid> style functions).

So we could say with confidence:

✅ A Business Rule running on the Account form hid Customer Group by calling setVisible(false).
✅ Not JavaScript web resources. Not security. Not form XML missing. Not personalization.
✅ Focused our attention to look at all the business rules and we could find the culprit.

Hope this helps!