<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>D365 on LinkeD365 Blog</title><link>https://linked365.blog/tags/d365/</link><description>Recent content in D365 on LinkeD365 Blog</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Thu, 09 Jul 2020 00:00:00 +0000</lastBuildDate><atom:link href="https://linked365.blog/tags/d365/index.xml" rel="self" type="application/rss+xml"/><item><title>Accelerators: Nonprofit - part 1 - Fundraising</title><link>https://linked365.blog/2020/07/09/accelerators-nonprofit-part-1-fundraising/</link><pubDate>Thu, 09 Jul 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/07/09/accelerators-nonprofit-part-1-fundraising/</guid><description>&lt;img src="https://linked365.blog/images/2020/07-image-68.png" alt="Featured image of post Accelerators: Nonprofit - part 1 - Fundraising" />&lt;p>Microsoft Dynamics is a great set of tools, which cover a lot of the requirements for most situations. These Sales and Service tools tend to focus on a generic requirement rather than those that can be specific to an industry. To get a more specific version of the application, one that is more suited for an industry vertical, Microsoft provides several Accelerators.&lt;/p>
&lt;p>The accelerators are a set of content to transpose your environment to be a starting point, tweaking the standard offerings towards an industry standard. These solutions have been designed with industry experts to enable a quick, easy starting point for many verticals, with functionality specific to them.&lt;/p>
&lt;p>As I know very little, apart from that they are there, I wanted to learn about the functionality in each and share my experience with you, starting with the Nonprofit accelerator.&lt;/p>
&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>Microsoft provides several industry-specific groups of functionality, called Accelerators. This post highlights the functionality available to you within the nonprofit accelerator, starting with how to get it for free and the Fundraising application.&lt;/p>
&lt;h2 id="installation">Installation&lt;/h2>
&lt;p>The Dynamics 365 Nonprofit Accelerator is available on Appsource &lt;a class="link" href="https://appsource.microsoft.com/en-gb/product/dynamics-365/msnfp.msftnonprofitcommondatamodel?src=office&amp;amp;tab=Overview" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-68.png"
loading="lazy"
>&lt;/p>
&lt;p>The packages are also available on GitHub, the AppSource version allows for an installation of all the components easily. This accelerator is also available for a Test Drive. this allows you to log in a pre-configured environment to take a look around the available functionality, without introducing it to any of your own systems.&lt;/p>
&lt;p>As it takes longer than the 24 hours duration of the test drive for me to get to write a blog post, I am going to install the application on a trial environment, so select Get It Now.&lt;/p>
&lt;p>Fill out a simple form and accept the terms.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-69.png"
loading="lazy"
>&lt;/p>
&lt;p>Hit continue and select an appropriate environment.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-70.png?fit=1024%2C497&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Accept the required permissions and you are presented by the following screen.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-71.png"
loading="lazy"
>&lt;/p>
&lt;p>I selected those that were available to me, no PSA in my standard, blank environment. Now we get an install initiated screen and we wait&amp;hellip;.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-72.png"
loading="lazy"
>&lt;/p>
&lt;p>When you now launch D365, you get several new applications, firstly Fundraising.&lt;/p>
&lt;h2 id="fundraising">Fundraising&lt;/h2>
&lt;p>The fundraising app is designed around raising money for your charity or nonprofit. It revolves around donation commitments. These are the high-level commitments agreed. Each commitment may have one or more scheduled payments, leading to transactions. Each commitment is associated with an Account or Contact.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-73.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="commitment-screen">Commitment Screen&lt;/h3>
&lt;p>Drilling down into a Commitment, you get a screen with 3 columns. In the first column, is the name and description of the commitment. Anonymity, a yes/no picklist allows the pledge to remain anonymous, great for the high rollers I guess. Next comes the date when the commitment was made. The Commitment type is a choice of Sustainer, Installment or In-kind. Sustainer pledges are those where you commit to a regular payment, indefinitely. A monthly donation to a charity would be considered a Sustainer Pledge. Instalment is a one-off commitment, over one or more payments, but there is a set timeframe for the obligation. Finally, In-kind pledge indicates a product or service committed by the donor, which is not cash. The commitment can also be marked as bookable. This is for use in the Volunteer management section of the app.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-82.png"
loading="lazy"
>&lt;/p>
&lt;p>The second section denotes whether this commitment came from a planned giving, where a donor includes the charity in their will. You also indicate which account and/or contact the pledge was made by and it may also be on behalf of another account. Next are a set of fields to indicate the total amount, payment dates and amounts as well as the currency.&lt;/p>
&lt;p>The final column shows where the pledge came from, the campaign, and where it is going to. Designations are projects with specific funding that may arise to pledges being designated directly to them rather than the charity as a whole.&lt;/p>
&lt;h3 id="iati">IATI&lt;/h3>
&lt;p>The next tab allows the user to log details about the donation to ensure the transparency of donations. &lt;a class="link" href="https://en.wikipedia.org/wiki/International_Aid_Transparency_Initiative" target="_blank" rel="noopener"
>International Aid Transparency Initiative&lt;/a> (IATI) is a campaign to ensure transparency in recording and spending donations to charities. This standard indicates the information that a non-profit should record when logging donations and spending them.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-83.png"
loading="lazy"
>&lt;/p>
&lt;p>The final tab highlights the created and modified info for the commitment.&lt;/p>
&lt;h3 id="payment-schedule">Payment Schedule&lt;/h3>
&lt;p>Associated with Commitments are payment schedules. These indicate the series of payments that will form the total for the commitment. This screen highlights all the information of an expected payment, how often, when it starts and how many payments.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-84.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="transactions">Transactions&lt;/h3>
&lt;p>Transactions are actual payments received. These can be linked to pledges, where the donation was planned or directly to an account for when they are not. Each transaction has an amount, currency, booked and received dates and a type of entry (either data entry or via an integration). The transaction can also be anonymous if required. As everyone makes mistakes this transaction can be an adjustment to previous transactions.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-85.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="planned-giving">Planned Giving&lt;/h3>
&lt;p>Planned giving is a pledge to bequeath an amount, either money or assets, in the will of a donor on their death. This part of fundraising is significant for charities which provide support for individuals in times of hardship and makes up a large proportion of giving across the charitable sector. Planned giving could also be Living trusts.&lt;/p>
&lt;p>The main screen allows data entry of the details for the planned giving, with links to Household and campaign, as well as fields for Amount, stage and the type of bequest being available. Further, feels to account for capital gains tax as well as deductions are available.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-4.png"
loading="lazy"
>&lt;/p>
&lt;p>The Details tab highlights more detail about the giving and has fields to denote market values for assets that have been bequeathed, rather than cash.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-5.png"
loading="lazy"
>&lt;/p>
&lt;p>The Trust tab defines more fields to document a Living Trust, such as how much of the trust is pledged and distribution dates.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-6.png"
loading="lazy"
>&lt;/p>
&lt;p>The Giving tab highlights information about the payments that will be part of the Planned Giving.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-7.png"
loading="lazy"
>&lt;/p>
&lt;p>A method of donating via Planned Giving is to gift a Life Insurance policy, where it has been nearly paid up and hence it is of value to the charity. The Insurance tab highlights some fields to detail this contribution.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-9.png"
loading="lazy"
>&lt;/p>
&lt;p>Finally, details about when Planned giving was triggered. A bit morbid, but essential with the bequeaths.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-11.png"
loading="lazy"
>&lt;/p>
&lt;p>The Planned Giving can be associated with commitments which detail payments and converts the planned to the actual. It can also be linked to a Payment Asset where the payment is not a cash payment rather whole or part of an asset with value.&lt;/p>
&lt;h3 id="membership">Membership&lt;/h3>
&lt;p>A lot of fundraising is conducted by offering the pledger services or products in exchange for their donation. This can be in the form of a membership to the organisation, with each membership having a category and associated with products. For example, offering access to a garden or listed building for the year would be a membership donation.&lt;/p>
&lt;p>The Membership screen is quite simple, indicated the start and end date of the membership as well as the status and a link to the contact or account that has the membership.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-12.png"
loading="lazy"
>&lt;/p>
&lt;p>Each membership can be associated with one or membership Categories. These are grouping of products to define the offer to the customer.&lt;/p>
&lt;h3 id="designations">Designations&lt;/h3>
&lt;p>A commitment can be allocated to a certain project within the charity, these are called Designations. Each designation can be part of a larger project, there is a parent-child connection between designations.&lt;/p>
&lt;p>The designation screen defines the details on the project including the Geneal Ledger information for accounting purposes.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-14.png"
loading="lazy"
>&lt;/p>
&lt;p>Sometimes, a donor may state that rather going to one designation, the donation is split between projects and as such, the designation can be associate with one or more commitments via the designation plan when this occurs.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-15.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="campaigns">Campaigns&lt;/h2>
&lt;p>A large proportion of a fundraisers role is targeted marketing of the charity across numerous mediums to improve the donation rate. Campaigns for Not for Profit are based around standard Marketing Campaigns with some tweaks for the Nonprofit sector.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/07-image-17.png"
loading="lazy"
>&lt;/p></description></item><item><title>Adding to Calendars using Power Automate</title><link>https://linked365.blog/2020/06/24/adding-to-calendars-using-power-automate/</link><pubDate>Wed, 24 Jun 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/06/24/adding-to-calendars-using-power-automate/</guid><description>&lt;img src="https://linked365.blog/images/2020/06-image-81.png" alt="Featured image of post Adding to Calendars using Power Automate" />&lt;p>D365 Customer Service and Field Service both use Calendars associated with resources to schedule working time. This is accessible via the resource calendar and typically relies on the individual working a set time frame each week. Fiona works Monday to Friday, 8-5.&lt;/p>
&lt;p>When you are working with volunteers, this doesn&amp;rsquo;t work. Each volunteer will have an inconsistent schedule, with most of the time not being available. Rita has just volunteered for a couple of hours next Thursday.&lt;/p>
&lt;p>A recent client project to improve their scheduling of resources and was definitely in the second scenario. It wanted volunteers to sign up for times using simple time entry on a portal and transfer these times to the scheduling board.&lt;/p>
&lt;p>As Calendar is available as an entity, my initial thoughts that these would be a simple integration using Flow, unfortunately, not. This post details my findings and how I achieved creating sporadic &amp;ldquo;On Time&amp;rdquo; in Field Service or Customer Service.&lt;/p>
&lt;p>All credit for this discovery goes &lt;a class="link" href="https://www.linkedin.com/in/david-bostock-b097a730/" target="_blank" rel="noopener"
>Dave Bostock&lt;/a>, my colleague at Avanade, but judicious use of F12. Thanks to &lt;a class="link" href="https://twitter.com/JasonAAlmeida" target="_blank" rel="noopener"
>Jason Almeida&lt;/a> and &lt;a class="link" href="https://www.linkedin.com/in/robdawson/" target="_blank" rel="noopener"
>Rob Dawson&lt;/a> for their support and experience to nudge me to the solution.&lt;/p>
&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>How to create calendar entries in D365 for resources using an unbound action in Power Automate.&lt;/p>
&lt;h2 id="manual-configuration-of-calendar-entities">Manual configuration of Calendar Entities&lt;/h2>
&lt;p>Every bookable resource has a calendar associated with them. This Calendar has several rules which establish the working pattern for the resource. A rule, normally, would say &amp;ldquo;This resource works Monday to Friday, 9 to 5&amp;rdquo; or something similar.&lt;/p>
&lt;p>From the Resource, you can get to a calendar view by selecting Show Work Hours, highlighted below. It may also be available as a tab on the main form, depending on whether you are using Field Service or not. For me, I am still using the Customer Service version.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/06-image-74.png?fit=1024%2C602&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Top left, you can alter the default rule for the user by adding a new weekly schedule, add an update to a single day or add time off for the resource.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/06-image-75.png"
loading="lazy"
>&lt;/p>
&lt;p>Selecting New Weekly Schedule and populating the next screen is the standard way resource get a weekly schedule.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/06-image-76.png"
loading="lazy"
>&lt;/p>
&lt;p>For volunteer management, resource tends to have a blank calendar. This is done by deleting all the calendars associated with the resource. From there, a volunteer would sign up for periods or shifts. This, on the face of it, just sounds like data entry, easily achieved via Powe Automate.&lt;/p>
&lt;h2 id="creating-rules-via-power-automate">Creating Rules via Power Automate&lt;/h2>
&lt;p>If you use either of the Common Data Service connectors to create a calendar rule, you will be presented with this error.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/06-image-77.png"
loading="lazy"
>&lt;/p>
&lt;p>This is because calendarrule is not a real entity, rather it is an aggregate entity. You can not create or update them directly. The only way you will get around this is to use the unbound action, msdyn_SaveCalendar.&lt;/p>
&lt;p>To demonstrate this, I have created a simple Schedule entity. This is a child of Contact, with 2 datetime fields, start and end. The premise is the Resource, via a portal, will be allowed to add to their schedule by signing up for predefined slots, but this will mean that there is a schedule for each contact.&lt;/p>
&lt;p>When a schedule record is created, we need to create the corresponding CalendarRule to show that this resource is available in the calendars used for planning.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/06-image-79.png"
loading="lazy"
>&lt;/p>
&lt;p>Next, retrieve the calendar for this resource. The schedule is linked to a Contact, so use the Id to find the Bookable Resource.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/06-image-80.png"
loading="lazy"
>&lt;/p>
&lt;p>Finally, call the action. It is in a loop as the List records always returns 1 or more records.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/06-image-81.png"
loading="lazy"
>&lt;/p>
&lt;p>This is a JSON snippet, creating an object to add to the calendar.&lt;/p>
&lt;p>CalendarId is the Resources calendar, ObjectTypeCode defines this as a Bookable resource, displayed &lt;a class="link" href="http://www.dynamicscrm.blog/object-type-codes-cheat-sheet-for-dynamics-365/" target="_blank" rel="noopener"
>here&lt;/a>. TimeZoneCode is obvious, this points us to UTC. StartDate I have populated with the start of the schedule.&lt;/p>
&lt;p>The next is a list of rules to add to this Calendar, you could create more than one here, but we don&amp;rsquo;t have to. Start and End time are taken directly from the Schedule record. Duration is the time in minutes for the scheduled appointment. This can be calculated by firstly converting both to ticks (seconds) and reconverting to minutes. I got this from an excellent response to a forum question &lt;a class="link" href="https://powerusers.microsoft.com/t5/Building-Power-Apps/how-to-get-difference-between-two-dates-in-flow/td-p/283186" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-csharp" data-lang="csharp">&lt;span class="line">&lt;span class="cl">&lt;span class="n">div&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">div&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mul&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sub&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ticks&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">triggerOutputs&lt;/span>&lt;span class="p">()?[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">body&lt;/span>&lt;span class="p">/&lt;/span>&lt;span class="n">cc_end&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">]),&lt;/span>&lt;span class="n">ticks&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">triggerOutputs&lt;/span>&lt;span class="p">()?[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">body&lt;/span>&lt;span class="p">/&lt;/span>&lt;span class="n">cc_start&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">])),&lt;/span>&lt;span class="m">100&lt;/span>&lt;span class="p">),&lt;/span>&lt;span class="m">1000000000&lt;/span>&lt;span class="p">),&lt;/span>&lt;span class="m">60&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Effort, timecode and subcode are required, defaulted to indicate a working period (timecode 0) and 100% effort (Effort 1).&lt;/p></description></item><item><title>Sales Insights: Sales accelerator</title><link>https://linked365.blog/2020/05/28/sales-insights-sales-accelerator/</link><pubDate>Thu, 28 May 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/05/28/sales-insights-sales-accelerator/</guid><description>&lt;img src="https://linked365.blog/images/2020/05-image-223.png" alt="Featured image of post Sales Insights: Sales accelerator" />&lt;p>This is the final of a 6 part series on Sales Insights, where I attempt to walk through of the Sales AI functionality that is part of the suite. The other articles are listed here.&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/2020/05/05/sales-insights-basic-set-up/" target="_blank" rel="noopener"
>Basic (Free) Setup&lt;/a> - The &amp;ldquo;free&amp;rdquo; AI capabilities that can be added to any Sales Instance&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/2020/05/11/sales-insights-assistant-full-capabilities/" target="_blank" rel="noopener"
>Assistant Studio - Full capabilities&lt;/a> - The full suite of options for Insight Cards&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/2020/05/14/sales-insights-productivity-intelligence/" target="_blank" rel="noopener"
>Productivity Intelligence&lt;/a> - Activity and Contact suggestions as well as Notes Analysis&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/?p=1336" target="_blank" rel="noopener"
>Connection Insights&lt;/a> - Relationship Analytics and Talking points&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/?p=1377" target="_blank" rel="noopener"
>Predictive Models&lt;/a> - Lead and Opportunity scoring along with premium forecasting.&lt;/p>
&lt;p>This post will look at the Sales accelerator, which is still in preview.&lt;/p>
&lt;h2 id="sales-accelerator">Sales Accelerator&lt;/h2>
&lt;p>Playbooks have been around for quite a while - the ability to have a pre-defined set of tasks when something happens. Sequences, which are fundamental for the Sales Accelerator, are a series of prompts to do things which are your best way of completing or reacting to an event. Applying this across your opportunities and leads, it can define what the next action should be today and for which deal.&lt;/p>
&lt;h2 id="configuration">Configuration&lt;/h2>
&lt;p>First, the terms need to be agreed to within the Sales Insights section.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-218.png"
loading="lazy"
>&lt;/p>
&lt;p>Next, the content and layout needs to be defined, which adds components to the Sales Insights forms.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-219.png?fit=1024%2C387&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Ensure you configure the Engagement settings as well as security, I left these as the default.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-220.png"
loading="lazy"
>&lt;/p>
&lt;p>Let Publish and see what has changed. Veronica, my tame Sales user, now has a My Work section in the menu. This shows the Sales Accelerator option. Clicking on this displays a list of things that should be done and the record as shown here.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-221.png?fit=1024%2C800&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Without adding any sequences, the My work is pretty blank, just showing incomplete tasks.&lt;/p>
&lt;h2 id="sequences">Sequences&lt;/h2>
&lt;p>As we have discussed, sequences are a series of recommended tasks of your best practice to complete a sales process successfully. As an administrator, add a new sequence from the Sales Insights settings.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-222.png"
loading="lazy"
>&lt;/p>
&lt;p>Choose a name and also which of the entitles you want this sequence to start on.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-223.png"
loading="lazy"
>&lt;/p>
&lt;p>You are then prompted to create your first activity.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-224.png"
loading="lazy"
>&lt;/p>
&lt;p>I chose Email. There are a variety of options depending on what you choose, email having the ability to use a template.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-226.png"
loading="lazy"
>&lt;/p>
&lt;p>Next, add steps as your requirements dictate. Another important one is a wait time. This will mean the next activity will not be displayed until that time has passed.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-227.png"
loading="lazy"
>&lt;/p>
&lt;p>Build up your sequence with other steps and delays.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-228.png"
loading="lazy"
>&lt;/p>
&lt;p>Save the sequence then activate it. Activation allows a user to apply the sequence to a record but prevents you from editing it while it is active. You need to deactivate first. Any sequences currently running will be disconnected from the sequence when is deactivated. This is nonsense, in my opinion. If you have a published sequence that you need to tweak, all users would have to re-apply the sequence and start from scratch.&lt;/p>
&lt;p>In a Lead or Opportunity view now, if you select one or more records you get a new option to connect a sequence.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-229.png"
loading="lazy"
>&lt;/p>
&lt;p>This will display a list of the active sequences. Select one and choose Connect.&lt;/p>
&lt;p>![]((images/2020/05-image-230.png?fit=1024%2C395&amp;amp;ssl=1)&lt;/p>
&lt;p>In the My Work section now, you will see an additional list, like below listing 3 lead actions to be done today. This view also shows the other steps I created.&lt;/p>
&lt;p>![]((images/2020/05-image-231.png?fit=1024%2C477&amp;amp;ssl=1)&lt;/p>
&lt;p>The steps can then be completed or action from that central pane. In this case, we can send an email or just mark it as complete. The next action, with the associated record is displayed in the main view.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-SI-Acc-1.gif"
loading="lazy"
>&lt;/p>
&lt;p>In the Up Next pane, the action depends on the type of step. Email will create a new email and populate with the template is selected. Task will use a quick create form. Phone call will attempt to use your configured dialer. I find this a problem as most sales environments won&amp;rsquo;t have an integration, and will frequently rely on a mobile to do the actual call. I would still want to log the fact that this call occurred.&lt;/p>
&lt;p>On the left panel, there are options to sort the list by score and at this point, it brings in all the capabilities of Sales Insights together.&lt;/p>
&lt;h2 id="final-thoughts">Final Thoughts&lt;/h2>
&lt;p>Sequences are a great tool to aid your workforce if your sequence of events is simple. I would like to see branching within the sequence with steps being defined by data on the record. Imagine if the sequence branched determined by the expected revenue or days to decision date? I added this idea &lt;a class="link" href="https://experience.dynamics.com/ideas/idea/?ideaid=343d96cd-fa9f-ea11-8b71-0003ff68992e" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;p>You can achieve both in Flow, but you need to create the records as you do if you use Playbooks. Sequences allow you to suggest record creation rather than enforce. Also, there is no customisation in sequences, except for Email Templates. Custom activities are not supported, for example. Would love some of the tasks to be automated, like an email reminder if no email has been returned from the customer. And it should interact with the email engagement part to&lt;/p>
&lt;p>The deactivation process also needs to be altered. Deactivating will de-link the sequence form the record. I would suggest deactivating leaves sequences connected to records to run but prevents new connections. You should be able to clone a sequence so that your new one can be used once you have tweaked it. I added the idea &lt;a class="link" href="https://experience.dynamics.com/ideas/idea/?ideaid=1709a075-00a0-ea11-8b71-0003ff68992e" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;p>Whilst I think it is a good step forward, the functionality available in tools like &lt;a class="link" href="https://www.salesspark.com/" target="_blank" rel="noopener"
>SalesSpark&lt;/a> is above and beyond what is available in Sales Accelerator now. I do think that Microsoft will get there though and hopefully will bring more automation and tools to the standard Sales functionality.&lt;/p></description></item><item><title>Sales Insights: Predictive Models</title><link>https://linked365.blog/2020/05/27/sales-insights-predictive-models/</link><pubDate>Wed, 27 May 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/05/27/sales-insights-predictive-models/</guid><description>&lt;img src="https://linked365.blog/images/2020/05-image-149.png" alt="Featured image of post Sales Insights: Predictive Models" />&lt;p>This is the fifth in the series on Sales Insights, were I attempt to walkthrough the Sales AI functionality that is part of the suite. The other articles are listed here.&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/2020/05/05/sales-insights-basic-set-up/" target="_blank" rel="noopener"
>Basic (Free) Setup&lt;/a> - The &amp;ldquo;free&amp;rdquo; AI capabilities that can be added to any Sales Instance&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/2020/05/11/sales-insights-assistant-full-capabilities/" target="_blank" rel="noopener"
>Assistant Studio - Full capabilities&lt;/a> - The full suite of options for Insight Cards&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/2020/05/14/sales-insights-productivity-intelligence/" target="_blank" rel="noopener"
>Productivity Intelligence&lt;/a> - Activity and Contact suggestions as well as Notes Analysis&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/?p=1336" target="_blank" rel="noopener"
>Connection Insights&lt;/a> - Relationship Analytics and Talking points&lt;/p>
&lt;p>This post will walkthrough the Predictive models functionality, which includes Lead and Opportunity scoring as well as Premium forecasting.&lt;/p>
&lt;h2 id="lead-scoring">Lead Scoring&lt;/h2>
&lt;p>Predictive Lead scoring is a machine learning model which puts a score against each open lead. This allows your sales users to prioritise their interactions with leads, nurturing the right ones at the right tie to improve qualification results and reduce the time take to qualify a lead.&lt;/p>
&lt;p>The model used is specific to your organisation and needs to be configured by the administrator prior to publication and usage by the salesforce.&lt;/p>
&lt;p>Like Relationship analytics with similar opportunities I discussed previously, it needs some data. 30 qualified and unqualified leads. I utilised &lt;a class="link" href="https://mockaroo.com/" target="_blank" rel="noopener"
>Mockaroo&lt;/a> to create a thousand leads then used Flow to qualify and unqualify randomly. I detailed my work in the previous post, &lt;a class="link" href="https://linked365.blog/2020/05/21/mockaroo-and-flow-perfect-demo-data/" target="_blank" rel="noopener"
>here.&lt;/a> Once this is done, the predictive lead scoring is enabled.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-144.png?fit=1024%2C748&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Pressing Get Started now shows this screen.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/image-146.png?fit=1024%2C659&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>I was expecting the ability to create my own model, but it seems it uses the default first. Once ready, it shows this screen.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-149.png"
loading="lazy"
>&lt;/p>
&lt;p>Not really good accuracy so far&amp;hellip;. Selecting Publish brings you to the configuration site.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/image-150.png?fit=1024%2C478&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Now, let&amp;rsquo;s add some fields that have been populated in the Lead to personalise the model. Select Edit Fields. The next screen allows you to define the list of fields that you think have an impact on the qualification rate of a lead. Here, the fields that were populated when I created Leads are used. Your mileage on which fields is part of the training of your model.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-199.png"
loading="lazy"
>&lt;/p>
&lt;p>Once this is done, Click Retrain model for this new field selection to be used. After a period, the model is ready, and you can publish this model. Once published, the toggle for retraining automatically is available. This will, as it suggests, retrain the model regularly based on the fields selected. It will only publish the new version of the model it is better at predicting that the previous model&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-200.png"
loading="lazy"
>&lt;/p>
&lt;p>On the Lead form, there is a new section available, namely Predictive Lead Scoring.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-201.png"
loading="lazy"
>&lt;/p>
&lt;p>This is telling the sales user that this lead is likely to be disqualified, and the reasons why. There is also a view that is made available, My Open Leads Scored which gives a visual indicator of the score for each. Great information for a Sales user to quickly identify the Leads worth progressing.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/image-202.png?fit=1024%2C226&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;h2 id="opportunity-scoring">Opportunity Scoring&lt;/h2>
&lt;p>Similar steps can be completed for the Opportunity Scoring, with a Predictive Opportunity Scoring section added to the Opportunity form.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-203.png"
loading="lazy"
>&lt;/p>
&lt;p>Top right of this section is a Chat icon, allowing a user to give feedback and provide a different score to the one given.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-204.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="premium-forecasting">Premium Forecasting&lt;/h2>
&lt;p>Premium Forecasting is based on the standard forecasting but adds a prediction on the value of each opportunity dependent on historical information as well as data in the opportunity.&lt;/p>
&lt;p>To establish forecasting, first, as an administrator, establish a forecast by choosing the Forecast configuration in the Sales App Settings section.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-206.png"
loading="lazy"
>&lt;/p>
&lt;p>Add a Org chart Forecast. This presents you with a form to fill out.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/image-207.png?fit=1024%2C849&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Required fields are a name and the top of the hierarchy. Here, I have configured the management hierarchy as shown to reflect the data in my system.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-208.png"
loading="lazy"
>&lt;/p>
&lt;p>Clicking on the progress bar at the top (great control!), leave the user security section as default and hit Next.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-210.png"
loading="lazy"
>&lt;/p>
&lt;p>Include the Prediction field in the Layout and columns section. Here, you can add a column set - I found difficulty here, as the configuration of the values was not done automatically, I had to attach a column set and then use the option to change option set selection to choose the one I actually wanted, which would then show the Auto-configure columns option.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-212.png"
loading="lazy"
>&lt;/p>
&lt;p>Select Next again, then activate the forecast.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-214.png"
loading="lazy"
>&lt;/p>
&lt;p>After a while, a success message is displayed.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-215.png"
loading="lazy"
>&lt;/p>
&lt;p>Once this is done, sales users will be able to select the Forecasts section for themselves. As you can see from the version for Veronica, the Opportunities in the forecast include the hierarchy. The bottom panel can also be used to quickly forecast data, such as the category, revenue and close dates.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/image-217.png?fit=1024%2C559&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>The Prediction value in the top row is meant to show the revenue, including the prediction percentage, but I have found it hard to replicate the data I need to establish a value.&lt;/p></description></item><item><title>Sales Insights: Connection Insights</title><link>https://linked365.blog/2020/05/18/sales-insights-connection-insights/</link><pubDate>Mon, 18 May 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/05/18/sales-insights-connection-insights/</guid><description>&lt;img src="https://linked365.blog/images/2020/05-image-140.png" alt="Featured image of post Sales Insights: Connection Insights" />&lt;p>This is the fourth in a series walking through the Sales Insights add-on application. The series list is below for your reference.&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/2020/05/05/sales-insights-basic-set-up/" target="_blank" rel="noopener"
>Basic (Free) Setup&lt;/a> - The &amp;ldquo;free&amp;rdquo; AI capabilities that can be added to any Sales Instance&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/2020/05/11/sales-insights-assistant-full-capabilities/" target="_blank" rel="noopener"
>Assistant Studio - Full capabilities&lt;/a> - The full suite of options for Insight Cards&lt;/p>
&lt;p>&lt;a class="link" href="https://linked365.blog/2020/05/14/sales-insights-productivity-intelligence/" target="_blank" rel="noopener"
>Productivity Intelligence&lt;/a> - Activity and Contact suggestions as well as Notes Analysis&lt;/p>
&lt;p>This post will be walking through Connection Insights, which includes Relationship Analytics and Talking Points.&lt;/p>
&lt;h2 id="relationship-analytics">Relationship Analytics&lt;/h2>
&lt;p>Relationship Analytics uses the data stored in D365 and Exchange, whether accounts, contacts, activities and emails. It then computes numerous KPIs for this data to establish how best to interact with an individual, leading to improved closure rates and customer satisfaction. There is also an analysis of the health of relationships to improve customer retention.&lt;/p>
&lt;p>The first step is to enable Relationship analytics and health by clicking the box within the Sales Insights settings app.&lt;/p>
&lt;p>&lt;img src="https://i2.wp.com/linked365.blog/wp-content/uploads/2020/05/image-124.png?fit=1024%2C584&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Hitting Save (the 2 Data Sources options were not enabled for me) you get a message stating it is being activated.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-125.png"
loading="lazy"
>&lt;/p>
&lt;p>After a short period, a success message is ready to use. At this point I have not changed any settings, including not enabling the Exchange Online configuration, as I would like to see what it is like without Email data.&lt;/p>
&lt;p>For the sales user, there is a new View available against opportunities, namely My Open Opportunities by Relationship. On first use, this is not very impressive.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/image-126.png?fit=1024%2C320&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Relationship health is done by looking at the frequency and type of interaction with the customer regarding the opportunity. By adding in some data (this is a demo system so data is not available) the view becomes a lot more usable.&lt;/p>
&lt;p>In this instance, data is added to the opportunity. You will also notice that a new section to the Opportunity form is has appeared. This section is giving me a visual representation of the health and indication when the next and last interactions were.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-128.png?fit=1024%2C505&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>The KPIs are not populated straight away, it states it could be a couple of hours behind, so be patient. You will see the Relationship Health State (KPI) populated with the Health Computation in Progress which indicates it has enough data to provide a value.&lt;/p>
&lt;p>Once calculated, the control on the form is updated&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-130.png"
loading="lazy"
>&lt;/p>
&lt;p>Further, the view is giving you a visual indication across your opportunities&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/image-131.png?fit=1024%2C326&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Unfortunately, the data I entered wasn&amp;rsquo;t enough to make the relationship anything except poor! As you add more activity, this changes. I think on a 12 hour cycle, but can not confirm.&lt;/p>
&lt;p>&lt;img src="https://i2.wp.com/linked365.blog/wp-content/uploads/2020/05/image-132.png?fit=1024%2C165&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Also, now it is a little more insightful and realistic, let&amp;rsquo;s look at the chart that comes with the solution. Click on Show Chart and select Relationship Pipeline.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/SI-Rel-Ana-1.gif?fit=1024%2C719&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>This chart shows all the deals that are due to close and plots them along with their relationship health. The bigger the circle, the larger the revenue. You can also hover over a point to see those key metrics. Pretty!&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-133.png"
loading="lazy"
>&lt;/p>
&lt;p>Digging further into some of the tools, along with the control on the Opportunity record, there is a new tab, Relationship Analytics.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-135.png?fit=1024%2C455&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>This is a great, one stop shop to look at the activity on the opportunity and how it is improving over time. Top left is the same content you seen on the first tab. Next is the count of Interactions that have occurred on this opportunity, split between us, your employees, and them, your customers.&lt;/p>
&lt;p>The top right shows the time spent on the Opportunity, a count of the hours spent in appointments or tasks, again split between us and them. Us is calculated by multiplying the length of the activity by the number of employees were part of the activity. Them does not do this calculation and is just a summation of the length of the activities where they were involved.&lt;/p>
&lt;p>Email Engagement relies on the Email Engagement functionality discussed in a previous &lt;a class="link" href="https://linked365.blog/2020/05/05/sales-insights-basic-set-up/" target="_blank" rel="noopener"
>post&lt;/a>. It shows all emails that were sent to and from the customer and how many were opened etc. Response rate measures the ratio of emails we sent to the customer which they responded to and vice-versa. This also comes from the Response time, which is the next chart.&lt;/p>
&lt;p>Most contacted displays the contacts that have been included on meetings, calls or emails regarding this opportunity. This is duplicated for who has sent the most emails etc in Most Contacted By.&lt;/p>
&lt;p>Finally, the Relationship Activities lists when activity has taken placed, the create date for activities over the lifetime of the Opportunity.&lt;/p>
&lt;p>This tab is pretty useful and will come into its own when you have the data to support it. We all know the more you speak to a client the more likely an opportunity will be successful. The likelihood of a deal being lost where the customer continues to respond frequently and quickly is pretty slim.&lt;/p>
&lt;h2 id="fine-tuning-the-results">Fine-tuning the results&lt;/h2>
&lt;p>Microsoft has provided you with a way of &amp;ldquo;tweaking&amp;rdquo; the results of the KPIs by rating the relative influence of each activity type. This will depend on your business and how it operates. For a B2C business, I would suggest that email or phone calls would be normal, and a meeting would normally be rare and infer a good relationship with the customer. B2B these would be different, with meetings more common.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-136.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="relationship-analytics-with-similar-opportunities-preview">Relationship Analytics with similar opportunities (preview)&lt;/h2>
&lt;p>There is a preview addition to the Sales Insights tools, namely relationship analytics with similar opportunities. There is a warning when you enable this feature that you need to have at least 30 each of won and lost opportunities to allow the new KPIs to be available.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-137.png?fit=1024%2C212&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>In that spirit, I created a Flow to generate the data. The flow asks for a number, then creates that number of opportunities for each active account with that number of activities, a random mix of emails, meetings, tasks &amp;amp; calls against each opportunity. It then closes the opportunity, either won or lost, with a roughly 60% spilt for won.&lt;/p>
&lt;p>You can find the flow as well as the other tweaks I made to my environment in GitHub &lt;a class="link" href="https://github.com/CooksterC/Community/tree/master/SalesInsightsTweaks" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;p>By enabling the preview, you have to agree to the terms.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-139.png"
loading="lazy"
>&lt;/p>
&lt;p>On the Opportunity screen now, the Relationship Analytics tab is replaced with Relationship Analytics (Preview) and is significantly improved, comparing your opportunity with the historic data.&lt;/p>
&lt;p>&lt;img src="https://i2.wp.com/linked365.blog/wp-content/uploads/2020/05/image-140.png?fit=1024%2C870&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;h2 id="talking-points">Talking Points&lt;/h2>
&lt;p>Small talk is a method of embedding you with a customer or lead. If they think you are friendly and discuss more than just the product or deal, then it has been proven to increase the likelihood of winning a contract. Remembering all your client&amp;rsquo;s insignificant details, and not confusing customers is hard work. Great salespeople make notes on each client and keep them updated. Dynamics eases this pain by scanning your email and highlighting to you details about the customer which you can use to improve your relationship with them.&lt;/p>
&lt;p>These talking points are using the individuals&amp;rsquo; email, which is private to them, so any points that displayed are specific to the individual sales user.&lt;/p>
&lt;p>Back in the Sales Insights settings, an administrator can enable talking points and also which categories to use.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-142.png"
loading="lazy"
>&lt;/p>
&lt;p>There is one more thing you need to do to enable this, and it isn&amp;rsquo;t documented. Thankfully Priyesh Wagh steered me straight in his blog &lt;a class="link" href="https://d365demystified.com/2018/12/09/talking-points-in-d365-ai-for-sales/" target="_blank" rel="noopener"
>article&lt;/a> for D365 DeMystified. Thanks, &lt;a class="link" href="https://twitter.com/priyesh_wngman7" target="_blank" rel="noopener"
>Priyesh&lt;/a>!&lt;/p>
&lt;p>The relationship analytics solution adds a control to the contact form, namely TalkingPoints_section. This needs making visible by default, the form published an then you will see in the contact form a new section. This is populated with parts of an email I sent in.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-143.png"
loading="lazy"
>&lt;/p>
&lt;p>Each of the icons in the bottom represents the categories that have been found in the email that you have with the contact. If you click on an icon, the relevant snippet is shown. Further you can choose to view this in carousel view, the default, or list view by clicking on the icon top right.&lt;/p>
&lt;p>Lastly, by selecting the drop down arrow, the full email is displayed, where the user can click on the hyperlink to go to that email.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-SI-Rel-Ana-2.gif"
loading="lazy"
>&lt;/p></description></item><item><title>Sales Insights: Productivity Intelligence</title><link>https://linked365.blog/2020/05/14/sales-insights-productivity-intelligence/</link><pubDate>Thu, 14 May 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/05/14/sales-insights-productivity-intelligence/</guid><description>&lt;img src="https://linked365.blog/images/2020/05-image-91.png" alt="Featured image of post Sales Insights: Productivity Intelligence" />&lt;p>This is the third instalment of my review/walkthrough of the Dynamics 365 Sales Insights application. &lt;a class="link" href="https://linked365.blog/2020/05/05/sales-insights-basic-set-up/" target="_blank" rel="noopener"
>Part 1&lt;/a> detailed the free features, with &lt;a class="link" href="https://linked365.blog/?p=1242" target="_blank" rel="noopener"
>Part 2&lt;/a> detail the first of the premium features, Assistant Studio, including custom Insight cards and how to prioritise them.&lt;/p>
&lt;p>This time, the blog is about Productivity Intelligence. This encompasses Auto capture (automatically bringing in content from Outlook and act on it, to reduce time entering data), email engagement (tracking email interaction from your customers) and Notes analysis (suggesting actions on the notes you make).&lt;/p>
&lt;h2 id="auto-capture">Auto capture&lt;/h2>
&lt;p>I have already discussed the basic version of this, so will just be going through the additions the Premium version brings.&lt;/p>
&lt;p>Auto capture is not enabled by default when you enable the other Sales Insights features, toggle the switch&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-91.png"
loading="lazy"
>&lt;/p>
&lt;p>You have to agree to the terms and conditions as this is still a preview feature&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-92.png"
loading="lazy"
>&lt;/p>
&lt;p>Here you now get to choose a security role or allow all users to enrol. This is on top of the license requirement. I checked all the content to be captured for my trial.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-93.png"
loading="lazy"
>&lt;/p>
&lt;p>As All security roles have been selected, the warning that basic features will be displayed is shown.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-94.png"
loading="lazy"
>&lt;/p>
&lt;p>Once complete, each user will have to give individual consent as well, which appears in the timeline or in the Assistant like below.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-98.png"
loading="lazy"
>&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-99.png"
loading="lazy"
>&lt;/p>
&lt;p>After you select Allow access, the central panel now has an Activity Suggestions link.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-100.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="activity-suggestions">Activity Suggestions&lt;/h3>
&lt;p>If an email comes into the users inbox now, a notification is displayed if the email address is associated with the account or contact.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-101.png"
loading="lazy"
>&lt;/p>
&lt;p>At the bottom is a Show all link, which displays a simple popup before delivering the user to the Activity Suggestions page.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-102.png"
loading="lazy"
>&lt;/p>
&lt;p>This is also available via the menu on the left&lt;/p>
&lt;p>&lt;img src="https://i2.wp.com/linked365.blog/wp-content/uploads/2020/05/image-104.png?fit=1024%2C292&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Back in the timeline frame, a couple of options are available to the user, highlighted below. The first dismisses the suggestion, removing it from the list of possible suggestions.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-105.png"
loading="lazy"
>&lt;/p>
&lt;p>The next allows you to edit the activity, namely set the regarding to a different record&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-106.png"
loading="lazy"
>&lt;/p>
&lt;p>Hitting Save on the Edit screen shows this screen before the activity becomes part of the timeline.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/image-107.png?fit=1024%2C595&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>The third option is just Save, which provides a prompt before it is created.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-108.png"
loading="lazy"
>&lt;/p>
&lt;p>A small prompt is also shown when saving activities in this manner&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-109.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="contact-suggestions">Contact Suggestions&lt;/h3>
&lt;p>With the advanced features, you also get Contact Suggestions. This reduces the effort that syncing contacts etc. can be for your workforce. If an email is received from an email that is not within D365, a contact suggestion is created. An insight suggestion appears on the dashboard, which takes you to the full list on the left.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-112.png"
loading="lazy"
>&lt;/p>
&lt;p>On the menu, there is also a Contact Suggestions menu allowing the user to go to their full list.&lt;/p>
&lt;p>&lt;img src="https://i2.wp.com/linked365.blog/wp-content/uploads/2020/05/image-119.png?fit=1024%2C286&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>These contacts are ones that are not present in my instance and as such are prime to be brought in. Selecting a contact or the hyperlinked full name takes you to a quick create form, prepopulated with the information it has captured.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-120.png"
loading="lazy"
>&lt;/p>
&lt;p>Save and Close will create a contact in the system. Hitting cancel returns you to the list, but the contact suggestion is removed. I have asked the question on the forums, as I don&amp;rsquo;t think this is correct behaviour, whether intentional or not. Will update if I get a response.&lt;/p>
&lt;p>&lt;strong>UPDATE&lt;/strong>: Had confirmation that this is a bug and it &lt;a class="link" href="https://community.dynamics.com/365/aisales/f/dynamics-365-sales-insights/389123/contact-suggestions---cancel-in-quick-create-removes-suggestion/1044856#1044856" target="_blank" rel="noopener"
>will be fixed&lt;/a> by the end of the month! See, if you raise problems to Microsoft, they get resolved!&lt;/p>
&lt;p>On the list, you also have options to either Save as contact, which will create using the default population or Edit and Save which will show the quick create form. Delete will remove this contact from the suggestions. If you select more than one contact suggestion, only Save as contact and Delete are available.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-122.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="notes-analysis">Notes Analysis&lt;/h3>
&lt;p>The final part of Productivity Intelligence is Notes Analysis. This uses sentiment analysis to capture information held in the notes against contacts, accounts or opportunities. From this information, suggestions are made with data retrieved from the notes.&lt;/p>
&lt;p>Notes Analysis is enabled within the Sales Insights application once again. Toggle the switch.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-111.png"
loading="lazy"
>&lt;/p>
&lt;p>So now, in the activity pane against accounts, contacts, case, opportunity &amp;amp; lead you will be offered suggestions to create other records from the content in the notes. This is by providing a hyperlink in the note itself.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-113.png"
loading="lazy"
>&lt;/p>
&lt;p>Notice how the notes are read in direct notes and emails. Clicking on the link provides the user with a suggestion.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-115.png"
loading="lazy"
>&lt;/p>
&lt;p>As you can see from this suggestion, not only has it determined that I should have a meeting planned for Tuesday, but automated the date entry from my &amp;ldquo;next tuesday&amp;rdquo;.&lt;/p>
&lt;p>If I hit Edit and Create, a Quick Create form is displayed, prepopulated with the detail.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-116.png"
loading="lazy"
>&lt;/p>
&lt;p>The only issue I have here is that the note, when I return to the Timeline, still appears like I have not done the previous step and created the activity. Some suggestions allow a quicker create process, if you don&amp;rsquo;t need to change any of the detail&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-117.png"
loading="lazy"
>&lt;/p>
&lt;p>Edit and Create displays the prepopulated Quick Create form. Create just accepts the defaults and creates the record.&lt;/p>
&lt;p>Note Analysis is a great tool to the arsenal of the busy sales person. All of these tools are trying to reduce the time spent doing administrative tasks and push the sales person to be more active with their customers.&lt;/p></description></item><item><title>Sales Insights: Assistant (full capabilities)</title><link>https://linked365.blog/2020/05/11/sales-insights-assistant-full-capabilities/</link><pubDate>Mon, 11 May 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/05/11/sales-insights-assistant-full-capabilities/</guid><description>&lt;img src="https://linked365.blog/images/2020/05-image-48.png" alt="Featured image of post Sales Insights: Assistant (full capabilities)" />&lt;p>In my previous &lt;a class="link" href="https://linked365.blog/?p=1183" target="_blank" rel="noopener"
>post&lt;/a>, I walked through the configuration of the standard, &amp;ldquo;free&amp;rdquo; features of the Sales Insights offering for D365 Sales. This time, I am going to start on the premium features covered by the £37.70 per month license fee.&lt;/p>
&lt;p>If you look at the Sales Insights administration screen, the list of the capabilities is quite hefty. For this post, I will concentrate on the Assistant, Sales Insights cards and prioritising them.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-48.png"
loading="lazy"
>&lt;/p>
&lt;p>To get going, hit the Try Sales Insights button. This launches the screen below. Read and agree to the terms and hit continue.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/image-51.png?fit=1024%2C275&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Once done, you are presented with the install screen.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/image-52.png?fit=1024%2C497&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Once installation is complete, a message appears and the Go to Configuration is now available. This button takes the user to the Sales Insights Settings portion of the application.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-53.png?fit=1024%2C88&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>As you can see there is a lot more settings available to the administrator now. Lets start with the Insight Cards available in the Assistant Studio.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-54.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="assistant-studio">Assistant Studio&lt;/h2>
&lt;p>The advanced Assistant Studio is a separate display than the &amp;ldquo;free&amp;rdquo; version I mentioned on previous post.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-55.png?fit=1024%2C740&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>The first thing you will notice is the ability to make your own. This utilises Power Automate (and from there, you could rule the world) to define a schedule or trigger to run and produce a card for display.&lt;/p>
&lt;p>&lt;img src="https://i2.wp.com/linked365.blog/wp-content/uploads/2020/05/image-56.png?fit=1024%2C364&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>Each Insight card has a security role selection now.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-77.png"
loading="lazy"
>&lt;/p>
&lt;p>Also, on the left is an ability to tweak the ranking of the cards, which ones appear higher in the view. This is tweaking the inbuilt sorting in addition to being able to make the card a priority. It is pretty limited, only 4 ranks available, but I would think that this is more than enough for most scenarios.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/image-79.png?fit=1024%2C478&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;h3 id="creating-a-custom-insight-card">Creating a Custom Insight Card&lt;/h3>
&lt;p>Though the most common scenario would be using Power Automate to create a custom Insight, it is possible to go further by using cards created as XML and import them into your environment as a solution. The card is triggered by using the Web API. This will require a blog post on its own to get to the details, but for now, here is the link the Microsoft &lt;a class="link" href="https://docs.microsoft.com/en-gb/dynamics365/ai/sales/extend-relationship-assistant-card" target="_blank" rel="noopener"
>tutorial&lt;/a> on the subject. As you are calling the Web API, when and if these cards get created is open to a whole manner of scenarios - alerting from a finance system or bespoke service offering, or even telemetry from your own app or licensing solution is possible.&lt;/p>
&lt;p>Thankfully, creating cards via Power Automate is a lot simpler. I will walk through a scenario that is applicable to a Sales team. Everyone has competitors. Competitors all have blog rolls where they publish information on their products and views. It would be good to highlight these new posts to your Sales team, so they are aware of the latest developments prior to discussions with their customers. You can have a trigger for when an RSS feed changes, but this would mean you would have a flow for each blog. Adding a competitor blog would be time-consuming and in-effective.&lt;/p>
&lt;p>My design would be to on a daily schedule, loop through each of the competitors stored in the D365 environment with a blog, read any articles that have been posted since the day before and create an Insight card for each.&lt;/p>
&lt;p>I created a new field on the Competitor entity to enter the blog address.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-59.png"
loading="lazy"
>&lt;/p>
&lt;p>I have put it on the Competitor form and filled it with my blog for testing.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-60.png"
loading="lazy"
>&lt;/p>
&lt;p>My trigger is a schedule, defined to run every day at 7am.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-58.png"
loading="lazy"
>&lt;/p>
&lt;p>Then, get all the competitors that have a blog listed.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-66.png"
loading="lazy"
>&lt;/p>
&lt;p>Each Insight Card that you create needs to have a user that you will show the insight for - something that flummoxed me for a long while. I would have thought that some cards would be applicable to the whole organisation, or a group of users. You can assign a security group for a card, which I will show later, so would assume it would create an active card for each member of the security group at the least. (I created an idea &lt;a class="link" href="https://experience.dynamics.com/ideas/idea/?ideaid=4835db60-fc8e-ea11-99e5-0003ff689573" target="_blank" rel="noopener"
>here&lt;/a>).&lt;/p>
&lt;p>To combat this, retrieve the Team based on a name (to allow for moving between environments)&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-68.png"
loading="lazy"
>&lt;/p>
&lt;p>Put this into a variable for use in the next query without a loop action.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-69.png"
loading="lazy"
>&lt;/p>
&lt;p>Then, query the team memberships table. The user id is the field needed so this is easier than drilling down to the user table.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-70.png"
loading="lazy"
>&lt;/p>
&lt;p>Convert this to an array so the flow can quickly use the values when creating the Insight card.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-71.png"
loading="lazy"
>&lt;/p>
&lt;p>For each of the blogs, get the posts that have been created since yesterday. If there is any, loop through the articles then for each user create an Insight card.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-74.png"
loading="lazy"
>&lt;/p>
&lt;p>With this information, we can post our card, firstly find the Sales Insights connector, and choose Create card for assistant V2 (preview)&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-62.png"
loading="lazy"
>&lt;/p>
&lt;p>When you add this for the first time, you are prompted to log in and consent for the connector. Lots of permissions needed.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-64.png"
loading="lazy"
>&lt;/p>
&lt;p>Finally, ready for creating the card. Here, properties from the blog roll and the Competitor are used.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-73.png"
loading="lazy"
>&lt;/p>
&lt;p>There are other properties that could be applicable to your Sales Insight, such as Card behaviour after click (whether to dismiss\snooze\do nothing to the card when the action is clicked), which entity and record to display the card on (remember this is only for core sales entities so far, namely Account, Contact, Lead and Opportunity) and display dates for the Insight.&lt;/p>
&lt;p>The Button type is an interesting selection. I have chosen open URL, but there is also Custom Action (CRM Process), Launch playbook, Open Record and Open URL. I used Open URL for my demo, will describe the others later in the post.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-80.png"
loading="lazy"
>&lt;/p>
&lt;p>The Show for is populated with the following. This gets the current user Id from the teams membership array.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-csharp" data-lang="csharp">&lt;span class="line">&lt;span class="cl">&lt;span class="n">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Loop_users&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)?[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">userId&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The URL is populated with a link to the article, but as this is an array in itself, take the first one using the code below&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-csharp" data-lang="csharp">&lt;span class="line">&lt;span class="cl">&lt;span class="n">first&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Loop_new_articles&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)?[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">links&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Once this code is run, you should create your first custom insight card, which appears on the dashboard like below&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-75.png"
loading="lazy"
>&lt;/p>
&lt;p>Drilling down into the note gives you more detail and allows the action to be taken.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-76.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="button-types">Button Types&lt;/h3>
&lt;p>As described earlier, there are 5 actions available in the button types.&lt;/p>
&lt;h4 id="custom-action-crm-process">Custom Action (CRM Process)&lt;/h4>
&lt;p>Custom Action is a relatively new one. It relies on a pre-created action in the Flow that defines the action. This functionality allows the administrator to configure triggering of a workflow or plugin, as long as it is against an entity.&lt;/p>
&lt;p>For example, here the action is defined to use the Opportunity custom action CloseAllOpportunityQuotes, define which record it needs to run against and also the quote Status.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-87.png"
loading="lazy"
>&lt;/p>
&lt;p>The parameters are defined by the action within the D365 customisation.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-89.png"
loading="lazy"
>&lt;/p>
&lt;p>This new action is configured in the Sales Insight card creation step.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-88.png"
loading="lazy"
>&lt;/p>
&lt;h4 id="launch-playbook">Launch Playbook&lt;/h4>
&lt;p>Playbooks are a relatively new feature within the Sales app, which allows a sales manager or administrator to configure a pre-defined set of activities, or a play, to define the perfect way an interaction with a customer should work. You can define them on one or more of the core sales entities.&lt;/p>
&lt;p>&lt;img src="https://i2.wp.com/linked365.blog/wp-content/uploads/2020/05/image-82.png?fit=1024%2C489&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>On a Sales Insight card, establish which Playbook template you want to use, define which entity to apply it to and which record.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-83.png"
loading="lazy"
>&lt;/p>
&lt;h4 id="open-record">Open Record&lt;/h4>
&lt;p>This is a simple one, launch a record when the user hits the button. Define the entity and the record Id.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-84.png"
loading="lazy"
>&lt;/p>
&lt;h4 id="open-url">Open URL&lt;/h4>
&lt;p>Another simple one, I used it in the walkthrough above. You need to define the URL to open, here I link back to the first article link in the RSS feed.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-85.png"
loading="lazy"
>&lt;/p>
&lt;h4 id="rest">REST&lt;/h4>
&lt;p>This button type allows interaction with an API endpoint. Define the endpoint, which method, though I am not sure what use a GET would be. Also, define the Headers and body. This allows the user to push content or start activity in external systems, logging a case with ServiceNow or creating an activity in your own bespoke system for example. You could also use this to trigger a Flow and create an interaction via that route.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-86.png"
loading="lazy"
>&lt;/p></description></item><item><title>Sales Insights: Basic set up</title><link>https://linked365.blog/2020/05/05/sales-insights-basic-set-up/</link><pubDate>Tue, 05 May 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/05/05/sales-insights-basic-set-up/</guid><description>&lt;img src="https://linked365.blog/images/2020/05-image.jpeg" alt="Featured image of post Sales Insights: Basic set up" />&lt;p>I have been working for quite a while on &lt;a class="link" href="https://dynamics.microsoft.com/en-gb/ai/customer-insights/" target="_blank" rel="noopener"
>Customer Insights&lt;/a>, running workshops and generally getting to know it, but I realised that there is a multitude of products in the Insights suite, Customer Insights, Customer Service Insights, Product Insights, Marketing Insights and Sales Insights. These tools each have their own niche, and I don&amp;rsquo;t know them at all well. So I thought I would educate myself and hopefully someone else by walking through configuring each one and writing down my experiences.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image.jpeg"
loading="lazy"
alt="Microsoft Dynamics 365 Sales Insights - YouTube"
>&lt;/p>
&lt;h2 id="the-business-case">The Business Case&lt;/h2>
&lt;p>Dynamics 365 Sales Insights to use its full name is designed to help your sales managers improve their team&amp;rsquo;s performance. It does this by continuously analysing the interactions a salesperson has with a customer, whether in D365 Sales or Exchange. Each business relationship is evaluated to understand the activities that are completed and how previous interactions have affected sales.&lt;/p>
&lt;p>Do you know how often a salesperson contacts a potential lead? Do they always use canned responses, or is there a form of personality on the interaction? Have you provided your sales team with actionable insights about their opportunities?&lt;/p>
&lt;p>Dynamics 365 Sales Insights has a selection of Free and Advanced features which improve the view of the customer, enabling rich customer experiences in the interactions with your sales team. It uses AI modelling to constantly monitor these interactions and provide insights to your salespeople at the appropriate time, increase lead closure and customer satisfaction.&lt;/p>
&lt;h2 id="free-vs-advanced">Free vs Advanced&lt;/h2>
&lt;p>As already described, there are several free tools to start your journey, which are part of the standard Dynamics 365 Sales offering, namely Assistant (was Relationship Assistant), Auto Capture and email engagement. This first part of the series will walk through configuring the free features.&lt;/p>
&lt;p>Advanced features is a £37.70 per month per user add-on, which is a hefty cost, but with it, you get the full suite of products - Assitant with Studio, Relationship Analytics, Predictive lead and opportunity scoring, Notes analysis, Talking points, Who knows whom, Sales accelerator, Assistant for teams and Conversation Intelligence. This is a lot of functionality. Over the next few posts, I will try and educate myself and step through the experience.&lt;/p>
&lt;h2 id="configuring-sales-insights-free-features">Configuring Sales Insights Free features&lt;/h2>
&lt;p>I started with a brand new trial, again, the best way to do this is to follow along with &lt;a class="link" href="https://twitter.com/TATTOOEDCRMGUY" target="_blank" rel="noopener"
>Chris Huntingford&lt;/a> &lt;a class="link" href="https://www.youtube.com/watch?v=lfGtjcxeKj4" target="_blank" rel="noopener"
>here&lt;/a>. I chose all apps, as usual, then launched the standard Sales Hub. Down the bottom right, is a new area Sales Insights Settings.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-SI-1.gif"
loading="lazy"
>&lt;/p>
&lt;h2 id="assistant-configuration">Assistant Configuration&lt;/h2>
&lt;p>The first free feature is Assistant. Clicking on the Manage link takes us to the Assistant Studio to manage the cards that are available to the end-user.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image.png?fit=1024%2C472&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>You are pretty limited to what you can do on this screen, as it is the Free version. All you can do is enable/disable specific cards &amp;amp; make them a high priority. Each card description is vague, but there is a reference from Microsoft &lt;a class="link" href="https://docs.microsoft.com/en-gb/dynamics365/ai/sales/action-cards-reference" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;p>For instance, I have enabled Recent Meeting and Recent Meeting (Exchange). I have then added a meeting both within D365 and within Outlook for Veronica Quek. When she opens her sales dashboard, she gets this view.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-2.png?fit=1024%2C374&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>This is different than the view if you have not got the 2020 Wave 1 functionality enabled.&lt;/p>
&lt;p>For the Reminder, as it is just passed, I get an option to add some notes or open the appointment.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-3.png"
loading="lazy"
>&lt;/p>
&lt;p>Also, clicking on the Assistant button top right gives a drop-down for the activities I have set up.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-SI-2.gif"
loading="lazy"
>&lt;/p>
&lt;p>You will notice that the user has the option to tell the AI whether the alert is useful or not, delay or cancel a notification. The valuable data is available to the administrator (and Microsoft) appearing alongside the detail of the card in the admin section.&lt;/p>
&lt;p>Some cards have options for the administrator to set, such as the Close date coming soon card. This allows an admin to specify how many days before a close date will the owner is notified via a card on the assistant.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-5.png"
loading="lazy"
>&lt;/p>
&lt;p>This pops up in the assistant like below.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-7.png"
loading="lazy"
>&lt;/p>
&lt;p>All these action cards are great to bring outstanding tasks or stuff to the attention of your salespeople. Some of them will be reliant on having a full license.&lt;/p>
&lt;h2 id="auto-capture-free">Auto capture (free)&lt;/h2>
&lt;p>The next free component of Sales Insights is Auto Capture. To enable this, you have to agree to the Terms of service, which will enable Auto capture.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-8.png"
loading="lazy"
>&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-10.png"
loading="lazy"
>&lt;/p>
&lt;p>Clicking on Manage opens the Auto Capture configuration.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-11.png?fit=1024%2C296&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>You can see that the Premium is now tantalising close, but let&amp;rsquo;s limit our selves to the free version. This requires Exchange Online sync set up and mailboxes configured. Plenty of articles out there stepping you through that. The insights from this don&amp;rsquo;t seem to come through straight away, I set up on a Friday and did not see any insights, by the Monday, it was all visible. Maybe that is just a glitch in the system, can not see any reference to this.&lt;/p>
&lt;p>I sent 2 emails to my demo account, from an email address already belonging to a contact in D365.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-12.png"
loading="lazy"
>&lt;/p>
&lt;p>These are emails I would expect a salesperson to action, the contact is explicitly asking for something related to a possible sale. In Sales Insights dashboard, there is a new notification.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-13.png"
loading="lazy"
>&lt;/p>
&lt;p>If I click on the first part, it opens a preview of the email where you can open the email direct in Outlook online.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-14.png"
loading="lazy"
>&lt;/p>
&lt;p>On the contact record you see the insights again and also the email that is untracked is highlighted. In the Timeline, the highlighted button allows you to track the email straight away without returning to Outlook.&lt;/p>
&lt;p>&lt;img src="https://i2.wp.com/linked365.blog/wp-content/uploads/2020/05/image-15.png?fit=1024%2C346&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>What cards appear depend on the insight cards you enable on the Assistant studio, discussed earlier. Anything that has a mention on your inbox is reliant on the auto-capture functionality being configured.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-16.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="email-engagement-free">Email Engagement (Free)&lt;/h2>
&lt;p>The final &amp;ldquo;free&amp;rdquo; Sales Insight is Email Engagement. Check the Microsoft page on it &lt;a class="link" href="https://docs.microsoft.com/en-gb/dynamics365/ai/sales/email-engagement" target="_blank" rel="noopener"
>here&lt;/a> for full details. This tool allows you to be notified when the recipient opens an email, tr&lt;/p>
&lt;p>Firstly, we need to grant permission by selecting the grant permission link in the Sales Insight Admin.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-17.png"
loading="lazy"
>&lt;/p>
&lt;p>This brings up the usual Permissions Requested approval box.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-18.png"
loading="lazy"
>&lt;/p>
&lt;p>Once accepted, you should be presented with this page.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-19.png"
loading="lazy"
>&lt;/p>
&lt;p>Now, back in the Sales Insights configuration page, the Email Engagement (free) has changed to a Set up link.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-20.png"
loading="lazy"
>&lt;/p>
&lt;p>Clicking on Set up presents you with a page where you enable the functionality.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-22.png"
loading="lazy"
>&lt;/p>
&lt;p>If you want to track attachment opening etc. you also need to configure OneDrive integration for your environment. In effect, any attachments are stored in OneDrive, and a link to that is sent to the user rather than the actual file. This allows the logging of attachment interactions. Navigate to &lt;a class="link" href="https://admin.powerplatform.com/" target="_blank" rel="noopener"
>admin.powerplatform.com&lt;/a>, open your environment and Settings. Click on Integration / Document Management Settings, which will open this page.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-25.png?fit=1024%2C314&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>To enable OneDrive, you need SharePoint enabled, so click on Enable Server-Based SharePoint Integration. Walkthrough the SharePoint Integration dialog, choosing a site to host your D365 files. Then click Enable OneDrive for Business back in the Document Management Settings page.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-26.png"
loading="lazy"
>&lt;/p>
&lt;p>When I did this, I came across the issue that I needed a default SharePoint Site, but to set the default you need to change a setting which is not on the form. Workaround &lt;a class="link" href="https://community.dynamics.com/crm/f/microsoft-dynamics-crm-forum/247524/how-to-set-sharepoint-site-as-default-yes-in-dynamics-365/1029478" target="_blank" rel="noopener"
>here&lt;/a>. Once that is done, you get a new part of the Document Management Settings.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-27.png?fit=1024%2C406&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>There is also a bit they don&amp;rsquo;t tell you about in the config, namely to enable Email as a document storage entity. If you go into SharePoint Document Locations under the Document Management Settings, you will be presented with this screen.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-31.png"
loading="lazy"
>&lt;/p>
&lt;p>Make sure Email is ticked (along with the others), enter a path to the SharePoint and select Next. I decided to link it back to the Account so selected that as a based on entity then hit Next again. After a little churning, this is the result.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-33.png"
loading="lazy"
>&lt;/p>
&lt;p>When you add an email now, you get a new tab (with the Enhanced Email Wave 1 enabled).&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-23.png"
loading="lazy"
>&lt;/p>
&lt;p>In the old way, you get a section available on the right&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-24.png"
loading="lazy"
>&lt;/p>
&lt;p>There are a few additional features enabled with this, firstly Recipient Activity&lt;/p>
&lt;h3 id="recipient-activity">Recipient Activity&lt;/h3>
&lt;p>To record email activity, a small 1-pixel gif is placed in the email as you send it. This will, when the email is read, notify you that the email has been read. You can toggle this on or off per email using the Do Not Follow functionality in the Email Engagement section. There is also an override per Contact in the contact preferences section.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-47.png"
loading="lazy"
>&lt;/p>
&lt;p>This is a snapshot of the HTML email that I sent, you can see the embedded gif which is a link to the Microsoft tracking site.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-28.png?fit=1024%2C168&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>In D365, a notification appears as a new Insight card against the contact and in the dashboard view. It also appears in the timeline for the contact that was sent the mail. The stats and alerts are not fool-proof, each email seems to be opened multiple times, which is not my interactions. I assume that this is due to various services such as spam filters etc. checking the links, but it does give you confidence that there has been an interaction of some sort.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-29.png?fit=1024%2C364&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;h3 id="attachment-activity">Attachment Activity&lt;/h3>
&lt;p>In addition to opening the email, you can also track them opening any attachments you send too. Firstly, you need to save the email before you can add attachments. Then add an attachment. You should get a new Follow button once you have added the attachment.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-34.png"
loading="lazy"
>&lt;/p>
&lt;p>Selecting the Follow button tags the attachment for following and it appear in the grid of attachments like below.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-35.png"
loading="lazy"
>&lt;/p>
&lt;p>Now, when the recipient receives the attachment, it is a link to the OneDrive file like below.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-36.png"
loading="lazy"
>&lt;/p>
&lt;p>Clicking on the link drives the recipient to a OneDrive page where they can download the file. Please note, that these files are not secured, you don&amp;rsquo;t need to log on to get at these files, only the link. It would be pretty random that you could determine the link, but it is just a warning. Normal sharing would be preferred for contracts etc. but it is great for marketing/sales documents.&lt;/p>
&lt;p>&lt;img src="https://i2.wp.com/linked365.blog/wp-content/uploads/2020/05/image-38.png?fit=1024%2C485&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;p>In D365, once the file is opened, you see a Sales Insights notification and if you open the email in D365, activity gets logged like below.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-39.png"
loading="lazy"
>&lt;/p>
&lt;p>The attachments are stored on the users OneDrive, which you can see below for Veronica&amp;rsquo;s OneDrive.&lt;/p>
&lt;p>&lt;img src="https://i0.wp.com/linked365.blog/wp-content/uploads/2020/05/SI-3.gif?fit=1024%2C628&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;h3 id="link-activity">Link Activity&lt;/h3>
&lt;p>Another feature in Email Engagement is link tracking. Any link you put into your email gets replaced with a link back to the D365 server. Each time the user clicks on the link, it is logged in D365, before the recipient is redirected to the original URL.&lt;/p>
&lt;p>For instance, if I link to my blog in an email&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-40.png"
loading="lazy"
>&lt;/p>
&lt;p>The recipient receives the email like below, but if you hover over the link it shows the full link that the user gets.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-41.png"
loading="lazy"
>&lt;/p>
&lt;p>If I click on the link, the user gets directed to my awesome blog. More importantly, the link tracking appears in D365.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-42.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="delayed-delivery">Delayed Delivery&lt;/h3>
&lt;p>When you send an email, with Email Engagement on, you can delay it. Click on Delay Send option presents you with this screen&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-43.png"
loading="lazy"
>&lt;/p>
&lt;p>Hit send this time does nothing, with D365 in the background sending the email out when the time arrives. A nice little feature to pre-plan engagements.&lt;/p>
&lt;h3 id="follow-up-reminder">Follow-up Reminder&lt;/h3>
&lt;p>Another nice little quality of life feature is the ability to add a follow-up reminder. This can be done at any time after the email has been sent.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-44.png"
loading="lazy"
>&lt;/p>
&lt;p>You can choose the condition and the time frame as well as a comment. This appears as an Assistant card once the date has reached.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/05-image-45.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="email-templates">Email Templates&lt;/h3>
&lt;p>Another feature enhanced with Email Engagement is templates. You can select templates by selecting Insert Template in the Email form. As you build up tracking on these emails and they are interacted with, statistics are built upon the suitability of each template - which ones ended up with an email that was opened for example.&lt;/p>
&lt;p>&lt;img src="https://i1.wp.com/linked365.blog/wp-content/uploads/2020/05/image-46.png?fit=1024%2C404&amp;amp;ssl=1"
loading="lazy"
>&lt;/p>
&lt;h2 id="next-time">Next time&lt;/h2>
&lt;p>As you can see this set of tools, including in the subscription cost of a Sales license is pretty cool. In my next post I will delve deeper into the premium features.&lt;/p></description></item><item><title>Scottish Summit - A Review</title><link>https://linked365.blog/2020/03/07/scottish-summit-a-review/</link><pubDate>Sat, 07 Mar 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/03/07/scottish-summit-a-review/</guid><description>&lt;img src="https://linked365.blog/images/2020/03-whatsapp-image-2020-03-01-at-22.44.28-1.jpeg" alt="Featured image of post Scottish Summit - A Review" />&lt;p>The extra day a year only comes around every 4 years and it seemed appropriate that a lot of the Power Platform community came together to celebrate in Glasgow.&lt;/p>
&lt;p>Scottish Summit 2020 was sponsored by Avanade and myself and several colleagues went along to enjoy the event, cement Avanade in the community, share our knowledge and learn from others.&lt;/p>
&lt;p>With over 1000 people descending on the University of Strathclyde’s Technology and Innovation Centre, this event is one of the biggest, free, community organised events in Europe. Our hosts, Iain Connolly and Mark Christie have worked hard to promote the event and established it quickly as the place to be for D365 / Azure / Office users and partners to be.&lt;/p>
&lt;h2 id="first-day--common-data-service-hack">&lt;strong>First Day – Common Data Service Hack&lt;/strong>&lt;/h2>
&lt;p>My first day at the conference was participating in the CDS Hackathon. Chris Huntingford and Lucy Bourne from Microsoft introduced us to the requirements for the hack and 20 of us spent the day being creative in groups to resolve an environmental challenge. Our group decided to tackle our carbon footprint, highlighting how our day-to-day choices can have an impact on the environment.&lt;/p>
&lt;p>Combining a Forms Pro questionnaire, a Power App for the collation of data by council employees, a Modal driven app to maintain the questions and Power BI to visualise it, we produced a solution that would be ready for use within 3 hours! This shows the power of the Low code capabilities of the Power Platform and teamwork!&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/03-whatsapp-image-2020-03-04-at-11.21.54.jpeg?w=1024"
loading="lazy"
>&lt;/p>
&lt;p>Thanks to &lt;a class="link" href="https://twitter.com/LeeMBaker" target="_blank" rel="noopener"
>@LeeMBaker&lt;/a> for the photo&lt;/p>
&lt;p>On Friday evening I managed to catch up with a lot of the Microsoft team attending the event, discussing the partner landscape, challenges they are seeing and how we can work with them to overcome these challenges.&lt;/p>
&lt;h2 id="scottish-summit-saturday">&lt;strong>Scottish Summit Saturday&lt;/strong>&lt;/h2>
&lt;p>On Saturday, after an early start, we set out our stall. Avanade was showcasing our capabilities to the attendees with D365, across Customer Engagement and Finance and Operations. Mixed Reality has become a big topic within the community, and we were lucky to be able to showcase a HoloLens 2. This was a big crowd-pleaser, with a lot of attendees experiencing this technology for the first time.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;img src="https://linked365.blog/images/2020/03-whatsapp-image-2020-03-01-at-22.44.28-1.jpeg?w=768"
loading="lazy"
>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;img src="https://linked365.blog/images/2020/03-whatsapp-image-2020-02-29-at-12.57.12-1.jpeg?w=1024"
loading="lazy"
>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;img src="https://linked365.blog/images/2020/03-whatsapp-image-2020-02-29-at-12.52.50.jpeg?w=768"
loading="lazy"
>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Explaining how Mixed Reality can be used for training, 3rd line support or visualisations of products in your environments was an eyeopener to a lot of people and it was great to showcase Avanade&amp;rsquo;s capability and some customer successes.&lt;/p>
&lt;h2 id="keynote--this-is-more-than-just-technology">&lt;strong>Keynote – This is more than just technology…..&lt;/strong>&lt;/h2>
&lt;p>What a start! Jon Levesque, Senior Platform Evangelist for the Power Platform at Microsoft was piped into the main hall, with a kilt on to celebrate our location.&lt;/p>
&lt;p>&lt;img src="https://pbs.twimg.com/media/ER7p32BXUAAApQS?format=jpg&amp;amp;name=medium"
loading="lazy"
alt="Image"
>&lt;/p>
&lt;p>Photo courtesy of &lt;a class="link" href="https://twitter.com/marijnsomers" target="_blank" rel="noopener"
>@MarijnSomers&lt;/a> (corrected)&lt;/p>
&lt;p>He started with his personal journey, starting from being a member of the team that supported Steve Ballmer when he was giving talks across the world to his role now, where he is paid to fly around the world and evangelise on the Power Platform.&lt;/p>
&lt;p>Jon gave pertinent stories about how the Power Platform has changed people and businesses across the world, empowering people in their day jobs to think about creating solutions to benefit their role.&lt;/p>
&lt;p>His enthusiasm for the community and how it impacts the lives of everyone was infectious. Everyone left with a sense of belonging and enthusiasm to develop themselves and their businesses to the next level&lt;/p>
&lt;p>Throughout the day, there were various sessions that we attended to educate ourselves.&lt;/p>
&lt;h2 id="session-1---to-code-or-not-to-code---that-is-the-question">&lt;strong>Session 1 - To Code or not to Code - That is the Question&lt;/strong>&lt;/h2>
&lt;p>My first session was given by Scott Durow and Sara Lagerquist, both Microsoft Valued Professionals and at the top of their game. Their talk was about the perceived battlegrounds that have been drawn between LowCode and Pro-Dev practitioners.&lt;/p>
&lt;p>Sara argued that Low-code, via Power Apps, Power Automate and the other numerous members of the Power Platform are allowing for a more reactive and time frames for users to achieve the solutions they need in their businesses. She highlighted that coding can lead to technical debt, development bottlenecks and reduced user adoption.&lt;/p>
&lt;p>Scott countered these arguments by highlighting that bad solutions can come from low-code or pro dev equally, and each has its place in bring solutions to live. Gone are the days when grumpy developers can hold BAs and functional consultants hostage with their use of technical terms&lt;/p>
&lt;p>But the outcome of their presentation was showing that we need to remove the barriers. Technical and functional need to co-exist and work with each other to use the right technology for the problem. Low code has great use cases to empower individuals to expand their applications across data silos, but if you want a speedy integration would Power Automate fit the bill? Encouraging Functional and Technical consultants to have conversations early on in a project and recognising the diversity of their skill sets would lead to increased user adoption and improved solutions.&lt;/p>
&lt;h2 id="session-2---mixed-reality---extending-d365-on-the-next-frontier">&lt;strong>Session 2 - Mixed Reality - Extending D365 on the next frontier&lt;/strong>&lt;/h2>
&lt;p>Kyle Hill, one of Avanade’s MVP hosted a session on Mixed Reality. He used the session to show the capabilities of Microsoft’s HoloLens 2 and how it empowers everyone within a business. From architectural uses – walking through a floor plan to first-line service staff - providing visual clues to while they are resolving a problem on customer site.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;img src="https://linked365.blog/images/2020/03-whatsapp-image-2020-02-29-at-12.52.49.jpeg?w=1024"
loading="lazy"
>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;img src="https://linked365.blog/images/2020/03-whatsapp-image-2020-02-29-at-12.24.48-1.jpeg?w=1024"
loading="lazy"
>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;img src="https://linked365.blog/images/2020/03-whatsapp-image-2020-02-29-at-12.24.48.jpeg?w=1024"
loading="lazy"
>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>He also walked through how a low-code approach can be taken to augment the view of a user and the tools Microsoft provides to create this content.&lt;/p>
&lt;p>It was a great show of how this emerging technology will soon be as widespread as mobile phones, available to all at a price point to match. I love the fact that Avanade is at the front of this adoption and are bringing this technology to businesses of all scales to change their approach to solving problems and transforming their processes.&lt;/p>
&lt;h2 id="session-3---top-20-tips-for-surviving-networking-at-events">&lt;strong>Session 3 - Top 20 Tips for Surviving Networking at Events&lt;/strong>&lt;/h2>
&lt;p>Not every session is a technical one, Lucy Bourne, another Microsoft employee delivered a great session on how individuals can address their anxieties to better involve them in our community. In any community, when you begin, it is a room of strangers and lots of people are anxious about reaching out and getting involved.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/03-er9io5ux0aejlcl-scaled.jpg?w=1024"
loading="lazy"
>&lt;/p>
&lt;p>Photo courtesy of &lt;a class="link" href="https://twitter.com/D365Geek" target="_blank" rel="noopener"
>@D365Geek&lt;/a>&lt;/p>
&lt;p>Lucy gave a whistle-stop guide to her 20 tips to survive these moments, gain confidence in your interactions and get involved. She highlighted that everyone has the same fears, everyone thinks they are an imposter at times and every one is unique. If you be yourself, “celebrate your onlyness”, as she puts it, and be genuine, then you can address your fears and become part of the big family we have as a community.&lt;/p>
&lt;h2 id="session-4--powerapps--a-thunderbolt-of-functional-awesome">&lt;strong>Session 4 – PowerApps – A Thunderbolt of Functional Awesome&lt;/strong>&lt;/h2>
&lt;p>To round out my day, I went to see Chris Huntingford, a Microsoft Partner Technical Architect show his audience how quick and easy it is to create a production application using low-code techniques and the tools make available to us via the Power Platform.&lt;/p>
&lt;p>He explained the benefits and fundamentals of the Power Platform and how we should be engaging with it as users, empowering businesses to democratise their data. He further made it clear that there is only a limited pool of developers, but if we encourage our business users to make edge apps with the data that is available to them, companies can save time and money.&lt;/p>
&lt;p>Towards the end of the session, he built an application within minutes, truly showing the flexibility of the platform.&lt;/p>
&lt;h2 id="in-conclusion">&lt;strong>In conclusion&lt;/strong>&lt;/h2>
&lt;p>Scottish Summit was a great event, it highlighted the great community we have. With speakers coming from Australia, America and all over Europe, it is an event that has started to become a must for anyone involved in the Microsoft stack.&lt;/p></description></item><item><title>3 Minute Feature : Episode 9 : Dashboards</title><link>https://linked365.blog/2020/03/05/3-minute-feature-episode-9-dashboards/</link><pubDate>Thu, 05 Mar 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/03/05/3-minute-feature-episode-9-dashboards/</guid><description>&lt;p>A common staple of the Model driven app experience, my 9th video runs you through creating single and multi stream dashboards&lt;/p>
&lt;h2 id="episode-9--dashboards">Episode 9 : Dashboards&lt;/h2>
&lt;div class="video-wrapper">
&lt;iframe loading="lazy"
src="https://www.youtube.com/embed/gmLIvkGkNQM"
allowfullscreen
title="YouTube Video"
>
&lt;/iframe>
&lt;/div>
&lt;h2 id="transcript">Transcript&lt;/h2>
&lt;p>Dashboards have 2 variants, those that are connected to an entity and those that are not. An entity dashboard, called Single Stream previouly, are designed for support desk users or similarly focused indviduals.  The multii stream dashboards are for more typical dashboard requirements, displaying MI for your users.&lt;/p>
&lt;p>For an entity dashboard,  you need to start from an entity.&lt;/p>
&lt;p>Use Entity, Dashboard, add dashboard, select one of the overview types, I have gone for 3 column overview, varied width.&lt;/p>
&lt;p>You are presented with the dashboard edit screen. Give it a name and a view to use with the dashboard, remember this is for a single entity.&lt;/p>
&lt;p>In the 3 panels at the top you can add 3 charts of your choice, from those available against that entity, and only system charts.&lt;/p>
&lt;p>The stream is meant to be a focus area for a list of records to be displayed. Select a view, again for the same entity.&lt;/p>
&lt;p>Select Save and close. In the user interface, if you got to the entity in question and select Dashboards, the new dashboard should be visible. It stats with the visual filter not displayed. This is the 3 charts we put in.&lt;/p>
&lt;p>If you select any of the charts and drill down, the data in the other charts and the feed is filtered as well&lt;/p>
&lt;p>In the top right of the dashbaord you can also alter the timeframe resulting in the records being redisplayed.&lt;/p>
&lt;p>For the multi-stream dashboards, add a new dashboard direct from the solution. Here I chose a 3 column dashboard. The same editor appears. You can add components such as Charts, views web resources and even a timeline control. To make room for it, I will delete the 2 spots to the right, the add a timeline control. I can also then expand to fill the whole of the right of the frame.&lt;/p>
&lt;p>Again save and close, to return to the solution view and ensure you publish all customisations.&lt;/p>
&lt;p>In the user interface, our new dashboard is now available. The timeline fills out the far side and our other components are visible&lt;/p>
&lt;p> Like with Views, you can also create your own dashboards. Similarly, if you want to restrict the access to Dashboards, you need to do it with a personal dashboard and share it to restict the useage to a particular user group. All System dashboards are available to all users who have the application where the dashboard is configured.&lt;/p>
&lt;p>Here I create a copy of my dashboard and then I am able to share it. I go into the dashboard and remove the pane for an account listing. Hitting save shows you my new, personal version of the dashboard.&lt;/p>
&lt;p>When using Personal dashboards, ensure the users you share with also have access to any personal views or charts you add to your dashboard&lt;/p></description></item><item><title>3 Minute Feature : Episode 8 : Charts</title><link>https://linked365.blog/2020/02/27/3-minute-feature-episode-8-charts/</link><pubDate>Thu, 27 Feb 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/02/27/3-minute-feature-episode-8-charts/</guid><description>&lt;p>Charts in a model app are a great tool for customisers to visualise data&lt;/p>
&lt;h2 id="episode-8--charts">Episode 8 : Charts&lt;/h2>
&lt;div class="video-wrapper">
&lt;iframe loading="lazy"
src="https://www.youtube.com/embed/9z1LLflHro8"
allowfullscreen
title="YouTube Video"
>
&lt;/iframe>
&lt;/div>
&lt;h2 id="transcript">Transcript&lt;/h2>
&lt;p>Charts in D365 allow a visualisation of the data from a view. We discussed views earlier in the series so won&amp;rsquo;t go into that.&lt;/p>
&lt;p>Starting at the Entity in your solution, you navigate to charts, select Add Chart&lt;/p>
&lt;p>The new chart display comes up&lt;/p>
&lt;p>We will begin with a simple column chart.&lt;/p>
&lt;p>Select a Legend Entries, this is the column that will be counted or summed etc, giving you your Y axis&lt;/p>
&lt;p>Next, select the series entries. This gives you your x axis bands. If you choose a date field, you can define the date period.&lt;/p>
&lt;p>Now hit save and close.&lt;/p>
&lt;p>The chart appears in the solution&lt;/p>
&lt;p>Over in the user interface, if you select the entities and views, you will have an option to display a chart. This allows the current view to be displayed in the chart you select, getting you this visualisation&lt;/p>
&lt;p>Here, you can see the chart we defined has been brought through.&lt;/p>
&lt;p>If you select or one or the bars in the chart, the view gets filtered by the selected data and it also allows you to drill down the data, dividing the data into other categories.&lt;/p>
&lt;p>This chart is a system chart. System charts can be part of your solution, being able to move between environments, but you will not be able to &amp;ldquo;secure&amp;rdquo; them. Either everyone sees the chart of no one does.&lt;/p>
&lt;p>If you want to only share certain charts with certain groups of users, you should be using user charts. It also allows me to show you the other visualisations easier.&lt;/p>
&lt;p>On the chart, if I select New, I will be creating a new user view, only initially shared with my user. The same interface appears allowing you to define the chart.&lt;/p>
&lt;p>I have given this a separate name, hit save and close&lt;/p>
&lt;p>Back in the user interface, on hard refresh, the new chart appears. Also, on the chart, I have the ability to share. Here I can share with other users or teams of users.&lt;/p>
&lt;p>Using account, as there is more data, I will run through the options available to you. Firstly, I make a copy of the out of the box Account By Industry then select edit.&lt;/p>
&lt;p>This chart starts off as a bar chart, firstly switch to a column chart. Next we can add a field to the series to show a max number of employees in each sector.&lt;/p>
&lt;p>You can only have mor e than one series or legend entry, not both at one time. So next I remove the number of employees and add a second series for country region&lt;/p>
&lt;p>You can see now that the bars are split up by country then industry. Swappng the series over, allows you to imagine the data in a different way&lt;/p>
&lt;p>Lets looked at the other options, Stacked Bar or Column is great for you to show percentage data, but only works if the totals are roughly the same.&lt;/p>
&lt;p>Areas have a different visualisation, good for time line data to show increases.&lt;/p>
&lt;p>Line does nto have the overlap like area, again great to show variation in time.&lt;/p>
&lt;p>You will notice that I can not choose the other types. This is because I have more than one series or legend displayed. These visualisations rely on 2 dimensional data only.&lt;/p>
&lt;p>I remove the series for country to show these other options and select a simple Pie chart. This chart has a high number of records that are redundant, no industry, so it may be worth fitlering using a different view, or fixing the data.&lt;/p>
&lt;p>Funnel charts are really useful to show progress through a sales cycle, changing the size of the segment depending on the count of records.&lt;/p>
&lt;p>Tags display a list of the fields in the category &amp;amp; a count. Great for quickly visualising other data for filtering.&lt;/p>
&lt;p>And finally donuts are another visualisation&lt;/p>
&lt;p>This works well with small sets of types.&lt;/p>
&lt;p>To limit data, either use a different view or you can grab the top or bottom number of records from the view. Here I limit to the top 3 types displayed, hence our visualisation is a lot more appealing&lt;/p></description></item><item><title>3 Minute Features : Episode 7 : Forms Pt2</title><link>https://linked365.blog/2020/02/20/3-minute-features-episode-7-forms-pt2/</link><pubDate>Thu, 20 Feb 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/02/20/3-minute-features-episode-7-forms-pt2/</guid><description>&lt;p>This is the second part of the Forms feature, highlighting some useful tips &amp;amp; where to start when Business rules is not enough.&lt;/p>
&lt;h2 id="episode-7-forms-pt2">Episode 7: Forms Pt2&lt;/h2>
&lt;div class="video-wrapper">
&lt;iframe loading="lazy"
src="https://www.youtube.com/embed/DIqKBoJkbGs"
allowfullscreen
title="YouTube Video"
>
&lt;/iframe>
&lt;/div>
&lt;h2 id="transcript">Transcript&lt;/h2>
&lt;p>With forms, if business rules don&amp;rsquo;t meet your requirements, you may have to resort to Javascript. These little code snippets allow you to do pretty much anything on a form that is not possible in business rules, but be warned, Javascript nowadays is frowned upon. It is code for a start, so you need a skilled professional to create and maintain it. Use it as a last resort.&lt;/p>
&lt;p>Each form has a library of files you can upload to it, each file containing one or more functions. Each function needs to be associated with an event, such as the load event of the form or a change event for a field.&lt;/p>
&lt;p>You can also establish form parameters, which can be used by your scripts. Say you want to ensure only if the user comes from another form, you can use this to pass history from the other form.&lt;/p>
&lt;p>Non-event dependencies are a list of fields that are required by scripts. Adding a field to the list locks it to the form.&lt;/p>
&lt;p>Back in the maker experience, there are few nice functions to make your life as a designer easier.&lt;/p>
&lt;p>In the bottom left is a selection which allows you to visualise how your form will look at certain aspect ratios. As this is the new world of unified interface, this form will be rendered on a phone or tablet as well as a desktop. Here, as the form size is changed, the header section is displayed as the first section. Phone is also the size used for the outlook client.&lt;/p>
&lt;p>Header can also be altered, fields added. As you add more than 4 fields, you get a prompt, letting you know that this new field won&amp;rsquo;t be directly visible on the form, but part of the flyout only. Opening the app, you can see this.&lt;/p>
&lt;p>The default option is high density, as we just saw, but you can also choose to untick this to go back to the previous way. This means the fields are editable in the header, but take up more space. Depends on what you want to achieve in your layout. As you can see, as I was in responsive mode, the header gets shifted to the first section of the first tab&lt;/p>
&lt;p>In the user experience, now that we are not in high density mode, the fields in the header are editable directly, with the 5th field being available and editable in the drop down&lt;/p>
&lt;p>There are 4 types of form you can create. We have mostly been working with Main forms, the default wide forms which we are used to.&lt;/p>
&lt;p>Quick view forms are those to show data from a parent entity.&lt;/p>
&lt;p>We can also have Card forms, which appear when the user is displaying a list as a series of cards. Generally, if there is not enough space to render a list properly, the UI will shift to display it as a card view.&lt;/p>
&lt;p>To show this, on the account form, I add a quick view form to the form, choose the related entity and the form to display.&lt;/p>
&lt;p>Also, we can add a new grid to show off the card view. This, as there is little space in the thin column, uses the card view form.&lt;/p>
&lt;p>Quick Create is a form which you first have to enable on the entity by editing the properties of the entity.&lt;/p>
&lt;p>Once enabled, you can create a quick create form, add some fields to it and save.&lt;/p>
&lt;p>When you select quick create on a grid now, it will display a form to the right of the main form, allowing you to quickly add information, and automatically link the new record to the main entity&lt;/p></description></item><item><title>2020 Release Wave 1 : Kanban board</title><link>https://linked365.blog/2020/02/16/2020-release-wave-1-kanban-board/</link><pubDate>Sun, 16 Feb 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/02/16/2020-release-wave-1-kanban-board/</guid><description>&lt;img src="https://linked365.blog/images/2020/02-image-6.png" alt="Featured image of post 2020 Release Wave 1 : Kanban board" />&lt;p>On 3rd February, early access to the Kanban board for Opportunities was made available, and as an avid user of Kanban like boards, I thought I would give it a spin. Kanban is a method of visualising and planning activities by their status. In the standard model app you can apply a process to any record, having a step by step guide to your business process.&lt;/p>
&lt;h3 id="update">UPDATE&lt;/h3>
&lt;p>I have been playing with this further, and it seems that there is a large caveat around the process that the Kanban uses, details at the end&lt;/p>
&lt;h2 id="enabling-the-wave-1-early-access">Enabling the Wave 1 Early Access&lt;/h2>
&lt;p>Goto &lt;a class="link" href="https://admin.powerplatform.microsoft.com/support" target="_blank" rel="noopener"
>https://admin.powerplatform.microsoft.com/&lt;/a>, Environments, choose your environment&lt;/p>
&lt;p>On the right hand side, there is now an option to Enable the 2020 Wave 1 Early Access. Here, you can see that I have enabled mine&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/02-image.png?w=1024"
loading="lazy"
>&lt;/p>
&lt;h2 id="enable-kanban-on-opportunity">Enable Kanban on Opportunity&lt;/h2>
&lt;p>The Microsoft documentation &lt;a class="link" href="https://docs.microsoft.com/en-us/dynamics365/sales-enterprise/add-kanban-control" target="_blank" rel="noopener"
>here&lt;/a> walks you through the steps. For a new feature, having to resort to using the classic customisation interface is something that goes against the grain.&lt;/p>
&lt;p>Open make.powerapps.com, select Advanced Settings from the cog top right&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/02-image-1.png?w=396"
loading="lazy"
>&lt;/p>
&lt;p>This opens the classic interface where you need to go to Settings \ Customise \ Customise the system. You should add this to a solution obviously, but just for PoC.&lt;/p>
&lt;p>Scroll down the entities until you find Opportunity, and select it. The third tab lists the controls that are available to the Opportunity.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/02-image-2.png?w=809"
loading="lazy"
>&lt;/p>
&lt;p>Select Add Control then scroll down to Kanban, select it then hit Add.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/02-image-3.png?w=767"
loading="lazy"
>&lt;/p>
&lt;p>You will then hit Save and Publish.&lt;/p>
&lt;h2 id="displaying-the-kanban-board">Displaying the Kanban board&lt;/h2>
&lt;p>Once this is done, open up the Sales app. Select a view of opportunities. In the top right, select the 3 dots then Show As and choose Kanban.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/02-image-5.png?w=381"
loading="lazy"
>&lt;/p>
&lt;p>Once this is done, your Sales process is displayed as columns with each opportunity listed&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2020/02-image-6.png?w=1024"
loading="lazy"
>&lt;/p>
&lt;p>Each column has a count of the number of records and a sum of the estimated revenue for all the records at the status.&lt;/p>
&lt;p>You can search the opportunities like any other view and also change it to display the opportunities by status.&lt;/p>
&lt;p>The 3 fields on each record can be edited on this screen, allowing for quick editing of the key fields. You can drill down into each record which pops the main form into view.&lt;/p>
&lt;p>Each opportunity can be dragged between columns. This triggers the display of the record for you to choose the next stage.&lt;/p>
&lt;h2 id="thoughts">Thoughts&lt;/h2>
&lt;p>It is a great feature that will be handy for teams to quickly see the state of opportunities.&lt;/p>
&lt;p>It is let down by not being able to customise the card display, well I couldn&amp;rsquo;t work it out. You are limited to the owner, estimated revenue and estimated close date. I can understand limiting you to 3 fields, but a customiser should be able to choose. I would assume a card form should be tied to this.&lt;/p>
&lt;p>Also, when you drag and drop, even if you have the required fields, the record is displayed. Not really that quick. I would think that if no fields are required for a particular stage change, it should just happen. A bit fiddly.&lt;/p>
&lt;p>Finally, the adherence to your process is excellent. I added a step to my sales process and it just re-displayed the Kanban board. No effort.&lt;/p>
&lt;p>I am sure this feature will be improved over time, and will be great for those companies that don&amp;rsquo;t customise away from the Microsoft sales process too much.&lt;/p>
&lt;h2 id="default-process-only">Default Process only&lt;/h2>
&lt;p>After working with a client on demoing this in their environment, it became obvious that there is a fundamental caveat with using the Kanban feature.&lt;/p>
&lt;p>If you don&amp;rsquo;t use the standard Opportunity Sales Process, don&amp;rsquo;t expect any use out of the new feature as it stands currently. Only the default process is used.&lt;/p>
&lt;p>I created an idea here &lt;a class="link" href="https://experience.dynamics.com/ideas/idea/?ideaid=2548d535-b154-ea11-b698-0003ff68c1c4" target="_blank" rel="noopener"
>https://experience.dynamics.com/ideas/idea/?ideaid=2548d535-b154-ea11-b698-0003ff68c1c4&lt;/a>&lt;/p></description></item><item><title>3 Minute Features : Episode 6 : Forms Pt1</title><link>https://linked365.blog/2020/02/13/3-minute-features-episode-6-forms-pt1/</link><pubDate>Thu, 13 Feb 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/02/13/3-minute-features-episode-6-forms-pt1/</guid><description>&lt;p>There is a lot you can do with forms in the Modal driven app, so this topic is split into two&lt;/p>
&lt;h2 id="episode-6-forms-pt-1">Episode 6: Forms Pt 1&lt;/h2>
&lt;div class="video-wrapper">
&lt;iframe loading="lazy"
src="https://www.youtube.com/embed/LFajN4gVfno"
allowfullscreen
title="YouTube Video"
>
&lt;/iframe>
&lt;/div>
&lt;h2 id="transcript">Transcript&lt;/h2>
&lt;p>In the solution, select our entity, then forms&lt;/p>
&lt;p>Select the main form. Once the form opens, you can see the fields I have already added.&lt;/p>
&lt;p>I am going to a new tab, then add sections. Sections allow you to add controls linked to the primary record. Each section can have upto 4 columns to display your fields.&lt;/p>
&lt;p>As you drag fields onto the segment, the form renders for you.&lt;/p>
&lt;p>Another form control is the subgrid. A subgrid allows you to display a grid of records, either assocaitated with the main record or defined by a view. If you want to display contacts associated with an account, this is where you would do it.&lt;/p>
&lt;p>Quick View allows you to display the quick form displayed for a parent entity. Approver is a user record and is a parent of our entity. This allows quick display of important data from the parent. The form you choose is defined as any other form, just a special type.&lt;/p>
&lt;p>Depending on the field you add to the form, you can change the control that is used. There are a few controls that Microsoft provide out of the box. Here I have added a numeric field to the form. Under components, you can change the default component to a selection, depending on your business needs.&lt;/p>
&lt;p>Each component will have properties for you to set and configure the interaction. There are a growing number of controls available to you, google pcf gallery.&lt;/p>
&lt;p>Don’t forget about your header and footer as well, drag fields into them. The header tends to be critical information that you can alter, owner status reason etc.&lt;/p>
&lt;p>The footer tends to be more audit information, the current status, who last edited or create the record for example, but this will depend on your requirements.&lt;/p>
&lt;p>Switching to the form we created, you can see the Arc Knob we selected, allows us to point or drag the data entry&lt;/p>
&lt;p>In the new tab we created, you can see the fields that have been rendered. You can also see the subgrid that was added, giving the user the ability to create a new contact or associate this record with an existing record. Hit save and you can confirm that the grid now displays the newly linked record.&lt;/p>
&lt;p> If you noticed on our main tab, there was a large control displaying notes and activities. This is a special section that is really useful and common in D365. To utilise it on your entity, we first have to enable your entity for activities. This is not currently available within the maker experience, so as a customiser, go back to the old method of editing apps and switch to the classic interface&lt;/p>
&lt;p>Select the  Activities check box, which enables your entity to have all the activity types associated with it. Save and close to update the entity.&lt;/p>
&lt;p>If you go to the form now, you will not notice any difference, as again this is a Classic interface only feature currently.&lt;/p>
&lt;p>Opening ithe form in classic mode allows the activity section to be tweaked. You can show Notes or activities or both and a host of additional options including whether to show the filter pane or not.&lt;/p>
&lt;p>Under the activities tab you can select which activity types are visible and which field to sort on. You can also define options to tweak what is displayed to the user and how the user interacts with the form.&lt;/p>
&lt;p>So publishing our form and displaying the content you can see that the user can quickly add a phone call or other activity tab to the entity. This displays in the timeline. Notes can be added straight in the grid. This is also where attachments can be uploaded .&lt;/p></description></item><item><title>3 Minute Features : Episode 5 : Views</title><link>https://linked365.blog/2020/02/06/3-minute-features-episode-5-views/</link><pubDate>Thu, 06 Feb 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/02/06/3-minute-features-episode-5-views/</guid><description>&lt;p>In the fifth installment of this series, I look at views. How to design them and where they are used.&lt;/p>
&lt;h2 id="episode-5-views">Episode 5: Views&lt;/h2>
&lt;div class="video-wrapper">
&lt;iframe loading="lazy"
src="https://www.youtube.com/embed/K6wIdnxP_vs"
allowfullscreen
title="YouTube Video"
>
&lt;/iframe>
&lt;/div>
&lt;h2 id="transcript">Transcript&lt;/h2>
&lt;p>Starting on the entity, go to Views&lt;/p>
&lt;p>This lists all the system views that are associated with our entity. These are generated when you create an entity. Some of them are normal, views that represent data to the user when they view lists. Some have special uses, which I will go through at the end&lt;/p>
&lt;p>Lets start with a new view&lt;/p>
&lt;p>Give your view a name, meaningful for what it will be doing, hit create&lt;/p>
&lt;p>As you can see, it now displays the defualt field of your entity, name. It is also showing you data from your live system, so you can tell if you need to adjust layout to fit your data&lt;/p>
&lt;p>Some fields, the ones that are added by the system, are hidden, so change the selection to All. Then, it is as simple as drag and drop to add a field to the view.&lt;/p>
&lt;p>You can use the drop down on each field to change the width, or drag the handles. You can also drag and drop to change the order. Delete the column by the drop down.&lt;/p>
&lt;p>On the right or on the field, you can define the sorting. This changes the sorting by first ascending then descending if you repeat the action. The sorting is only by fields visible in the view. You can add further sort criteria as well.&lt;/p>
&lt;p>Filtering of the view is fundamental. Select Edit Filters. I want to show only my approvals, then add row. This is a simple field chosen on the entity at the moment. Select the field, then the condition. There are some special ones when working with user records to define it as the current user&lt;/p>
&lt;p>Hit Ok. Notice that the displayed list is filtered straight away, helping you to quickly visualise what it will look like. Back in filters, we can do lots of more advanced filtering, such as filtering on a parent or child entity. We can also group conditions to allow for complicated expressions using Or and And parts.&lt;/p>
&lt;p>Once we are happy, hit save, then publish so we can check it out in our app&lt;/p>
&lt;p>When we got to My Things now, in the view drop down, there is a new selection&lt;/p>
&lt;p>I can chose this and get my filtered list. The end user can add additional filtering as needed or resize columns, but the fundamental filter is kept.&lt;/p>
&lt;p>Back to our maker experience, to add a field from a parent entity, by selecting related. Here I add the primary email of the approver to the view, which allows me to see parent information on the child record. Just that, no child information or many to many information is available.&lt;/p>
&lt;p>Just to show you the lookup view, I connected account to My thing via a relationship. On the account form, the list of fields displayed when selecting my thing is defined as the lookup view.&lt;/p>
&lt;p>Quick view and advanced find are the views used for those particularly capabilities in the app. Feel free, and you should, update these to your business needs.&lt;/p>
&lt;p>Users can also make their own views (subject to permission), by selecting Create View in any view. Their interface is not as pretty as the maker experience, but would assume this is coming.&lt;/p>
&lt;p>They can base the view on an existing view. Then ammend a filter. Hit save, give it a name and close.&lt;/p>
&lt;p>This new view is available under the drop down under My Views.&lt;/p>
&lt;p>If you go back to Create Views, under saved views, select the view you just created and you can hit Share, which allows you to share the view with a colleague or team of colleagues. You can also allow them to edit this view.&lt;/p></description></item><item><title>3 Minute Features : Episode 4 : Business Rules</title><link>https://linked365.blog/2020/01/30/3-minute-features-episode-4-business-rules/</link><pubDate>Thu, 30 Jan 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/01/30/3-minute-features-episode-4-business-rules/</guid><description>&lt;p>Wearing ties is a rule that is just bonkers, and not allowing working from home. Thankfully those in CDS are a little more understandable.&lt;/p>
&lt;p>Welcome to the 4th video in the 3 minute feature series, on Business Rules&lt;/p>
&lt;h2 id="episode-4--business-rules">Episode 4 : Business Rules&lt;/h2>
&lt;div class="video-wrapper">
&lt;iframe loading="lazy"
src="https://www.youtube.com/embed/HNFvild4WUw"
allowfullscreen
title="YouTube Video"
>
&lt;/iframe>
&lt;/div>
&lt;h2 id="transcript">Transcript&lt;/h2>
&lt;p>Starting from the Entity, select Business Rules, Add Business Rule&lt;/p>
&lt;p>At the top is some tools which we will use later&lt;/p>
&lt;p>The first part is a condition, what combination of fields will make the rule trigger. This can be a combination of fields, either both values or one or more of the values&lt;/p>
&lt;p>In my scenario, I am going to worry about the status reason for my thing, mimicking an approval process. So, firstly, is the status reason waiting approval?&lt;/p>
&lt;p>Then our first action. I want to make the Approver field business required, forcing the user to enter a value.&lt;/p>
&lt;p>Next, make the default value of the log field Waiting for approval. Setting values is very limited, you might want a timestamp here, but this is not possible in a rule.&lt;/p>
&lt;p>Next, the 2 approval fields need to be visible, allowing my user to enter the values&lt;/p>
&lt;p>Now I have achieved everything I wanted on this condition, lets move to th e next condition. If it is not &amp;ldquo;waiting approval&amp;rdquo;, check to see if it is approved&lt;/p>
&lt;p>Add a condition to the negative side of the first condition, select eh status reason &amp;amp; a different value&lt;/p>
&lt;p>This time, we want to still ensure the approver and the log are visible, but lock them both, stopping once it is approved anyone changing the value&lt;/p>
&lt;p>But what would happen if the status reason was switched back to waiting approval from approved? The first condition path does not unlock the fields, assumes they are already unlocked. This should be fixed. The business rule editor allows you to copy actions and conditions. Click on the action, select copy.&lt;/p>
&lt;p>The select paste. The rule editor then asks you where to paste it to. Select the + where you want it.&lt;/p>
&lt;p>We want an unlock rather than a lock, so swap over the action.&lt;/p>
&lt;p>Repeat for the log as well.&lt;/p>
&lt;p>We can use this techique to cover all the basis, or the default condition, where it isnt Awaiting approval or approved. Copy the Set Business Required, past on the negative condition. Rename it to show we care about maintenance. Same for the show approver and log actions, with the value set to hide.&lt;/p>
&lt;p>Once we are done, hit save. This runs a validate as well, proving that there are no missing parts to the actions or conditions. You can rename the rule by dropping down the top option.&lt;/p>
&lt;p>This rule is not active yet, we need to activate it, but first the scope has to be considered. Do you want this rule to apply to any time a record is added or updated anywhere in your system, such as imports etc or just when using a form, or just one specific form.&lt;/p>
&lt;p>Finaly, Activate. Once activated, the rule can not be edited, only deactivated.&lt;/p>
&lt;p>This is then ready to be tested.&lt;/p>
&lt;p>I create a new Thing. The default negative path is running now, hiding both the approver &amp;amp; log fields.&lt;/p>
&lt;p>As I change the status reason to Waiting approval, the first postive branch kicks in, showing the 2 fields and making the approver mandatory.&lt;/p>
&lt;p>If I move it to Approved, the approver is locked, but the field remain visible.&lt;/p>
&lt;p>There are a few more options for you in actions, around the suggestions and warnings, so lets edit the rule by deactivating first.&lt;/p>
&lt;p>Lets show an error message to enforce that the approver is required. Against the field and a custom tesxt.&lt;/p>
&lt;p>Also, we can recommend a value in this condition for multiple fields.&lt;/p>
&lt;p>Under details, you can add one ore more defaults for fields, I will just recommend a title for now&lt;/p>
&lt;p>Hit Save, then Activate again and lets see it in action&lt;/p>
&lt;p>Where the status reason is waiting approval now, we get an error on the approver field, alerting us we need to fill that in. Also, there is a little light bulb that appears against Name, if you click on it, there is a button for you to fill in the form with the fields that we set up&lt;/p>
&lt;p>Back to the business rule, there is a snapshot button. This creates a picture of your full business rule to share with others.&lt;/p></description></item><item><title>3 Minute Features : Episode 3: Relationships</title><link>https://linked365.blog/2020/01/23/3-minute-features-episode-3-relationships/</link><pubDate>Thu, 23 Jan 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/01/23/3-minute-features-episode-3-relationships/</guid><description>&lt;p>Relationships are difficult, will she go out with you? Are you good enough? Does he want to propose?&lt;/p>
&lt;p>Those in CDS are a &lt;em>little&lt;/em> less complicated, but only just.&lt;/p>
&lt;p>My next 3 minute feature tries to give you an understanding of relationships&lt;/p>
&lt;h2 id="episode-3-relationships">Episode 3: Relationships&lt;/h2>
&lt;div class="video-wrapper">
&lt;iframe loading="lazy"
src="https://www.youtube.com/embed/oldn4f2lhH8"
allowfullscreen
title="YouTube Video"
>
&lt;/iframe>
&lt;/div>
&lt;h2 id="transcript">Transcript&lt;/h2>
&lt;p>First, lets explain a relationship&lt;/p>
&lt;p>The simpliest relationship there is in the Common data service is account to contact An account can have 0, 1 or more contacts. You could infer properties of the contact to be the same as the account. This relationship in CDS is called a 1 to many relationship if you take the relationship from the prospective of the account.&lt;/p>
&lt;p>From the contact, this is a many to one relationship, as many contacts will be associated with the same account. The same relationship, looking at the contact, would be a many to one relationship&lt;/p>
&lt;p>If, and this is pretty standard, a contact may have a relationship to many accounts, you can create a many-to-many relationship. This way, a intermediary table holds two relationships between the two entities in question.&lt;/p>
&lt;p>Going back to my solution, select my entity I have been creating and then relationships.&lt;/p>
&lt;p>As you can see, there are already a lot of relationships. These are created for you as you created the entity and selected some options. Connected From and To for example is because we ticked the box to Enable connections on the entity.&lt;/p>
&lt;p>Select Add relationship, then start with a Many-to-one. On the right hand side, you firstly need to select the related entity. As we are creating a many-to-one, where MyThing entity is the child, CDS will create a new lookup field on the child entity and give it a name and label both of which you are welcome to change&lt;/p>
&lt;p>In the general section, this is the name of your relationship itself. The default is very long winded, so I would advise to shorten to something more useful.&lt;/p>
&lt;p>Advanced options are where the relationship behaviour is defined. This is a set of options to automatically control the relationship. Parental is the default, but to understand what this means, lets look at all the options available in Custom&lt;/p>
&lt;p>The first is Delete. If the parent entity is deleted, what do you want to happen to the child? Delete the child as well when the business logic does not need orphaned records (for opporunity and opportunity lines for example) . Remove link will just make the child link to the parent null. Restrict will prevent the parent from being deleted if there are active child records present.&lt;/p>
&lt;p>The second is Share. The options here either share the child record with the same as who has just had the parent record shared with them (would work with account and opportunities for example), share only active records with them, share only those records owned by the owner of the parent record. None ensure that the share doesn’t get cascaded.&lt;/p>
&lt;p>Reparent is next, this works exactly the same as share, either changing the owner on all, active or user owned or none of the child records.&lt;/p>
&lt;p>Assignment works the same as share, if the parent record is assigned, do you want to assign all / active / user owned or none of the child records. This could work with tasks associated with cases.&lt;/p>
&lt;p>Finally unshare, which is the opposite of share.&lt;/p>
&lt;p>There are 2 standard options available to you as well, namely Referential and Parental.&lt;/p>
&lt;p>Referential has Cascade None for each of the Assign, Share, Unshare and reparent but with Delete as remove link or restrict&lt;/p>
&lt;p>Parental has Cascade All for all options, including delete.&lt;/p>
&lt;p>A word of caution here, a child entity can have only 1 parental entity, where you can cascade sharing or assigning. If there are 2 relationships, you will have to decide which one is the one you would like to use to cascade logic.&lt;/p>
&lt;p>Relationship configured, I will hit Done. The new relationship is highlighted in bold.&lt;/p>
&lt;p>I will quickly create a many to many relationship. Here after selected the related entity, you get to enter a relationship name as normal (noting the physical table name) and the new entity name you would like to create to serve as your intermediary table. Not there are no behaviour options here.&lt;/p>
&lt;p>Finally through the one to many relationship. This behaves the same as the many to one, but you are creating the lookup field on the child entity, which is the entity you select. You have the option to select behaviour type here as well.&lt;/p>
&lt;p>Hit Save entity to commit your changes to your environment.&lt;/p>
&lt;p>Going back to the solution, you can see it has automatically included the three entities I chose as related entities to my solution, as we are configuring them as well.&lt;/p></description></item><item><title>3 Minute Features : Episode 2 : Fields</title><link>https://linked365.blog/2020/01/16/3-minute-features-episode-2-fields/</link><pubDate>Thu, 16 Jan 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/01/16/3-minute-features-episode-2-fields/</guid><description>&lt;p>This is the 2nd installment of my 3 minute feature videos, going into detail about the different field types, how they appear on the interface and some other useful stuff.&lt;/p>
&lt;h2 id="episode-2-fields">Episode 2: Fields&lt;/h2>
&lt;div class="video-wrapper">
&lt;iframe loading="lazy"
src="https://www.youtube.com/embed/6LRwIyVUo48"
allowfullscreen
title="YouTube Video"
>
&lt;/iframe>
&lt;/div>
&lt;h2 id="transcript">Transcript&lt;/h2>
&lt;p>Starting with the new entity I created last time, select new then field.&lt;/p>
&lt;p>This pops up a form to the right, which has a display name and field name for you to enter the detail. The Name can not be changed once you hit save.&lt;/p>
&lt;p>Next is the type, as you ca n see there is a lot of them. To demonstrate each type, I added one of each to a modal form and display on the right how the default for each type behaves.&lt;/p>
&lt;p>There are certain properties for fields that are always present.&lt;/p>
&lt;p>Required ensures that there must be data in this field when saving&lt;/p>
&lt;p>Searchable means that this field is visible for all users who have entity access in views and advanced find. Usually this will be ticked&lt;/p>
&lt;p>Calculated or Rollup Fields allow you to summarise other fields to suit your business needs. This is only the tip of the iceberg and I will do a video on this soon&lt;/p>
&lt;p>Under Advanced options, give your field a description. The other options available depend on the field type you enter.&lt;/p>
&lt;p>Here, a simple text field has a maximum length. Be conservative over your field sizes as a best practice. Text has a max size of 4000 characters.&lt;/p>
&lt;p> On the form this is rendered with only 1 line.&lt;/p>
&lt;p>The Text Area has the same restrictions as Text The designer can decide how many lines to display.&lt;/p>
&lt;p>Email is still a text field in the backend database, but is rendered with a control allowing the user click and email from the page&lt;/p>
&lt;p>The same for URL, popping open the website.&lt;/p>
&lt;p>Ticker Field links directly to the MSN Money website to give a quick view of the stock&lt;/p>
&lt;p>Phone allows interaction with your telephony provider or Teams etc to direct dial the number&lt;/p>
&lt;p>Autonumber effectively gives each record a more user friendly or quotable reference to the record. This is great for case management type activities. You can establish what the prefix is and the number range. It gives you a preview of the format. On the form this &amp;ldquo;number&amp;rdquo; only appears when you save the record.&lt;/p>
&lt;p>The first number format is Whole Number. This does not allow decimal places to be entered and you can also establish a minimum and maximum value which helps with data entry. A warning to the user when the entry doesn’t match is given.&lt;/p>
&lt;p>Duration is a sppecial field which allows the user to select a duration from a drop down, the result is stored as a number in the database.&lt;/p>
&lt;p>Timezone presents the user with a list of international time codes and the database stores just a numeric representation of it.&lt;/p>
&lt;p>Language is similar, with only organisation enabled languages listed&lt;/p>
&lt;p>Date and time presents the user with 3 controls. A date picker and hour and minute drop downs. The Behavaiour option means that the data is stored as a Coordinated Universal Time and translates it to the user current time zone or you can say it is independent of the timezone, recorded and displayed as entered.&lt;/p>
&lt;p>IME Mode is applicable for all text fields, and it allows asian characters sets to be visible or rendered. Very advanced and if it effects you, you will probably already know how to configure it.&lt;/p>
&lt;p>The next type only renders a date picker, but still has the behaviour for time zones&lt;/p>
&lt;p>Currency is a numeric data type, but also creates a couple of extra fields when you hit save.. As the user enters the data, it is saved in the currency selected and also calculated and stored in the base currency of your system. This allows you to rollup opportunities etc in a common currency&lt;/p>
&lt;p>Customer is a special field that can either have a lookup to Contact or Account. The user can choose either. This field is useful for opportunities or other activities where sometimes you may link to one then the other.&lt;/p>
&lt;p>Decimal number allows you to define min &amp;amp; max again, but also how many decimal places These number types are limited to + or - one hundred thousand million, with upto 10 decimal places.&lt;/p>
&lt;p>File is next. File is only used, currently, in Canvas apps and flows, so not on my model driven form. It stores binary data and has a max file size of128Mb. Useful for capturing images, pdfs etc in a Power App.&lt;/p>
&lt;p>Floating point number is very similar to Decimal having the same restrictions, but is only stored as an approximation to your real number. This is done for performance reasons, normally there will be no difference to the end user. On rare occasions when you are dealing with large numbers that this may be of concern&lt;/p>
&lt;p>Lookup field link records together. This creates a parental relationship to the entity you select,This is a simple way of working with relationships, again a topic for a future video.&lt;/p>
&lt;p>Multi-option set is a great tool for data entry. The customiser decides on the options that they want to display and it is presented as a list where they can chose one or more of them. The options are stored globally across your orgainisation, allowing reuse&lt;/p>
&lt;p>Multi line text is for large paragraphs of text. You are limited to a million characters in this.&lt;/p>
&lt;p>Option set is identical to the Multi version, but restricts the user to only one choice.&lt;/p>
&lt;p>And finally two options is a specific option set for yes / no or on / off options. You can establish how these values are displayed, the user toggles between the two.&lt;/p>
&lt;p>Now that we have gone through the options, I&amp;rsquo;ll hit save. At this point, the field is not created. It is highlighted in bold to show those that have not been saved yet. You can go back and tweak the properties before you hit Save Entity&lt;/p></description></item><item><title>3 Minute Features : Episode 1 : Entities</title><link>https://linked365.blog/2020/01/09/3-minute-features-episode-1-entities/</link><pubDate>Thu, 09 Jan 2020 00:00:00 +0000</pubDate><guid>https://linked365.blog/2020/01/09/3-minute-features-episode-1-entities/</guid><description>&lt;p>My hiatus from blogging is due to my lack of creativity around thinking about problems and how to solve them and this got me thinking about a ready source of material that which would give me a infinite number of things to write about.&lt;/p>
&lt;p>As I always want to learn, and envy those that do these things, rather than a blog, I have started a video series which does a show and tell on a subject, in a set time frame.&lt;/p>
&lt;p>Welcome to 3 Minute Feature Thursdays&lt;/p>
&lt;h2 id="episode-1--entities">Episode 1 : Entities&lt;/h2>
&lt;p>&lt;div class="video-wrapper">
&lt;iframe loading="lazy"
src="https://www.youtube.com/embed/m72LASzFI3E"
allowfullscreen
title="YouTube Video"
>
&lt;/iframe>
&lt;/div>
//https://www.youtube.com/watch?v=m72LASzFI3E&amp;amp;list=PLm0EQNIOXEnNv34HhDOYP3PNbQqmaGK2Y&amp;amp;index=3&amp;amp;t=4s&lt;/p>
&lt;h3 id="transcript">Transcript&lt;/h3>
&lt;p>Hi and welcome to the first of a hopefully weekly topic on the fundamentals of the Common Data Service.&lt;/p>
&lt;p>There are a lot of blogs and videos out there that are documenting all the changes that are forever coming into the platform, so I thought we should take some time to ensure everyone knows the fundamentals.&lt;/p>
&lt;p>I will be diving into a topic each week in some depth, but trying to do it in 2 minutes. This gives me a timeframe to work to, reduces unnecessary words and hopefully gives a refresher or introduction to the topic in a bite sized portion.&lt;/p>
&lt;p>The first topic is Entities, so here we go&lt;/p>
&lt;p>Firstly, go to make.powerapps.com. Once there, check that you are in the correct environment. This is essential to ensure you are adding components to the right place.&lt;/p>
&lt;p>As with all development, it should start with a solution, so using the menu on the left, select Solutions, and new Solution.&lt;/p>
&lt;p>Give it a name and a publisher, both allow for the ability to differentiate our solutions and to patch solutions as we move the solution between environments for testing etc.&lt;/p>
&lt;p>The default version is 1.0.0.0&lt;/p>
&lt;p>Now hit publish, you can see that the solution is empty, so the next step is to create an entity using the menu top left&lt;/p>
&lt;p>The display and plural names are used by default in lists and records. The Name is the physical table name in SQL, so can not be changed after the entity is created. The name is prefixed with the publisher prefix.&lt;/p>
&lt;p>The primary field is what is selected when the user chooses a record to link 2 records together, like Contact name or company name. You can choose to change the default name and the field name.&lt;/p>
&lt;p>As we go down the properties, those with a little cross next to them can not be changed after you set it. You can set it if it is not set, but once it is set, there is no going back&lt;/p>
&lt;p>A key checkbox is the &amp;ldquo;Enable attachments&amp;rdquo;. This enables the entity for attachments, basically links the notes entity to your new one.&lt;/p>
&lt;p>Description allows your entity to be found later on and should describe it&amp;rsquo;s useage. More documentation the better&lt;/p>
&lt;p>If you change the Entity type to Activity, it will be allowed to be treated as an activity, such as email, tasks or call. Great if your entity is a new version of these things.&lt;/p>
&lt;p>If you want to restrict access to certain records in your entity, like opportunities typically, then ownership needs to be User or Team. Organisation level is used for data shared across your whole system, such as products.&lt;/p>
&lt;p>In the Collaboration section, Allow Feedback links your entity to the Feedback entity, allowing users, external or internal, to feedback and rate a record. Typically used for case or survey scenarios&lt;/p>
&lt;p>In the out of the box, meetings can have followup tasks that are associated with them, if your entity fits into this scenario, then enable this.&lt;/p>
&lt;p>Connections allow a user to link 2 disparate records together, typically used between employees / contacts / accounts to denote relationships.&lt;/p>
&lt;p>If you think that you want to be able to link your entity to incoming emails, then check Send email to Entity. The entity needs at least 1 email field. Leads and contacts are examples of this out of the box.&lt;/p>
&lt;p>Mail merge and sharepoint checkboxes enable the corresponding functionality too. Sharepoint needs more configuration, but here is where you enable each entity.&lt;/p>
&lt;p>Access teams complement the security via ownership. If you enable this checkbox, and set up a template, an access team for each record is automatically created when via code you add your first user to the team.&lt;/p>
&lt;p>Queues are typically used in a service scenario, but allows assignment of your record to a queue to be managed by a helpdesk or group of users.&lt;/p>
&lt;p>Quick create forms are useful in a lot of scenarios, where you want the user to easily create a new record with a subset of all the fields.&lt;/p>
&lt;p>Duplicate detection is common on most records. This setting enables it, but you will have to configure the rules to prevent duplicates.&lt;/p>
&lt;p>Flow change tracking allows Flow to subscribe to &amp;ldquo;When a record is updated&amp;rdquo; triggers on your entity. Essential in most scenarios.&lt;/p>
&lt;p>The final option is enabling your entity for offline outlook. There is a lot more to consider on this, but here is where you start the journey&lt;/p>
&lt;p>Once configured, hit Create and wait. You can go ahead and add fields and other stuff as you wait. Eventually you will be displayed with a nice green banner and a list of the default fields.&lt;/p>
&lt;p>So that’s it.&lt;/p>
&lt;p>Next time, I will dig into Fields, continuing on our journey.&lt;/p>
&lt;p>Please subscribe if you find these useful and provide feedback either via Twitter, LinkedIn or my blog.&lt;/p>
&lt;p>Cheers, see you next week.&lt;/p></description></item><item><title>D365 Org DB Settings - Other</title><link>https://linked365.blog/2019/11/03/d365-org-db-settings-other/</link><pubDate>Sun, 03 Nov 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/11/03/d365-org-db-settings-other/</guid><description>&lt;p>This is the second of a series where I &lt;strong>try&lt;/strong> to document all the rarely used settings available to your Dynamics organisation to tweak the standard behaviour.&lt;/p>
&lt;p>If you want to tweak your settings, see my previous &lt;a class="link" href="https://linked365.blog/2019/10/01/d365-org-db-settings-email/" >post&lt;/a>, or if you want to use a canvas app, see this &lt;a class="link" href="https://linked365.blog/2019/10/16/d365-org-db-settings-canvas-app/" >post&lt;/a>.&lt;/p>
&lt;p>Alternatively, I have created an XrmToolBox tool to do this, documented &lt;a class="link" href="https://linked365.blog/OrgSettingsTool" >here.&lt;/a>&lt;/p>
&lt;h3 id="activityconvertdlgcampaignunchecked">ActivityConvertDlgCampaignUnchecked&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>True&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Controls the default value of the Record Closed Campaign Response option. When you&lt;br>convert an activity to an opportunity, this default option controls whether&lt;br>the source campaign is set or not.&lt;br>False- Record Closed Campaign Response checked and source campaign will be set.&lt;br>True&amp;nbsp;- Record Closed Campaign Response not checked and source campaign is not set.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2720&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-39.png?w=437"
loading="lazy"
>&lt;/p>
&lt;p>When you convert activity to an opportunity, you have the option to populate a related campaign and also record a closed campaign response. This setting implies that you can default the Record a closed campaign response to true, forcing the selection of a campaign, but in my environment, it isn&amp;rsquo;t working.&lt;/p>
&lt;p>Someone prove me wrong&lt;/p>
&lt;h3 id="activateadditionalrefreshofworkflowconditions">ActivateAdditionalRefreshOfWorkflowConditions&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Enables an additional refresh of workflows that contain wait conditions and that may&lt;br>have to be resumed. This is required to be enabled to enable a fix that was originally&lt;br>released as a Critical On Demand hotfix, and was publically released starting with&lt;br>Update Rollup 13. When events in a Wait Until condition are met, the condition is not&lt;br>triggered as documented in KB&amp;nbsp;&lt;a href="https://support.microsoft.com/en-us/help/2918320">2918320&amp;nbsp;&lt;/a>.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.3445&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.3731&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Redundant fix for what looks like an issue in a specific version&lt;/p>
&lt;h3 id="allowroleassignmentondisabledusers">allowRoleAssignmentOnDisabledUsers&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Enables the assignment of a security role for user accounts&amp;nbsp;with a disabled status. This allows for&lt;br>scenarios where&amp;nbsp;stub users can be created and assigned a different security role. This is needed&lt;br>when&amp;nbsp;a stub/disabled user account&amp;nbsp;needs to own records, especially when&amp;nbsp;these records are from&lt;br>custom entities where custom security roles are required.&lt;br>False - By default, a security role cannot be assigned to users with disabled status.&lt;br>This is shipped by default.&lt;br>True - Allows security role to be assigned to users with disabled status.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.5610&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>There are lots of times, particularly around migrating systems, where you are not ready for users to have access to a new system but want to import their data. Think about where you are migrating department by department. The long-term goal would be for users to all have access, so temporarily assigning the records to another user or a system user may not be appropriate. Ownership is usually an indicator and first point of contact in most systems and a driver for security, etc.&lt;/p>
&lt;p>Toggling this setting to true allows assignment of roles, therefore records to disabled or stub users.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-41.png?w=515"
loading="lazy"
>&lt;/p>
&lt;p>Set to false, it displays this error message when you save any changes.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-40.png?w=573"
loading="lazy"
>&lt;/p>
&lt;h3 id="changedoublequotetosinglequote">ChangeDoubleQuoteToSingleQuote&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>false&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Changes double quotation marks to single quotation marks within KB articles when the article is viewed.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.3541&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This setting will do as it says, convert double quotes to single, but is only relevant for the old Knowledgebase Articles in your system, superseded by Knowledge articles that now have an appropriate WYSIWYG editor, this becomes redundant.&lt;/p>
&lt;h3 id="clearsystemuserprincipalswhendisable">ClearSystemUserPrincipalsWhenDisable&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>True&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Clear and/or populates SystemUserPrincipals values for systemUsers when they're disabled/enabled&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>6.1.1.123&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;h3 id="clientueipdisabled">ClientUEIPDisabled&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Disables the sending of customer experience feedback for the organization.&lt;br>This option can also be disabled from the user settings area for each user.&lt;br>False&amp;nbsp;- Enables the sending of experience feedback.&lt;br>True&amp;nbsp;- Disables the sending of experience feedback.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9688.583&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This, apparently, disables the option to send feedback to Microsoft when you get an error, great little setting, but until I get a repeatable error, can not see it in action&lt;/p>
&lt;h3 id="createspfoldersusingnameandguid">CreateSPFoldersUsingNameandGuid&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>True&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>True: creates SharePoint folders using the format of {Name}+{GUID}.-&lt;br>false: Creates SharePoint folders using just the name&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>6.0.0.809&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>When you integrate SharePoint, a folder in the site is created for each defined entity, normally with the name of the record and a GUID of the record. This can be ugly and not necessary if you have account names that are pretty unique. This setting allows you just to use the record name.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-42.png?w=1024"
loading="lazy"
>&lt;/p>
&lt;p>This screenshot shows with the setting as the default, true, at the top and the setting as false for JKL Sales&lt;/p>
&lt;h3 id="defaultheightforwizardreports">DefaultHeightForWizardReports&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>8.25&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Double&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>With a default value 0: CRM will use 8.25 inches (A4), any other double value will&lt;br>override the default of 8.25.&amp;nbsp; Some printers may reject printed reports if the&lt;br>height is any less than the height of the paper loaded in the tray, this setting will&lt;br>override the height used&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.3541&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Printing can be problematic with different paper sizes etc. Not really a problem with modern printers, but this setting allows you to configure default printing sizes to ensure printing works for your organisation.&lt;/p>
&lt;h3 id="disableiecompatmode">DisableIECompatMode&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Changes the server-side, automatic, IE Compatibility Mode Flag for Internet Explorer browsers.&lt;br>If you want pages to render in the most recent version of Internet Explorer set this to True.&lt;br>If you have form scripts or other customizations that require earlier versions of&lt;br>Internet Explorer this should be set to False.&lt;br>This is also controlled via Settings | Administration | System Settings | Customization&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.3233&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Compatibility mode was a big thing, particularly in the IE10 / 11 era. Making sure your website properly displayed across multiple browsers with inconsistent approaches to standards can still be a big gripe, but thankfully a thing of the past, with modern browsers adhering to standards a lot better.&lt;/p>
&lt;h3 id="disableinactiverecordfilterformailmerge">DisableInactiveRecordFilterForMailMerge&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>When you perform a mail merge, inactive records are not included.&lt;br>This option lets you&amp;nbsp;override that functionality.&lt;br>False&amp;nbsp;- Inactive records will not be included in the mail merge.&lt;br>True&amp;nbsp;- Inactive records will be included in the mail merge.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9688.583&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Mail Merge is a deprecated function, but if you still use it, when you call a mail merge from a campaign, inactive contacts or leads are not included.&lt;/p>
&lt;p>Mail merge is similar to the quick campaign, and I checked that this flag does not override the selection for quick campaigns, but it seems to have no effect.&lt;/p>
&lt;h3 id="enableactivitiestimelineperfimprovement">EnableActivitiesTimeLinePerfImprovement&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>1 to enable, 0 to disable(preserve existing behavior)&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.1639&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>In 2019 Wave 2, October 2019, enhancements were made to the timeline, to improve the density of activities and allowing the user to filter by multiple types etc. Details &lt;a class="link" href="https://docs.microsoft.com/en-us/dynamics365-release-plan/2019wave2/dynamics365-customer-service/timeline-usability-enhancements" target="_blank" rel="noopener"
>here&lt;/a>&lt;a class="link" href="https://docs.microsoft.com/en-us/dynamics365-release-plan/2019wave2/dynamics365-customer-service/timeline-usability-enhancements" target="_blank" rel="noopener"
>.&lt;/a>&lt;/p>
&lt;p>The new timeline can be seen below, which is toggled with EnableActivitiesFeatures described below. This setting toggles improvements to the performance of the new timeline, which may have an impact on your application.&lt;/p>
&lt;p>Thought the official line is that this is disabled by default, in any new environment it seems to be enabled.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/image-23.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="enableactivitiesfeatures">EnableActivitiesFeatures&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Bitmask to Enable various activities feature in UCI;&lt;br>1 to enable, 0 to disable(preserve existing behavior)&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.1639&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>In 2019 Wave 2, October 2019, enhancements were made to the timeline, to improve the density of activities and allowing the user to filter by multiple types etc. Details &lt;a class="link" href="https://docs.microsoft.com/en-us/dynamics365-release-plan/2019wave2/dynamics365-customer-service/timeline-usability-enhancements" target="_blank" rel="noopener"
>here&lt;/a>&lt;a class="link" href="https://docs.microsoft.com/en-us/dynamics365-release-plan/2019wave2/dynamics365-customer-service/timeline-usability-enhancements" target="_blank" rel="noopener"
>.&lt;/a>&lt;/p>
&lt;p>The new timeline can be seen below, toggled on and off by this setting.&lt;/p>
&lt;p>Thought the official line is that this is disabled by default, in any new environment it seems to be enabled.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/image-23.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="enablebulkreparent">EnableBulkReparent&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>True&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Disables and reparents using a one record at a time approach&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>6.0.0.809&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>I am not sure this is relevant any more. I assume this is for where you have large datasets and on premise, that could (with cascading) lead to large data changes for each ownership change, but with my environment, I did not notice any change between the two options.&lt;/p>
&lt;h3 id="enablequickfindoptimization">&lt;strong>EnableQuickFindOptimization&lt;/strong>&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>1&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>&lt;br>For more information, see the&amp;nbsp;"Optimizing the Performance of Quick Find Queries"&amp;nbsp;&lt;br>section in the&amp;nbsp;&lt;a href="http://go.microsoft.com/fwlink/?linkid=213093">Optimizing and Maintaining the Performance of a Dynamics CRM 2011 Server Infrastructure&lt;/a>.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2720&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Another one I assume has gone the way of the dodo for D365, this was initially configured to roll back the changes made to Quick find back in CRM 2011. I have toggle this on a new system and can not find any effect. This may be because of my minor data load etc and the optimisations that Microsoft has done since 2011.&lt;/p>
&lt;h3 id="enableretrievemultipleoptimization">EnableRetrieveMultipleOptimization&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>0&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>For more information, see the&amp;nbsp;"Optimizing the Performance of Queries against&lt;br>Large Datasets section" in the&amp;nbsp;&lt;br>&lt;a href="http://go.microsoft.com/fwlink/?linkid=213093">Optimizing and Maintaining the Performance of a Dynamics CRM 2011 Server Infrastructure&lt;/a>.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.1533&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This is another one that is probably redundant for anyone not on CRM 2011, and I would think those that are administering these systems already know about these settings. There is a full table of the configuration for this setting in the linked document, tweaking the way (away from the default) for returning multiple records in a list.&lt;/p>
&lt;p>As I do not have a CRM2011 environment and also don&amp;rsquo;t have the data volumes to see the effect, not sure I can or should add to this.&lt;/p>
&lt;h3 id="exportedexcelretentionwindow">ExportedExcelRetentionWindow&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>5&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>The number of days to temporarily store Excel exported Office Document Records.&lt;br>30 days max was selected arbitrarily as this is only a cache.&lt;br>Must be at least 2.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.1.0.1065&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Learning is great isn&amp;rsquo;t it? Researching this one led me to a great article from &lt;a class="link" href="https://twitter.com/bshastri" target="_blank" rel="noopener"
>Bhavesh Shastri&lt;/a> about the &lt;a class="link" href="https://community.dynamics.com/crm/b/crminthefield/posts/dynamics-365-customer-engagement-orgdborgsettings-configurations-might-affect-instance-size-storage" target="_blank" rel="noopener"
>settings that may affect storage size&lt;/a>, which has this setting in it.&lt;/p>
&lt;p>Basically, when you export a data set into Excel, D365 stores the result in a temporary table so that you can get back to the result quickly. There is a deletion service that goes and tidies up these temporary tables and this setting defines how old these records are before it removes them. If you have a very active system, these records could adversely effect the size of your instance.&lt;/p>
&lt;h3 id="expirechangetrackingindays">ExpireChangeTrackingInDays&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>30&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Maximum number of days to keep change tracking deleted record ID's.&lt;br>You want this value larger than the max# of days any change tracking dependent&lt;br>services sync with your system.&lt;br>Default is 30 days.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.1.0.0&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This is another storage related one like the previous, again jump over to Bhavesh&amp;rsquo;s &lt;a class="link" href="https://community.dynamics.com/crm/b/crminthefield/posts/dynamics-365-customer-engagement-orgdborgsettings-configurations-might-affect-instance-size-storage" target="_blank" rel="noopener"
>blog&lt;/a> to get more detail. This setting doesn&amp;rsquo;t appear in the Microsoft KB article where the others are, even more confusing and makes me wonder what else Microsoft are hiding&lt;/p>
&lt;p>If you have change tracking services running and worry about deleted records, this setting can be configured to increase the time these records are stored. Obviously, this will impact on storage if nothing else.&lt;/p>
&lt;h3 id="enabletdsendpoint">EnableTDSEndpoint&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Enable a SQL TDS Endpoint for your CDS Environment&lt;br>NOTE: your region will also have to support TDS endpoints, the regions with support for TDS may&lt;br>vary (as documented in the docs url provided here).&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.17162&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This, as it says, allows you to enable the CDS SQL TDS Endpoint, which allows you to use SQL Studio to query your live CDS environment. This is only recent, but is a great addition if you need more complexity in your queries.&lt;/p>
&lt;p>&lt;a class="link" href="https://twitter.com/MarkMpn" target="_blank" rel="noopener"
>Mark Carrington&lt;/a> did a great set of posts on it&amp;rsquo;s usage &lt;a class="link" href="https://markcarrington.dev/2020/05/13/cds-t-sql-endpoint-pt-2-first-thoughts/" target="_blank" rel="noopener"
>here&lt;/a>&lt;/p>
&lt;h4 id="forceretrievepublishedmetadataforretrieveallentities">ForceRetrievePublishedMetadataForRetrieveAllEntities&lt;/h4>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>All RetrieveAllEntities requests will ignore the AsIfPublished flag so that it always&lt;br>retrieves the published metadata from cache.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.1.1.1020&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;h4 id="fulltextspecialcharacterstoremovefromsearchtoken">FullTextSpecialCharactersToRemoveFromSearchToken&lt;/h4>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>null&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>string&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>This allows an organization to remove certain characters from a fulltext search string.&lt;br>Example: To remove a wildcard character from a FullText search, add “*”.&lt;br>To remove multiple characters, add them all together in a single string value “*.’#”.&lt;br>The characters are separated by ToCharArray&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.1.1.1020&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;h3 id="grantfullaccessformergetomasterowner">GrantFullAccessForMergeToMasterOwner&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>True&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>When two records owned by the same team are merged, the final record is shared with the&lt;br>owner of the record it was merged from. This creates redundant POA records, as a result,&lt;br>if the owner of the record is changed in the future it will be visible to&lt;br>team members of the previously owning team.&lt;br>To do this, set to false.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.4449&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Another one of those security options that most people don&amp;rsquo;t know about. I would hazard to guess that most people don&amp;rsquo;t know that the owner of a subordinate record in a merge has the new master shared with them. Mark Carrington has a great explanation of this setting and the next in his blog &lt;a class="link" href="https://markcarrington.dev/2019/08/31/msdyn365-internals-merge-permissions/" target="_blank" rel="noopener"
>here&lt;/a>&lt;/p>
&lt;p>The default setting puts a row in the Share table for the original owner, even if it is same as the new owner, which is useful in a lot of cases, but also could break your security model if the owner changes again.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-45.png?w=793"
loading="lazy"
>&lt;/p>
&lt;p>With the setting put to false, the original owner does not have the record shared with them&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-44.png?w=838"
loading="lazy"
>&lt;/p>
&lt;p>The wording of this setting implies that only the master owner will have the sharing stopped, but it seems that the original does as well.&lt;/p>
&lt;h3 id="grantsharedaccessformergetosubordinateowner">GrantSharedAccessForMergeToSubordinateOwner&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>True&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>To turn this setting off, this must be set to false. Records are shared with inherited access&lt;br>to subordinate owners during merge. This will not occur when set to false.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.3911&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>If you have a contact and merge the account, the contact will be moved to be owned by the master owner, but the owner of the contact will have the master record shared with them too. Obviously, this just makes the system work, but doesn&amp;rsquo;t help if you have a specific security prinicple in place.&lt;/p>
&lt;p>Please see Mark&amp;rsquo;s &lt;a class="link" href="https://markcarrington.dev/2019/08/31/msdyn365-internals-merge-permissions/" target="_blank" rel="noopener"
>blog&lt;/a> to fully understand these values.&lt;/p>
&lt;h3 id="hidestageandupgrade">HideStageAndUpgrade&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>1&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Changing this setting to 0 will allow users to see the upgrade solution option in solution&lt;br>import wizard when importing solutions with higher version than previously imported.&lt;br>This setting has a default of 1 which hides the option to perform a stage for upgrade.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.3&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Back in 2016, Microsoft gave us the ability to stage an upgrade solution, which means we can more easily remove parts of a managed solution, rather that using holding solutions.&lt;/p>
&lt;p>Nishant Rana has an excellent blog &lt;a class="link" href="https://nishantrana.me/2016/10/16/how-to-delete-components-from-managed-solution-in-dynamics-crm-2016-without-using-holding-solution/" target="_blank" rel="noopener"
>here&lt;/a> that describes the process. The process relies on having the Stage for upgrade tick box available to you, which is now hidden by default presumably because Microsoft has provided us the ability to create patches for solutions and it is no longer needed.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-47.png?w=547"
loading="lazy"
>&lt;/p>
&lt;h3 id="hierarchylevelforhierarchyfeature">HierarchyLevelForHierarchyFeature&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>3&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>The hierarchy level used for hierarchal security&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.0.0000.3027&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Another security tweak. There are 2 security models that may be in use in your instance, namely managerial or positional security.&lt;/p>
&lt;p>Both can take into account a number of managers above you who have the same access to records that you do, which is traditionally 3, and anything above this can cause performance issues. As you can set the hierarchy level on the hierarchy configuration, this setting is now redundant I think, as any change you make to the org setting is not reflected in the setting on the Hierarchy setting screen.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/wp-content/uploads/2019/11/image.png?w=330"
loading="lazy"
>&lt;/p>
&lt;h3 id="ifdauthenticationmethod">IfdAuthenticationMethod&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>null&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>String&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Changes the request sent to the ADFS server, this settings default value&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2835&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This setting is for on premise only, as it defines which SSO an internet facing deployment (an external facing on premise deployment) uses to establish the user has the right access credentials.&lt;/p>
&lt;p>This &lt;a class="link" href="https://community.dynamics.com/crm/b/1984crm/posts/ifd-claims-adfs-what-now" target="_blank" rel="noopener"
>blog&lt;/a> has a more detailed explanation.&lt;/p>
&lt;h3 id="includehtc">IncludeHTC&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>true&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Set whether forms should support HTML component.&amp;nbsp;&lt;br>The CRM 4.0 API uses this feature which is deprecated and will no longer be included&lt;br>after the next major release.&amp;nbsp; If you&amp;nbsp; have javascript code relying on CRM 4.0&lt;br>javascript API's you should enable this and work to update your code to support CRM 2011.&lt;br>This is also controlled via Settings | Administraton | System Settings | Customization.&lt;br>This setting is NOT SUPPORTED IN CRM 2013&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.3233&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This setting is only applicable to CRM 4, I know there are still users out there, but I can not get access to a system to try out this setting &amp;amp; assume even the CRM 4 people won&amp;rsquo;t be using this feature still&lt;/p>
&lt;h3 id="inheritedroleprivilegesfromteamroles">inheritedRolePrivilegesFromTeamRoles&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>true&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Disables the Azure AD Group team functionality of the organization in an event that there is a&lt;br>performance related issue. The Azure AD Group team feature is shipped enabled by default.&lt;br>False - Disable Azure AD Group Team and members of group teams are required to have their&lt;br>own security role assigned to them directly.&amp;nbsp; Run-time calls to Azure AD to obtain the user’s&lt;br>AAD groups are stopped.&lt;br>True - Azure AD GroupTeam is enabled and members of group teams shall inherit user/basic&lt;br>privileges directly and user privileges are derived at run-time.&amp;nbsp; Run-time calls to&lt;br>Azure AD to obtain user’s AAD groups are invoked.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.4632&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Earlier this year, Microsoft gave us the ability to give security permissions to all the members of an Azure AD group, rather than having to duplicate security across Azure and Dynamics. This can be a time consuming god-send for your administrative staff, but also can impact performance. Setting this value to false forces the old method of security, with each user having to be configured with a role in D365.&lt;/p>
&lt;p>Debajit Dutta has an excellent walkthrough on how to utilise this functionality &lt;a class="link" href="https://community.dynamics.com/crm/b/debajitcrm/posts/azure-ad-groups-can-own-your-dynamics-365-records-learn-it-how" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;h3 id="idscountbeforeusingjoinsforsecurity">IdsCountBeforeUsingJoinsForSecurity&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>1000&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Not documented in optimization paper.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2720&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;h4 id="idscountforusingguidstringsforsecurity">IdsCountForUsingGuidStringsForSecurity&lt;/h4>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>20&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Not documented in optimization paper.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2720&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;h3 id="integratedauthenticationmethod">IntegratedAuthenticationMethod&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>null&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>string&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Changes the request sent to the ADFS server, this settings default value&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2835&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>An On-premise property, which I can not find anything on.&lt;/p>
&lt;h3 id="jumpbaralphabetoverride--jumpbarnumberindicatoroverride">JumpBarAlphabetOverride / JumpBarNumberIndicatorOverride&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>null&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>string&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>&lt;a href="https://support.microsoft.com/help/2494984">How to customize the Alphabet &lt;strong>Bar &lt;/strong>for the CRM Application Grids for Microsoft Dynamics&lt;/a>&lt;br>&lt;a href="https://support.microsoft.com/help/2494984">CRM 4.0&lt;/a>&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2243&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>I didnt know this was a thing, but only for CRM 4.0. Basically, you could override what appears at the bottom of a search display.&lt;/p>
&lt;p>Shivam Dixit has a walkthrough &lt;a class="link" href="https://shivamdixit.wordpress.com/tag/jumpbaralphabetoverride/" target="_blank" rel="noopener"
>here&lt;/a>&lt;/p>
&lt;h3 id="listcomponentinstalled">ListComponentInstalled&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>If CRM and SharePoint use ADFS and users click to create a folder for a record in CRM 2011,&lt;br>intermittently, the SharePoint page is shown instead of the list part grid page causing&lt;br>confusion with users. This setting allows you to force CRM to use the installed list grid&lt;br>component in SharePoint when using ADFS.&lt;br>false: use the standard method of detecting Sharepoint Authentication&amp;nbsp;&lt;br>true: If CRM and SharePoint have ADFS enabled, force CRM to use the grid display.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.3911&lt;br>6.1.0.581&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This was a bug fix to force display of the SharePoint list instead of the page in a SharePoint created folder when a list is available.&lt;/p>
&lt;h3 id="lookupnamematchesduringimport">LookupNameMatchesDuringImport&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Importing a solution that was created from an upgraded 4.0 deployment fails.&lt;br>Changing this setting makes the import solution look up the names for forms, views,&lt;br>workflows and security roles.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.583&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>I have no access to CRM 4 to create a solution to test this out, but if anyone can create me screenshots, I&amp;rsquo;ll add in.&lt;/p>
&lt;h3 id="maximumchilduserscountlimitbeforeusingjoinforhsm">MaximumChildUsersCountLimitBeforeUsingJoinForHSM&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>80&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Maximum Child/Subordinate Users Count Before Using a Join Query for Heirarchical Security Model&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.0.0000.3027&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>As mentioned, hierarchical security model gives your manager (or managers manager etc) the same access to your data that you have. As a manager with lots of reports, this can cause performance problems, so limiting the maximum unions it makes when deciding on your access makes sense. After this number is reached, an outer join will be used to improve performance.&lt;/p>
&lt;p>If you have scenarios that require that number of child users to a manager, I would recommend not using Hierarchical security.&lt;/p>
&lt;h3 id="minrowcountforfkindexcreateinreferencingentity">MinRowCountForFKIndexCreateInReferencingEntity&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>100&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Setting min row count in referencing table for ForeignKey index creation&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.0.0000.3027&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>In the D365 world, the back end SQL optimisation is out of an administrators hands mostly, with indexes automatically been created for Primary keys or alternative keys for example. This setting tweaks the creation of indexes for FK keys.&lt;/p>
&lt;p>If an account has a foreign key to a location entity, there needs to be more than 100 rows (by default) before the system will create an index on the account table using the location foreign key.&lt;/p>
&lt;h3 id="officedocumentpersistencetimeindays">OfficeDocumentPersistenceTimeInDays&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>7&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>The number of days to temporarily store Office Document Records. 30 days&lt;br>max was selected arbitrarily as this is only a cache.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.1.0.1059&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>When an office document is retrieved from the database, it is stored in the cache, by default for 7 days. This can be altered. This is one option that impacts the size of your tenant.&lt;/p>
&lt;h3 id="pagesizeforhierarchyfeature">PageSizeForHierarchyFeature&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>5&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>The hierarchy page size used for hierarchal security&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.0.0000.3027&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>I assume that this is used in the same way as the MaximumChildUsersCountLimitBeforeUsingJoinForHSM setting, but I can not find any documentation for it&lt;/p>
&lt;h3 id="reassignallextendedtimeout">ReassignAllExtendedTimeout&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>0&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Increase script timeout for reassigning all records of a user or team - this allows you to exceed&lt;br>the default extended timeout value. Default extended timeout is 1000000 ms&lt;br>(roughly 15 minutes).&lt;br>WARNING: Care should be taken when increasing this value above the default -&lt;br>always double check the number of minutes before setting this to a value higher than the default&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.1.2.1020&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>If you have a security model that relies on a cascade of ownership, when a parent owner is changed, this ownership is also done for children and children of children etc.&lt;/p>
&lt;p>This can be a time-consuming process which you can increase the time-out for, possibly temporarily if you have an occasion that required it, though the default 15 minutes is a very long time.&lt;/p>
&lt;h4 id="recordcountlimittoswitchtoctesecuritysql">RecordCountLimitToSwitchToCteSecuritySql&lt;/h4>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>75000&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>For more information see the&amp;nbsp;Optimizing the Performance of&lt;br>Queries against Large Datasets"&amp;nbsp;section in the&lt;br>&amp;nbsp;&lt;a class="" href="http://go.microsoft.com/fwlink/?linkid=213093">Optimizing and Maintaining the Performance of a Dynamics CRM 2011 Server Infrastructure&lt;/a>.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2720&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>I didnt know this was a thing, but only for CRM 4.0. Basically, you could override what appears at the bottom of a search display.&lt;/p>
&lt;p>This setting is for On-premise only, impacting the switching to use a temporary table or CTE (Common Table Expression) to generate the results. I have not got enough data to check if this still has an impact on D365 environments.&lt;/p>
&lt;p>The linked paper has a lot of good stuff about optimisations, that thankfully the more modern SAAS environments have taken care of.&lt;/p>
&lt;h3 id="retrievemultiplesharingcountthreshold">RetrieveMultipleSharingCountThreshold&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>1000&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>For more information, see the&amp;nbsp;"Optimizing the Performance of Queries against Large Datasets&lt;br>section" in the&amp;nbsp;&lt;a href="http://go.microsoft.com/fwlink/?linkid=213093">Optimizing and Maintaining the Performance of a Dynamics CRM 2011 Server Infrastructure&lt;/a>.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2720&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This is another setting that is for optimisation of the on-premise architecture, defining the number of shared records the user has for the entity being searched for (either direct or via teams) that the system will convert the query to joins rather than table value functions.&lt;/p>
&lt;p>As sharing with individuals should be an increment to your security model rather than the main part, having 1000 shares per entity would be pretty rare.&lt;/p>
&lt;h3 id="securityqueryhint">SecurityQueryHint&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>1&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Used to hint the query within GetRightsFromPrincipalObjectAccess.&lt;br>0=None;&lt;br>1=Recompile (default);&lt;br>2=OptimizeForUnkown&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.1.0.141&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>I can&amp;rsquo;t find any information on this. Will update when I find out.&lt;/p>
&lt;h3 id="sharinglimitforpoasnapshottable">SharingLimitForPOASnapshotTable&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>10&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Not documented in optimization paper.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2720&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>I can&amp;rsquo;t find any information on this. Will update when I find out.&lt;/p>
&lt;h3 id="skipaadgroupobjectidvalidation">skipAadGroupObjectIdValidation&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Disables the validation of Azure AD Group objectID and allows application to create Group&lt;br>team in CDS.&amp;nbsp; This is used to mitigate the latency in the Azure AD distributed cache&lt;br>where a newly created Azure AD group cannot be validated if the subsequent&lt;br>Azure AD Group graph call goes to a distributed cache server that does not&lt;br>have the new Azure AD group yet.&lt;br>False - do not skip Azure AD group objectID validation during Group Team creation.&amp;nbsp;&lt;br>This is shipped by default.&lt;br>True - skip Azure AD group objectID validation to allow application to create Group team.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.5808&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>If you use the new functionality to connect teams to AD groups, allowing a single location to manage security, setting up the teams needs a link back to the AD group.&lt;/p>
&lt;p>As AD group creation takes time to propagate to the various caches, the group you want to link to might not be available, so, by default, no check is made to see if you have got the GUID right. This can be forced if you need that extra piece of mind by setting this value true.&lt;/p>
&lt;h3 id="skipgettingrecordcountforpaging">SkipGettingRecordCountForPaging&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Disables the record count query. This query is responsible for retreiving the total number of records returned for each view.&lt;br>This query can cause longer search times and may cause SQL timeouts or exceptions.&lt;br>False&amp;nbsp;- Enables record depend on views.&lt;br>True&amp;nbsp;- Disables record depend on views.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.2.0.0503&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>When you have a large dataset, knowing that you have thousands of records rather than just the 100 the view is showing is invaluable, but this query has to be done, as well as the query to retrieve the data, impacting performance&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/wp-content/uploads/2019/11/annotation-2019-11-03-143906.png?w=292"
loading="lazy"
>&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/wp-content/uploads/2019/11/image-1.png?w=306"
loading="lazy"
>&lt;/p>
&lt;p>With the setting applied, the query doesn&amp;rsquo;t display an accurate number, but it does display a number, which is mis-leading in my opinion.&lt;/p>
&lt;h4 id="skipgettingrecordcountforpagingforaudit">SkipGettingRecordCountForPagingForAudit&lt;/h4>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Disabled the record count query for just the Audit entity.&lt;br>False enables the record count, and True disables the record count&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.2.0.0503&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This is the same as the previous setting, but just for the auditing views, which are notoriously large.&lt;/p>
&lt;h2 id="skipsuffixonkbarticles">SkipSuffixOnKBArticles&lt;/h2>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Disables the suffix from being used on the automatically generated KB article numbers.&lt;br>False&amp;nbsp;- Enables the suffix on KB articles.&lt;br>True&amp;nbsp;- Disables the suffix on KB articles.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.1992&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Pretty self-explanatory, but for old KB articles rather than the new Knowledge Articles.&lt;/p>
&lt;h3 id="tabletclientmaxfields">TabletClientMaxFields&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>75&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Maximum Tablet Fields max-500/ min- 1&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>6.0.0.809&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>These tablet settings are not for D365, v9 as Unified interface has removed the limitations&lt;/p>
&lt;h3 id="tabletclientmaxlists">TabletClientMaxLists&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>10&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Maximum Tablet Lists max-50/min-1&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>6.0.0.809&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>These tablet settings are not for D365, v9 as Unified interface has removed the limitations&lt;/p>
&lt;h3 id="tabletclientmaxmashups">TabletClientMaxMashups&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>3&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Maximum Tablet Mashups&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.0.0000.3027&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>These tablet settings are not for D365, v9 as Unified interface has removed the limitations&lt;/p>
&lt;h3 id="tabletclientmaxtabs">TabletClientMaxTabs&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>5&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Maximum Tablet Tabs max-50/min-1&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>6.0.0.809&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>These tablet settings are not for D365, v9 as Unified interface has removed the limitations&lt;/p>
&lt;h3 id="tracelogpersistencetimeindays">traceLogPersistenceTimeInDays&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>30&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>This sets the amount of time that TraceLog data is maintained before being removed by the Deletion Service&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.1.1.1020&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This is another setting that can impact the size of your instance. The logs are stored by default for 30 days, if you have a heavily used system, this will be a lot of data, so reducing this will reduce costs. Trace logs are part of a separate pricing tier now, but still worth a look.&lt;/p>
&lt;h3 id="useorganizationserviceformultientityquickfind">UseOrganizationServiceForMultiEntityQuickFind&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Allows Multi-entity Quick Find to run serially rather than in parallel.&lt;br>This allows plugins to be executed on RetrieveMultiple.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.2.1.0135&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Retrieve multiple plugins can do a little more security to prevent the display of records or adding in data to a record set if you need it to be really truly accurate.&lt;/p>
&lt;p>Whilst this is frowned upon as is a real impact on system performance, it might be necessary. If you need this functionality, quick view doesn&amp;rsquo;t honour this logic as the queries run in parallel. Toggling this to true makes each quick query run in serial, allowing retrieve multiple plugins to work.&lt;/p>
&lt;h3 id="workflowxamlvalidationerrorreport">WorkflowXamlValidationErrorReport&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>WorkflowXamlValidationErrorReport is used to fail workflow loads if the XAML is not valid&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.5808&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>I can&amp;rsquo;t find any information on this. Will update when I find out.&lt;/p></description></item><item><title>D365 Org DB Settings - Canvas App</title><link>https://linked365.blog/2019/10/16/d365-org-db-settings-canvas-app/</link><pubDate>Wed, 16 Oct 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/10/16/d365-org-db-settings-canvas-app/</guid><description>&lt;img src="https://linked365.blog/images/2019/10-image-28.png" alt="Featured image of post D365 Org DB Settings - Canvas App" />&lt;p>On the back of one of my other posts on the &lt;a class="link" href="https://linked365.blog/2019/10/01/d365-org-db-settings-email/" target="_blank" rel="noopener"
>D365 Org DB Settings&lt;/a> I thought it would be good to re-imagine the method to update these settings in a Canvas app.&lt;/p>
&lt;p>The solution from Sean McNellis is great and has been a big influence on my design, including the settings xml is pretty much a copy. I am hoping that I give users a more visual experience and this is a starter for a bunch of D365 CE admin apps in PowerApps.&lt;/p>
&lt;p>I am now looking for people to test it and give me feedback on the solution, so if anyone has a little time to be critical, please contact me on the blog, via Twitter or on GitHub as an issue.&lt;/p>
&lt;p>&lt;a class="link" href="https://github.com/CooksterC/D365-Admin-Tools" target="_blank" rel="noopener"
>https://github.com/CooksterC/D365-Admin-Tools&lt;/a>&lt;/p>
&lt;h2 id="overview">Overview&lt;/h2>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-28.png?w=1024"
loading="lazy"
>&lt;/p>
&lt;p>Hope you like green&amp;hellip;.&lt;/p>
&lt;p>On the left is a list of the options for configuration. By default, it only shows the ones that are already configured, but we can alter this to show all settings by toggling the top button. You can also search at the top for the setting you want.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-29.png?w=872"
loading="lazy"
>&lt;/p>
&lt;p>The list is also colour coded, to highlight the ones you have changed, the ones that are configured already and the ones that have no setting.&lt;/p>
&lt;p>The grid shows the official documentation of the setting and a link to the KB article.&lt;/p>
&lt;p>The Bin button will remove this setting from your configuration, returning it to the default.&lt;/p>
&lt;p>The + button will add the setting to your configuration using the default value.&lt;/p>
&lt;p>The Value entered can be different controls depending on the value been configured.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-30.png?w=837"
loading="lazy"
>&lt;/p>
&lt;p>At the top right, you can save any configuration changes, which refreshes the list and the bottom right panel, which shows the current configuration&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-31.png?w=770"
loading="lazy"
>&lt;/p>
&lt;p>The top panel will display the documentation on the settings. There is also the ability to copy a configuration from another system or manually edit the xml.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-32.png?w=741"
loading="lazy"
>&lt;/p>
&lt;p>NO WARRANTIES GIVEN. If you get this wrong, then don&amp;rsquo;t blame me!&lt;/p>
&lt;h2 id="installation">Installation&lt;/h2>
&lt;p>The package is a solution, with 2 components, the Canvas App and a custom connector.&lt;/p>
&lt;p>As part of the app, the settings xml is cleared before it replaces with the new configuration, using the standard connector gives an error when this is done, so I reverted to doing this via a custom connector. Also, the settings are reliant on the version of your D365, less of an issue now that everyone is on the same version, but for those on premise, the version is required, again not available in a normal connector.&lt;/p>
&lt;p>I have found that if I include that in a solution, it has the intended effect of bringing with it the connection to the api that it is configured for. This is great for deploying apps using a common api, but in this scenario, I don&amp;rsquo;t want you to use my tenant, but your own. Not sure how this could be improved, particularly for ISVs etc. Also, as the solution matures, everytime you import the solution, the connector needs reconnecting, which isn&amp;rsquo;t ideal.&lt;/p>
&lt;p>So there is 2 parts, the Canvas App exported as a package and the connector.&lt;/p>
&lt;h2 id="connector-configuration">Connector Configuration&lt;/h2>
&lt;p>Select New Custom Connector / Import as OpenAPI file&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-36.png?w=370"
loading="lazy"
>&lt;/p>
&lt;p>Put in your environment link here. This is mine, and the solution method of connectors copies these settings, thankfully it is OAuth, so unless you know my password (and this is a trial).&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-33.png?w=586"
loading="lazy"
>&lt;/p>
&lt;p>Next is security. Edit the OAuth 2.0 settings.&lt;/p>
&lt;p>You need to enter the Client Id and Client Secret taken from the Azure AD authentication as well as the Resource URL being the address of your environment.I stepped through this when I created my first custom connector for &lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365/" target="_blank" rel="noopener"
>LUIS&lt;/a> integration.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-34.png?w=554"
loading="lazy"
>&lt;/p>
&lt;p>Update the connector and move on to testing.&lt;/p>
&lt;p>I have only got 3 actions defined here, keeping it to the actions I need for the application and WhoAmI, which is so simple, allows me to confirm the connection prior to worrying about syntax.&lt;/p>
&lt;p>As this is OAuth, you need to configure a connection, which is a prompt for you enter your credentials.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-35.png?w=537"
loading="lazy"
>&lt;/p>
&lt;p>Test the operation to prove you have got your connector up and running.&lt;/p>
&lt;h2 id="install-the-canvas-app">Install the Canvas App&lt;/h2>
&lt;p>Got to your apps and select Import package. Select the zip file from GitHub repository.&lt;/p>
&lt;p>The first time you install, it has nothing to update, so you will need to change the action to &amp;ldquo;Create as new&amp;rdquo; and give it a new name if you don&amp;rsquo;t like it.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-37.png?w=363"
loading="lazy"
>&lt;/p>
&lt;p>On the connector, you should connect it to the one that has just been created&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-38.png?w=1010"
loading="lazy"
>&lt;/p>
&lt;p>Hit import and you are done! Run the app to see a default configuration.&lt;/p>
&lt;p>Like I have said, I would like feedback, particularly on how to improve the installation process. It is rather fiddly, would love to be able to just install a solution and you are done.&lt;/p></description></item><item><title>D365 Org DB Settings - Email</title><link>https://linked365.blog/2019/10/01/d365-org-db-settings-email/</link><pubDate>Tue, 01 Oct 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/10/01/d365-org-db-settings-email/</guid><description>&lt;img src="https://linked365.blog/images/2019/10-image-71.png" alt="Featured image of post D365 Org DB Settings - Email" />&lt;p>On a client recently I helped deploy Microsoft D365 App for Outlook. Unfortunately, the behaviour requested by the client and the default behaviour of the Server Side synchronisation was not aligned.&lt;/p>
&lt;p>This led to long discussions with Microsoft about some of the DB Org Settings we could utilise to tweak the way SSS works. As I researched these settings and discussed with my colleagues and during networking events, it became clear they remain unknown to most developers and administrators. If your deployment needed to tweak the settings, then people knew, but it is not common knowledge.&lt;/p>
&lt;p>Further, there seemed to be very little documentation on what each setting does, apart from Microsoft&amp;rsquo;s own information &lt;a class="link" href="https://support.microsoft.com/en-us/help/2691237/orgdborgsettings-tool-for-microsoft-dynamics-crm" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;p>This is a series of posts explaining each of the Org settings, understanding how it affects your environment. Hopefully it will raise awareness of these settings.&lt;/p>
&lt;p>Bear in mind that there a lot of settings that I can not find any information on or have no experience on. This is frustrating for me, but assume someone in the community will push me in the right direction and I will update the page when I find out.&lt;/p>
&lt;h2 id="how-to-change-org-db-settings">How to Change Org DB Settings&lt;/h2>
&lt;p>&lt;a class="link" href="https://twitter.com/seanmcne" target="_blank" rel="noopener"
>Sean McNellis&lt;/a> has an excellent tool on GitHub &lt;a class="link" href="https://github.com/seanmcne/OrgDbOrgSettings" target="_blank" rel="noopener"
>here&lt;/a> which allows interaction with the org settings via a solution in your environment.&lt;/p>
&lt;p>One the solution is imported, selecting the solutions gives you an interface where you can check the current status of each setting and change them.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/10-image-71.png?w=902"
loading="lazy"
>&lt;/p>
&lt;p>To change the default, you need to select the Add hyperlink. This creates an XML file including your property which is uploaded to your system to change the setting.&lt;/p>
&lt;p>Selecting the Edit link for the attribute now gives you a popup window, where you can edit the value&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-72.png?w=435"
loading="lazy"
>&lt;/p>
&lt;p>Also, Sean has included a copy of the Microsoft description with each setting.&lt;/p>
&lt;p>On the right side of the grid is a link to to the KB article that mentions the setting, though normally it is just to KB 2691237 which is the central list of all Org settings.&lt;/p>
&lt;h3 id="activityrollupchildrecordlimit">ActivityRollupChildRecordLimit&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>50,000&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Limit the number of total aggregated activities to rollup in the Activity Rollup&lt;br>Default:50,000.&lt;br>Used with: VisibleRecordThreshholdSwitchToMultiplelineTVF&lt;br>and TotalRecordThreshholdSwitchToMultiplelineTVF&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.8031&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This is a new one on me. Activities roll up. You put an email against a contact, the email is available on the account the contact is associated with. This applies to custom entities as well, if you configure the relationship correctly. Inogic has a great post on it &lt;a class="link" href="https://www.inogic.com/blog/2017/01/configure-rollup-view-for-activities-with-dynamics-crm365/" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;p>This setting must have come about to limit this as the numbers where getting too big for some. I have not got the data to do this one justice unfortunately.&lt;/p>
&lt;h3 id="addressbookmaterializedviewsenabled">AddressBookMaterializedViewsEnabled&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>True&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Changes the way the CRM Client queries SQL CE&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2903&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>The description doesnt tie up with the title, and when you google it, this setting revolves around a previous setting, Disable MAPI cache, that was around in CRM 2011 and helped improve performance. Not a lot more I can say.&lt;/p>
&lt;h3 id="allowpromoteduplicates">AllowPromoteDuplicates&lt;/h3>
&lt;p>Duplicates in D365 are not unheard of, but when Outlook sync comes in, there are more chances to get duplicates. When a user syncs an Outlook Contact,&lt;/p>
&lt;h3 id="allowsaveasdraftappointment">AllowSaveAsDraftAppointment&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Setting value to true will provide the capability to create appointments in Dynamics 365&lt;br>as “draft” without synchronizing with Exchange.&lt;br>Appointment form will have a “Save as Draft” command and a “Send” command, so that you&lt;br>can save, add details and update an appointment activity without synchronizing to Exchange.&lt;br>Default value is set to false to preserve existing behavior.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>&lt;br>9.0.2.2275&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This flag opens up the possibility that you don&amp;rsquo;t always get a meeting correct the first time and allows you to save a draft.&lt;/p>
&lt;p>Ulrik Carlsson aka &lt;a class="link" href="https://twitter.com/crmchartguy" target="_blank" rel="noopener"
>@CRMChartGuy&lt;/a> from eLogic solutions has a great article about this attribute.&lt;/p>
&lt;p>The default behaviour is that users are not presented with a Save as Draft option for appointments, when a appointment is saved, if you are using SSS it will synchronise to Outlook and send out invites to the attendees as normal.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-74.png?w=619"
loading="lazy"
>&lt;/p>
&lt;p>If you change AllowSaveAsDraftAppointment to true, the users get a different set of buttons.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-75.png?w=737"
loading="lazy"
>&lt;/p>
&lt;p>Both Send and Send &amp;amp; Close buttons behave like the original Save and Save &amp;amp; Close. They will initiate a server side sync one the record is saved.&lt;/p>
&lt;p>The new button Save as Draft will save the appointment but not send it to Outlook etc. It adds a [Draft] prefix to the appointment header and also a new field on the appointment, isdraft, is populated with true.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-76.png?w=532"
loading="lazy"
>&lt;/p>
&lt;p>Weirdly, this field can not be added to a form. It just doesn&amp;rsquo;t appear in the field list. You can add it as view filter criteria, but you can&amp;rsquo;t display it as a column in a view.&lt;/p>
&lt;h3 id="heading">&lt;/h3>
&lt;p>AutoCreateContactOnPromote&lt;/p>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>True&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Disables the ability of the organization to create contact records automatically when an email&lt;br>message is tracked in CRM. This option can also be disabled from the user settings area&lt;br>for each user.&lt;br>False&amp;nbsp;- Disables the automatic creation of contacts.&lt;br>True&amp;nbsp;- Enables the automatic creation of contacts.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9688.583&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>By default, when a user sets regarding within the Outlook app, if any email address is in the To / CC / BCC etc that D365 does not know about, it creates it automatically.&lt;/p>
&lt;p>Most of the time this is fine, but consider when your business process requires a lot more data fields to be populated in the contact, this default process will create a contact that hasn&amp;rsquo;t got what your business needs. Forcing the contact creation away from this automation may be required.&lt;/p>
&lt;p>Users have an option under their personal settings which will mimic this settings, but this does it for everyone.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-77.png?w=728"
loading="lazy"
>&lt;/p>
&lt;p>Setting the AutoCreateContactOnPromote to false removes the option from users and no contacts are created automatically when emails etc are synced.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-78.png?w=907"
loading="lazy"
>&lt;/p>
&lt;h3 id="autotracksentfolderitems">AutoTrackSentFolderItems&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Setting value to TRUE will result in Server Side Sync auto tracking of emails from Sent Items.&lt;br>This setting only applies if the mailbox is configured to track "All Email Messages"&lt;br>Default value is set to False to preserve the existing behavior.&lt;br>To enable functionality on the organization "AutoTrackSentFolderItems" should be set to True.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.2.2.0840&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This setting works in hand with the selected option under &amp;ldquo;Select the email messages to track in D365&amp;rdquo; option under Personal Options.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-79.png?w=772"
loading="lazy"
>&lt;/p>
&lt;p>By default, sent emails are ignored, only picking up emails that arrive to send to D365.&lt;/p>
&lt;p>By marking the AutoTrackSentFolderItems to true, sent items will also be tracked, from the next sync, not retrospectively&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-80.png?w=386"
loading="lazy"
>&lt;/p>
&lt;h3 id="backgroundsendbatchsize">BackgroundSendBatchSize&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>10&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Integer&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Sets the number of email messages to download in one batch for the BackgroundSend API.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.583&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;h3 id="clientdisabletrackingforreplyforwardemails">ClientDisableTrackingForReplyForwardEmails&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Enables a user not to automatically track replies and forwarded email messages.&lt;br>Set this to&amp;nbsp;"True" to disable tracking replies and forwarded email messages.&amp;nbsp;&lt;br>&amp;nbsp;NOTE: This setting only applies to Dynamics 365 for Outlook (not Dynamics 365 App for Outlook).&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2903&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>When a user receives a reply to an email that has already been tracked, the reply will also be tracked by default. This is great for keeping the chains of emails all within D365. Unfortunately, this may lead to conversations being tracked that shouldn&amp;rsquo;t and give visibility to sensitive conversations - a manager receiving an email that was a complaint about a particular email that their report sent for example.&lt;/p>
&lt;p>Whilst this is mostly a training exercise, it can be quite embarrassing and this setting stops that. It does mean that you could lose out on a part of a conversation and rely on the user to track a response separately.&lt;/p>
&lt;p>This settings, as noted, only works with D365 for Outlook not the App for Outlook.&lt;/p>
&lt;h3 id="disableclientupdatenotification">DisableClientUpdateNotification&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Setting DisableClientUpdateNotification to true will disable the outlook client from checking for newer versions&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.0.0000.3027&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Only for the D365 for Outlook, will prevent the application checking for a new version. This will help if you are in a locked down environment and need the stability.&lt;/p>
&lt;p>With the D365 App for Outlook, it is a constant deployment rolled out with other fixes by Microsoft.&lt;/p>
&lt;h3 id="disableimplicitsharingofcommunicationactivities">DisableImplicitSharingOfCommunicationActivities&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Changing this to "True" will disable implicit sharing of records to recipients that are added to existing activities.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2903&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>When an email, meeting, phone call etc. is created and an internal user is included in the recipients list, it shares the record with them. This allows the internal user to have visibility of the record within D365.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-82.png?w=1024"
loading="lazy"
>&lt;/p>
&lt;p>If your security model has an issue with this, then this implicit sharing can be removed.&lt;/p>
&lt;p>Your model may restrict the visibility of activities depending on what record the activity is associated with in a team scenario. If the original recipient is no longer in the team, they should not have access to that information any longer. With the OOTB logic, this activity will still be visible.&lt;/p>
&lt;p>This email will still be in the recipients Outlook, nothing changes to the visibility in exchange, it is just the visibility in D365.&lt;/p>
&lt;h3 id="disablelookupmruonoutlookoffline">DisableLookupMruOnOutlookOffline&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>LookupMRUItems in UserEntityUISettings can cause a large data volume when going online,&lt;br>setting this to true will stop MRU's from syncing back ONLINE&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>6.1.0002.0106&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This one is not obvious to me and there is no information online. I&amp;rsquo;ll update when I find anything out&lt;/p>
&lt;h3 id="disablemapicaching">DisableMapiCaching&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>When this value is set to "True," users can still pin the views. However, the query is sent to the&lt;br>CRM Server to retrieve the results instead of to the local cache to prevent performance issues.&amp;nbsp;&amp;nbsp;&lt;br>&lt;br>Note&amp;nbsp;This value is not valid with CRM 2013.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2903&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This was present to prevent server performance issues, typically seen with on-premise solutions, when results are retrieved from the cache of the server, rather than direct from the database. It is unclear if still needed.&lt;/p>
&lt;h3 id="disablesmartmatching">DisableSmartMatching&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Disables the smart matching functionality and relies on the tracking token on the incoming e-mails for email tracking.&lt;br>False&amp;nbsp;- Enables smart matching.&lt;br>True&amp;nbsp;- Disables smart matching.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9688.583&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Smart Matching is how Microsoft works out that the email you just sent in belongs to a conversation that you have already synced, hence it will sync that email when it comes in.&lt;/p>
&lt;p>In System Settings, you have several options when it comes to matching. Correlation is the default, where it is using a conversation id on each email to match them. You can supplement this with a tracking token and/or smart matching.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-83.png?w=906"
loading="lazy"
>&lt;/p>
&lt;p>Token is generally used for support scenarios, to ensure any replies to an email are tracked against the same case.&lt;/p>
&lt;p>Smart matching does what it suggests, using keywords in the subject and an algorithm to determine if the email is linked to a previous conversation.&lt;/p>
&lt;p>Using the DisableSmartMatching flag does the same as un-ticking the box on the system settings, where conversation id and tracking tokens are relied on.&lt;/p>
&lt;h4 id="distinctphysicalandlogicaldeletesforexchangesync">DistinctPhysicalAndLogicalDeletesForExchangeSync&lt;/h4>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Server-Side synchronization needs a mechanism to distinguish between Logical and Physical deletes of entities in CRM&lt;br>False : No distinction between physical and logical deletes for exchange sync delete scenario&lt;br>True : Physical and logical deletes will be distinguished for exchange sync delete scenario&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.2.2.0840&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This is another where security takes over and users expectations can differ from the way Microsoft thinks it should work.&lt;/p>
&lt;p>If a user has been invited to a meeting, and it is recorded in D365, a copy of that exists within D365 and Exchange. If, for whatever reason, the user loses access (reas access) to that meeting in D365, the default behaviour would be to delete the copy in Exchange. Makes sense, to keep those in sync.&lt;/p>
&lt;p>With the DistinctPhysicalAndLogicalDeletesForExchangeSync set to true, lose of access to any activity does not mean that the activity is deleted in Exchange. Use this with DisableImplicitSharingOfCommunicationActivities to fully get control of activity access.&lt;/p>
&lt;h3 id="heading-1">&lt;/h3>
&lt;p>DoNotIgnoreInternalEmailToQueues&lt;/p>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>&lt;em>Version 5.0.9690.1533 to 8.2.2.1300:&lt;/em>&amp;nbsp;&lt;strong>False&lt;/strong>&lt;br>&lt;em>Version 8.2.2.1309 and higher:&lt;/em>&amp;nbsp;&lt;strong>True&lt;/strong>&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>If you disable the "Track email sent between CRM users as two activities" setting,&lt;br>email messages from a CRM user to a queue are not delivered.&lt;br>Additionally, if a workflow rule sends an email message to a queue,&lt;br>email messages that are sent by the workflow rule are not delivered.&lt;br>False&amp;nbsp;- Internal email messages to queues will not be delivered.&lt;br>True&amp;nbsp;- Internal email messages to queues will be delivered.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.1533&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This is used in combination with the Track emails sent between Dynamics 365 users as two activities available in the system settings&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-84.png?w=838"
loading="lazy"
>&lt;/p>
&lt;p>If you enable the Track as a separate option, normally any email from internal user to a queue mailbox will be ignored. This seems a weird consequence, but they have provided you with an override so that these internal mails are not ignored.&lt;/p>
&lt;h3 id="enableappointmentbroadcastingforoutlooksync">EnableAppointmentBroadcastingForOutlookSync&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>0&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Setting for Appointment broadcasting for Outlook Synchronization&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.0.1.121&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>I can&amp;rsquo;t find any information on this. Will update when I find out.&lt;/p>
&lt;h3 id="enablecrmstatecodeonoutlookcategory">EnableCrmStatecodeOnOutlookCategory&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>True&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Enables Statecode data on contact sync&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>6.1.0.581&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;h3 id="enablesssitemlevelmonitoring">EnableSssItemLevelMonitoring&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Setting value to True will enable a new dashboard accessible by users and administrators&lt;br>called Server-Side Synchronization Failures.&lt;br>This dashboard allows the owner of a mailbox to have information about all non-synched&lt;br>incoming/outgoing emails and also appointment, contact, and task (ACT) items.&lt;br>Information is provided for the reason items are not synchronized.&lt;br>Default value is set to False to preserve the existing behavior.&lt;br>You can use the ExchangeSyncIdMappingPersistenceTimeInDays setting to control how&lt;br>long the data for failed emails is retained.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.2.2.1661&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>There is a dashboard available to admin already called Server-Side Sync failures, without this setting. Not sure what this does, as the dashboard seems to be available regardless.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-85.png?w=1024"
loading="lazy"
>&lt;/p>
&lt;h3 id="exchangesyncidmappingpersistencetimeindays">ExchangeSyncIdMappingPersistenceTimeInDays&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>3&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>The number of days for which the ExchangeSyncIdMappings are to be persisted for failed emails.&lt;br>This setting is used in relation to the EnableSssItemLevelMonitoring setting.&lt;br>It is not recommended to increase this value higher than 7 days as it can lead&lt;br>to the table growing very large.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.2.2.2059&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This setting defines how many days of sync failures are kept, useful when you are troubleshooting, but table will get huge quickly, so only increase if you need to.&lt;/p>
&lt;h3 id="expiresubscriptionsindays">ExpireSubscriptionsInDays&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>90&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Max number of days before deleting inactive Outlook client subscriptions.&lt;br>We recommend you keep this to the default unless you absolutely need to change it,&lt;br>be mindful of keeping the tracking info too long, or deleting it too soon.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>6.0.0.0&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>On creating my second post in this series I came across several configurations that were not documented in the KB article and hence were missed when I wrote this.&lt;/p>
&lt;p>When you track an contact in Outlook, you are subscribing to changes made to those contacts in D365 so that they are mimicked in your Outlook. This is great, but each subscription is stored in a database record, hence impacting storage costs. There is a deletion service that works through the subscriptions and deletes these expired lines. after the value is reached, with an outlook Client refreshing it&amp;rsquo;s subcriptions as part of it&amp;rsquo;s sync routine.the&lt;/p>
&lt;h3 id="hideemailautotrackoptions">HideEmailAutoTrackOptions&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Default value is false, if it's set to True: do not show the following track options in&lt;br>Personal Options (Email): 'All email messages', 'Email messages from D365 Leads, Contacts&lt;br>and Accounts', 'Email messages from D365 records that are email enabled'&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.1639&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This setting goes one further to the one below by stripping out &amp;ldquo;All email messages&amp;rdquo;, &amp;ldquo;Email messages from D365 Leads, Contact and Accounts&amp;rdquo; and &amp;ldquo;Email messages from D365 records taht are email enabled&amp;rdquo;, just leaving you with the two below.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-46.png?w=737"
loading="lazy"
>&lt;/p>
&lt;h3 id="hidetrackalloption">HideTrackAllOption&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Removes “&lt;strong>All email messages&lt;/strong>” option from users’ Personal Options under Email&lt;br>tab&amp;nbsp;&lt;strong>Select the email messages to track in Microsoft Dynamics 365&lt;/strong>&amp;nbsp;area.&lt;br>False – "All email messages" option is shown in the dropdown.&lt;br>True – "All email messages" option is not shown in the dropdown.&lt;br>If a user already has "All email messages" selected, their synchronization option is&amp;nbsp;&lt;strong>not&lt;/strong>&amp;nbsp;updated&lt;br>in DB. Administrators will need to update this value via SDK.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.0.2.264&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Under personalisation settings for each user, they can decide to track all emails they receive from any source. Great for a shared mailbox or customer mailbox, but not for a normal user who receives spam and invites to cake sales etc.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-86.png?w=795"
loading="lazy"
>&lt;/p>
&lt;p>The default here is Email messages in response to D365 mail, but to stop users filling your D365 instance, setting the HideTrackAllOption to true will remove that top option.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-87.png?w=743"
loading="lazy"
>&lt;/p>
&lt;p>Any users that had this setting prior to it&amp;rsquo;s removal need to be updated manually or via the SDK.&lt;/p>
&lt;h3 id="ignorecopieditemsinsssformailbox">IgnoreCopiedItemsInSSSForMailbox&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Ignore creating duplicate for copied items for Server Side Sync&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.11129&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Normally, when an email or meeting or task is synced, it doesn&amp;rsquo;t matter where that content came from. If it appears new, it will be created new, even if it is a copy of another item. This will reduce the amount of synced items but may be a concern for your environment.&lt;/p>
&lt;h3 id="mailboxstatisticspersistencetimeindays">MailboxStatisticsPersistenceTimeInDays&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>3&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>If value is 0, dont store ANY MailboxStatistics Data, if the value is greater than zero then&lt;br>store that number of days statistics data. Max value arbitrarily chosen at 1 year,&lt;br>this generates at lot of data so 1 year should be plenty of time&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.0.0.1088&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>The Mailbox statistics records how frequently a mailbox is accessed and synced. This way, the more active mailboxes are synced more regularly. A mailbox that is infrequently used will be checked less regularly.&lt;/p>
&lt;p>On a high user system, with SSS on, it can get populated quickly, so 3 days will normally be appropriate.&lt;/p>
&lt;h3 id="outlookclientemailtaggerenabled">OutlookClientEmailTaggerEnabled&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>here are 3 values for this Boolean setting - true, false, and NULL (which is the value when NOT set).&lt;br>True: Will override any and all client registry setting to True.&lt;br>False: Will override any and all client registry setting to False.&lt;br>NULL: If the setting is NULL the outlook clients will use whatever is in the registry of the client.&lt;br>TO SET THIS VALUE TO NULL YOU WILL NEED TO CLICK EDIT, THEN REMOVE THE VALUE&lt;br>TO HAVE IT DEFAULT TO NULL.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.0.1.121&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;h3 id="outlooksyncdatasubscriptionclientsbatchsize">OutlookSyncDataSubscriptionClientsBatchSize&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>100&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>This setting is used to determine how many record changes (deletes, inserts, and updates)&lt;br>to send back to a syncing client for each request.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>7.1.0.1059&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;h3 id="overridetrackincrmbehaviour">OverrideTrackInCrmBehaviour&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>0&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>When this option is Enabled, the ‘Track in CRM’ button functions as the Set Regarding&lt;br>button in Dynamics 365 for Outlook. In Dynamics 365 App for Outlook,&lt;br>‘Track without regarding’ command is not displayed, with Set Regarding as&lt;br>the only way to synchronize Outlook items to Dynamics 365.&lt;br>0 - Normal behavior of the "Track in CRM" button not having to set a Regarding record&lt;br>in Dynamics 365 for Outlook.&lt;br>‘Track without regarding’ command is displayed in Dynamics 365 App for Outlook.&lt;br>1 - The ‘Track in CRM’ button functions as the ‘Set Regarding’ button, and makes you&lt;br>select a regarding record in Dynamics 365 for Outlook.&lt;br>In Dynamics 365 App for Outlook, ‘Track without regarding’ command is not displayed,&lt;br>with Set Regarding as the only way to synchronize Outlook items to Dynamics 365.&lt;br>NOTE: This setting applies to&amp;nbsp;both&amp;nbsp;Dynamics 365 for Outlook and Dynamics 365 App for Outlook.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.6200&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Normally, a user can track an activity to D365 without associating with a record, the Set regarding. This could lead activities in your tenant not associated with a record, orphaned. Depending on your business requirements, disabling this feature could be required.&lt;/p>
&lt;p>Normally, under the &amp;hellip; under Not Tracked, the user has an option to Track without Regarding&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-88.png?w=384"
loading="lazy"
>&lt;/p>
&lt;p>Setting OverrideTrackInCrmBehaviour to 1 will override this behaviour, removing the ellipses button altogether. The user has to establish a link to an existing record to sync the email or activity.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-89.png?w=300"
loading="lazy"
>&lt;/p>
&lt;h3 id="overridev5senderconflictresolution">OverrideV5SenderConflictResolution&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>When multiple records with the same email address exist in the Dynamics CRM Organization&lt;br>and email is automatically tracked, the email address is resolved to the record for the owner&lt;br>record that was created first. This option lets you override that functionality.&lt;br>False&amp;nbsp;- E-mails are tracked to the first record created.&lt;br>True&amp;nbsp;- E-mails are not tracked automatically if there are multiple records&lt;br>with the same email address.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2243&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Michael Sulz has a good write up on this, &lt;a class="link" href="https://michaelsulz.wordpress.com/tag/crm/" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;p>Normally, if there are 2 or more contacts with the same email address (data quality is always a problem, however much you take care of it, though &lt;a class="link" href="https://www.data-8.co.uk/" target="_blank" rel="noopener"
>data8&lt;/a> do a real good job of removing duplicates and improving your data) the contact chosen is the first contact owned by the syncing user, sorted by create date or the first created if that doesn&amp;rsquo;t match.&lt;/p>
&lt;p>Setting this option to true will force the user to make a decision and not sync the email automatically.&lt;/p>
&lt;h3 id="restrictirmemailitems">RestrictIRMEmailItems&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Setting value to TRUE will result in Server Side Sync NOT synchronizing ALL emails&lt;br>that are marked as IRM emails.&lt;br>Default value is set to False to preserve the existing behavior.&lt;br>To enable this restriction on the organization " RestrictIRMEmailItems " should be set to True.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.2.2.0840&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Bhavesh Shastri has a great write up of this configuration &lt;a class="link" href="https://community.dynamics.com/crm/b/crminthefield/posts/dynamics-365-customer-engagement-how-to-choose-system-settings-and-personal-options-for-automatic-email-tracking" target="_blank" rel="noopener"
>here&lt;/a>&lt;/p>
&lt;p>Restricted messages, those that the sender has marked as any of the restricted types in Azure information Protection, may not be suitable to be included in your D365 system.&lt;/p>
&lt;p>If you set his flag to true, the user will not be able to sync those that are protected and will be given an error message if they try to.&lt;/p>
&lt;h3 id="securitysettingforemail">SecuritySettingForEmail&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Number&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>1: Display a Warning Message And give an option to open -&lt;br>2: Display a Warning Message and do not give an option to open&lt;br>3: Do not display a Warning Message and do not give any option to open.&lt;br>This setting is NOT SUPPORTED IN CRM2013 as of build 809&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.3731&lt;br>6.1.0.581&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>The majority of emails that a user receives and hence sync to D365 contain HTML to some degree, whether it is simple formatting or full on marketing emails.&lt;/p>
&lt;p>In all scenarios, the interface presents a stripped down version of the email, but formatting etc will be lost.&lt;/p>
&lt;p>There is a risk when these are displayed in all their glory in D365, that parts of the email could be nefarious, including scripts etc that could include phishing or other attacks. Microsoft by default warns the user that this is the case, but allows the user to click through to the content, putting the decision in the users&amp;rsquo; hands.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-90.png?w=722"
loading="lazy"
>&lt;/p>
&lt;p>If you change the setting to 2, the link to the full content is removed&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-91.png?w=679"
loading="lazy"
>&lt;/p>
&lt;p>Changing the setting to 3 removes the message and always shows the full version of the email&lt;/p>
&lt;h3 id="sendemailsynchronously">SendEmailSynchronously&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>0&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Int&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>If you have a plugin registered on the email send flow, you&amp;nbsp;should&amp;nbsp;change this setting to&amp;nbsp;"1."&amp;nbsp;&lt;br>0&amp;nbsp;- Email is sent asynchronously.&lt;br>1&amp;nbsp;- Email is sent synchronously.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2720&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Depending on your logic, you may interact by workflow when an email is sent via Outlook. This setting moves the send email to a synchronous operation rather than asynchronous, allowing a more immediate interaction with the email. This may have a performance impact on the user in Outlook.&lt;/p>
&lt;h3 id="sortemailbyreceivedon">SortEmailByReceivedOn&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>When the Activities tab of the social pane is show, the data ordered by the 'modifiedon'&lt;br>date in descending order, toggling this setting to True will enable the social pane to sort&lt;br>emails by RecievedOn Desc instead of modifiedon&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.0.1.79&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>I am not sure that this is a problem any more, in Social pane in D365 we have a lot of options for searching, but back in the legacy UI this allowed you to change the email sorting from the date the email was edited or added to D365 to the date the email was received. This could be several days difference, so it could give a different perspective to the conversation.&lt;/p>
&lt;h3 id="traceexchangesyncdata">TraceExchangeSyncData&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>true&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Enables exchange sync tracing&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>6.0.0.809&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Logging of the sync data is essential for any troubleshooting, but it adds to the size of your database. With the separation of log and data in storage costs, I am not sure this should ever be turned off if you are using SSS.&lt;/p>
&lt;h3 id="trackappointmentsfromnonorganizer">TrackAppointmentsFromNonOrganizer&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>True&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Enabled users to track appointments organized by another Dynamics 365 user via&lt;br>Dynamics 365 App for Outlook.&lt;br>False &amp;nbsp;– &amp;nbsp;Dynamics 365 App for Outlook and Server-Side Synchronization users cannot track&lt;br>Outlook appointments whose organizer is a Dynamics 365 user.&lt;br>True &amp;nbsp;– &amp;nbsp;Dynamics 365 App for Outlook and Server-Side Synchronization users can track Outlook&lt;br>appointments whose organizer is a Dynamics 365 user.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>9.1.0.0294&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>You can always track a meeting if it was sent from an external user and by default, you can track any appointment where the organiser is a D365 user. This setting prevents the user from tracking an appointment if it is not them organising it.&lt;/p>
&lt;h3 id="trackcategorizeditems">TrackCategorizedItems&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>True&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Setting value to False will remove the category tracking flag and functionality.&lt;br>Default value is set to True to allow category tracking and tracking status visibility for users&lt;br>whom do not use Dynamics 365 for Outlook or Dynamics 365 App for Outlook.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.2.2.0840&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Using &lt;a class="link" href="https://docs.microsoft.com/en-us/dynamics365/customer-engagement/admin/use-outlook-category-track-appointments-emails" target="_blank" rel="noopener"
>Category based tracking&lt;/a> is a great way to allow users to track multiple emails at once. In the App for Outlook, this is the only way.&lt;/p>
&lt;p>With the OOTB behaviour, the user gets a new category added and is able to select multiple emails to sync. It also appears as a great indicator in Outlook that the activity is synced.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-92.png?w=733"
loading="lazy"
>&lt;/p>
&lt;p>Setting the flag to false removes this category and ability.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-93.png?w=769"
loading="lazy"
>&lt;/p>
&lt;p>Be warned on this, if you leave any item with the category on it after you have disabled this functionality, re-enabling the functionality will mean that these items will be synced. Also, this category doesn&amp;rsquo;t respect the fact you upgrade. An email with the category that was synced to an on premise version will create a duplicate if that user is moved to the online version and the originating email was migrated as part of the data migration from on-prem to online.&lt;/p>
&lt;h3 id="usecrmorganizerforemptyexchangeorganizer">UseCrmOrganizerForEmptyExchangeOrganizer&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Use the CRM Organizer of an Appointment if the Exchange Organizer doesn't exist.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.1.1.1020&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>I think this is more to do with rare cases when the sync doesn&amp;rsquo;t work correctly, but another one that I can not find any information for.&lt;/p>
&lt;h3 id="usefilteringmethodofsyncingmailboxonlyforcorrelation">UseFilteringMethodOfSyncingMailboxOnlyForCorrelation&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>This is for controlling which users’ filtering settings will be used &amp;nbsp;for correlation.&amp;nbsp;&lt;br>False &amp;nbsp;– filtering method of all recipients of the email will be checked to decide if any&lt;br>user/queue accepts email or not.&lt;br>True &amp;nbsp;– filtering setting of user who synced email to CRM will be used. Filtering &amp;nbsp;setting&lt;br>of other recipients of the emails will be ignored.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>8.2&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>Each user has a seperate filter list to decide which emails are synced to D365. These can be various settings on what that individual user requires.&lt;/p>
&lt;p>The default for this setting, the standard OOTB behaviour, is false, where any user can sync this email if it matches their settings. True means that the user who created the email or synced it will be able to have the email included in the selection for the filter. It is in effect an additional filter for the user to only include emails I have created.&lt;/p>
&lt;h3 id="useplaintextforemailtemplatebody">UsePlainTextForEmailTemplateBody&lt;/h3>
&lt;table>&lt;tbody>&lt;tr>&lt;td>&lt;strong>Default Value&lt;/strong>&lt;/td>&lt;td>False&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Type&lt;/strong>&lt;/td>&lt;td>Boolean&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Description&lt;/strong>&lt;/td>&lt;td>Changes the Email Template to use plain text where otherwise text with the following&lt;br>symbols would not appear &amp;lt;text&amp;gt;.&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Min Version&lt;/strong>&lt;/td>&lt;td>5.0.9690.2720&lt;/td>&lt;/tr>&lt;tr>&lt;td>&lt;strong>Max Version&lt;/strong>&lt;/td>&lt;td>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>
&lt;p>This is one of the older settings, presumably when people had email clients that could not handle html formatted text.&lt;/p></description></item><item><title>Cloning Flows: Location triggers for everyone</title><link>https://linked365.blog/2019/09/14/cloning-flows-location-triggers-for-everyone/</link><pubDate>Sat, 14 Sep 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/09/14/cloning-flows-location-triggers-for-everyone/</guid><description>&lt;img src="https://linked365.blog/images/2019/09-image-69.png" alt="Featured image of post Cloning Flows: Location triggers for everyone" />&lt;p>Sometimes ideas don&amp;rsquo;t work out. This is one of these times. But the reason I blog is to learn, expand my knowledge of the PowerPlatform, expand my knowledge of components outside of it. So, I figured I would blog about my failure, learning is learning. As I started testing the flow again, moving environments etc, it started working. I guess this is down to the location trigger being a work in progress. Moral of the story: If it is broke last month, try again this month.&lt;/p>
&lt;p>Back in July, I started working on this scenario, but couldn&amp;rsquo;t get it working. I noticed &lt;a class="link" href="https://twitter.com/Flow_joe_" target="_blank" rel="noopener"
>@Flow_Joe_&lt;/a> &amp;amp; &lt;a class="link" href="http://twitter.com/JonJLevesque" target="_blank" rel="noopener"
>@JonJLevesque&lt;/a> did a &lt;a class="link" href="https://www.youtube.com/watch?v=J0vZCotp9Pw&amp;amp;t=1493s" target="_blank" rel="noopener"
>video walkthrough&lt;/a> of using the Geofence trigger to send out a summary of the customer when a sales person enters an area, which reminded me of my failure, hence why I have written it up. While from Joe &amp;amp; Jon&amp;rsquo;s video shows us how easy it is to create a flow, for Salespeople in general, I think this is too far. You can not expect a Salesperson to have any interest in creating flows to do this, you can expect them to click a button on a form within their D365 application.&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Scenario&lt;/li>
&lt;li>Creating the Flow button&lt;/li>
&lt;li>Cloning the Flow&lt;/li>
&lt;li>Outcome&lt;/li>
&lt;/ul>
&lt;h2 id="the-scenario">The Scenario&lt;/h2>
&lt;p>Numerous times when I have been a customer, a salesperson would come to us not knowing that we have several major cases logged with them against their product. This is mainly down to lazy sales people (I know, they don&amp;rsquo;t exist), but it would be awesome for the salesperson to get a summary of the account when they get in the door of a customer. The number of support cases, a list of the open opportunities and orders, any complaints that have been logged. All of this information is available to the salesperson via the D365 mobile app, but it would be good to ensure that they get this information and are less likely to get caught out by a customer venting at them for 5 critical bugs that have been sat around for a month.&lt;/p>
&lt;h2 id="the-solution">The Solution&lt;/h2>
&lt;p>Flow has a new trigger, still in preview, Location, which is triggered via the Flow application when an user enters or exists an area. This is perfect for our scenario, stick a GeoFence around a customers location, when the user enters the area, it gets triggered. Look up the Customer, format an email and send it to the user.&lt;/p>
&lt;p>Flow is user friendly, a low code solution, but you can not expect a salesperson to create a flow for each account they want to create this trigger for. What can be done, is put a button on a form, automatically create a Flow for the user against the account they have selected which would then be triggered when the user enters the location.&lt;/p>
&lt;p>There are 2 separate series of flows that are required, firstly to start with an action from the user on the account record, which triggers cloning of a template.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-31.png"
loading="lazy"
>&lt;/p>
&lt;p>The second series is the clone of the template, which triggers sending the salesperson the relevant information when they enter the customers property.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-32.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="creating-a-flow-button">Creating a Flow Button&lt;/h2>
&lt;p>Starting with a CDS &amp;ldquo;When a record is selected&amp;rdquo; trigger, configure it to be used when an account is selected.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-33.png?w=514"
loading="lazy"
>&lt;/p>
&lt;p>The next step is to retrieve who is running this flow. As mentioned, it will publish this button on a Account form, so it is essential to know who is running this, so an email can be sent to them. The account information and who the user is is sent as the body to a HTTP Post trigger, which is the next flow in the chain.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-39.png?w=502"
loading="lazy"
>&lt;/p>
&lt;p>An HTTP trigger is used because the next Flow requires enhanced access. An admin user needs to clone a Flow, which you would not want a normal user to be able to do. The admin is used as well to ensure any runs that happen are legitimate. The admin or sys account shouldn&amp;rsquo;t belong to someone who could have Flow in their pocket.&lt;/p>
&lt;p>To have the URL to send to, the next Flow needs to be created first, but just to show where this button appears within the D365 interface. The first time we run it, there are few confirmations that you need to do, finally you can run the flow.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-button-on-account.gif?w=1024"
loading="lazy"
>&lt;/p>
&lt;h2 id="cloning-the-flow">Cloning the Flow&lt;/h2>
&lt;p>This flow clones an existing template, tweak it slightly and gets it up and running as the user.&lt;/p>
&lt;p>Starting with an HTTP Trigger, I use a sample payload to build the schema.&lt;/p>
&lt;p>Next is retrieving the account. As the account id is passed in from the calling Flow, a simple Get Record is used.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-40.png?w=516"
loading="lazy"
>&lt;/p>
&lt;p>Next, configure the name of the Flow that will be created, making it unique for the user by adding their email address in. A flow definition string is also initialised for later&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-41.png?w=546"
loading="lazy"
>&lt;/p>
&lt;p>In this Flow, the user that called it from the button is needed, so it retrieves the profile using the Office 365 Users action.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-43.png?w=539"
loading="lazy"
>&lt;/p>
&lt;p>Next, retrieve my template flow. Flow has several actions around management of Flows, which are incredibly useful to a Flow administrator. The template flow is a simple flow which has a location trigger and a call to a http trigger to call a secondary flow. I will discuss later the detail about this.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-44.png?w=502"
loading="lazy"
>&lt;/p>
&lt;p>The next couple of actions try to determine if a flow with the FlowName defined already exists, firstly by getting a list of all my flows (as an admin) then getting a list of Flows in the organisation, then filtering it with the flowname that was defined in the initial steps&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-45.png?w=701"
loading="lazy"
>&lt;/p>
&lt;p>If there is a flow already, just stop. If not, carry on &amp;amp; clone the template flow.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-46.png?w=1024"
loading="lazy"
>&lt;/p>
&lt;h2 id="the-template">The Template&lt;/h2>
&lt;p>The Log Template is a very easy, small location trigger with an HTTP call action. The HTTP call passes in the user&amp;rsquo;s location and the account id and the user who started the process. Both email and account will be swapped out as part of the clone.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-63.png?w=523"
loading="lazy"
>&lt;/p>
&lt;p>The trigger region is essential for any location trigger. It triggers this one of the Microsoft campus in Redmond. Someday I will be fortunate to go to the motherland. I chose this as it is not likely that the user would have them as a client, but it doesn&amp;rsquo;t really matter where you chose, as what you need is the latitude and longitude from it so you can replace it when you clone the flow.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-48.png?w=1024"
loading="lazy"
>&lt;/p>
&lt;p>If you click on the peek code button against the trigger, it shows a JSON representation of the trigger. The latitude and longitude are that of the Microsoft office and this is the bit I need to replace&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-50.png?w=491"
loading="lazy"
>&lt;/p>
&lt;h2 id="cloning-the-flow-part-2">Cloning the Flow (part 2)&lt;/h2>
&lt;p>All a Flow is a JSON file. Obviously, how it is rendered and how the hooks and actions work are the power, but the definition is a JSON file. Using this knowledge, we can create a new version of the template, with a location specific to the account.&lt;/p>
&lt;p>The template in all it&amp;rsquo;s glory is below. Just using simple find / replace, we tweak it to the specific location, account and user.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;$schema&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;contentVersion&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1.0.0.0&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;parameters&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;$authentication&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;defaultValue&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;SecureObject&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;triggers&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;manual&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Request&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;kind&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Geofence&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;inputs&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;parameters&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;serializedGeofence&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Circle&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;latitude&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">47.64343469631714&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;longitude&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">-122.14205669389771&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;radius&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">35&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;actions&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;HTTP&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;runAfter&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Initialize\_Email\_Variable&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;Succeeded&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">\&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Http&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;inputs&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;method&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;POST&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;uri&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://prod-68.westeurope.logic.azure.com:443/workflows/&amp;lt;GUID&amp;gt;/triggers/manual/paths/invoke?api-version=2016-06-01&amp;amp;sp=%2Ftriggers%2Fmanual%2Frun&amp;amp;sv=1.0&amp;amp;sig=&amp;lt;SIG&amp;gt;-JQQvYT0&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;body&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;lat&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;@{triggerBody()?\[&amp;#39;currentLatitude&amp;#39;\]}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;long&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;@{triggerBody()?\[&amp;#39;currentLongitude&amp;#39;\]}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;@{variables(&amp;#39;Email&amp;#39;)}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;account&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;@{variables(&amp;#39;accountId&amp;#39;)}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Initialize\_Account\_Variable&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;runAfter&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;InitializeVariable&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;inputs&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;variables&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;accountId&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;String&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;value&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;accountId&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">\&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Initialize\_Email\_Variable&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;runAfter&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Initialize\_Account\_Variable&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;Succeeded&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">\&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;InitializeVariable&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;inputs&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;variables&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Email&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;String&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;value&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;email&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">\&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;outputs&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Back on the clone flow, the next step is to convert the template to a string. This makes it easier to replace the latitude, longitude etc. with the ones we want.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-51.png?w=488"
loading="lazy"
>&lt;/p>
&lt;p>On the account OOTB record there is a latitude and longitude. This data is not normally populated, but it is used by Field Service and other applications. I used Field Service to populate it using the Geo Code button.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-52.png?w=356"
loading="lazy"
>&lt;/p>
&lt;p>As you can see from the above, Field service populates both latitude and longitude to 5 decimal places. This is common precision when you use any mapping software such as Google. so I am not sure why if you do the same by the Flow trigger you get precision to 15 dp for latitude and 17 for longitude.&lt;/p>
&lt;p>The next 2 steps are because of me trying to get the flow to work. One of my thoughts was that the flow was expecting the all 15 of the decimal places to be populated, so these steps pad out the number you have against the account with additional numbers.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-53.png?w=517"
loading="lazy"
>&lt;/p>
&lt;p>The expression is the same for both&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">concat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">body&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Get&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Account&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">address1&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_latitude&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">]),&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="mi">111111&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The next step replaces the newly calculated values for latitude and longitude in the JSON definition&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-54.png?w=500"
loading="lazy"
>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">replace&lt;/span>&lt;span class="p">(&lt;/span> &lt;span class="nf">variables&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">flowdefstring&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="mf">47.643434696317136&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nf">outputs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Replace&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Lat&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)),&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mf">122.14205669389771&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nf">outputs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Replace&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Long&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The accountid is also replaced. This is used in the cloned flow to define which account the user selected. The trigger only gives you the user&amp;rsquo;s current location, not the centre of the circle you configured. You could use these values &amp;amp; find the account, with difficulty, unless there is something I am missing. I prefer to add a variable in the clone, which is the account id.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-60.png?w=486"
loading="lazy"
>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">outputs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Replace&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Lat&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Long&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">accountId&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nf">triggerBody&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Account&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The same with the email to send to, it should be the user who triggers the geofence, but seems to be the person who is the admin. As I clone the Flow with an admin account then add the user as an admin, it runs under the admin account.&lt;/p>
&lt;p>There is enough info now to create this flow. Using the Create Flow action, the new flow is created and up and running.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-68.png?w=497"
loading="lazy"
>&lt;/p>
&lt;p>I use a JSON expression to convert the string I have used to find / replace the latitude, longitude etc. to ensure the Flow is created with JSON.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">json&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">variables&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">flowdefstring&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The final step is to add a Flow owner. As the sales person who triggered the flow is who it should trigger on, make them the owner, so it should run under their context.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-56.png?w=524"
loading="lazy"
>&lt;/p>
&lt;h2 id="outcome-v1">Outcome V1&lt;/h2>
&lt;h4 id="ignore-this-bit-if-you-want-to-avoid-the-author-moaning-about-stuff-that-doesnt-work">Ignore this bit if you want to avoid the author moaning about stuff that doesn&amp;rsquo;t work.&lt;/h4>
&lt;p>If I run the whole flow, I do generate a new Flow.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-57.png?w=912"
loading="lazy"
>&lt;/p>
&lt;p>Going into what was generated, using peek code again, you can see that the Microsoft location has been replaced with the Avanade office&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-58.png?w=630"
loading="lazy"
>&lt;/p>
&lt;p>The trigger is active, but this is where it stops. I can not get this to trigger to fire. Changing the location to my home, going for a walk, coming back doesn&amp;rsquo;t trigger it.&lt;/p>
&lt;p>If I don&amp;rsquo;t put in the padding for the latitude and longitude, it doesnt trigger.&lt;/p>
&lt;p>If I clone from my location, not changing the latitude and longitude, still the trigger doesn&amp;rsquo;t fire.&lt;/p>
&lt;p>If I configure a new trigger from scratch, that works.&lt;/p>
&lt;p>Everything about the trigger look the same when you get it in code view, but there must be something different.&lt;/p>
&lt;p>This is where I started reaching out, I &lt;a class="link" href="https://twitter.com/linked365/status/1153218060632952834" target="_blank" rel="noopener"
>tweeted&lt;/a> about it to the gods of flow and asked in the Flow &lt;a class="link" href="https://powerusers.microsoft.com/t5/Building-Flows/Cloning-a-flow-Location-Trigger/m-p/330343" target="_blank" rel="noopener"
>forum&lt;/a> where I did get a response, basically saying the same, and that the location trigger is in preview.&lt;/p>
&lt;p>So, if you have got this far, how do I fix it?&lt;/p>
&lt;h2 id="outcome-v2">Outcome V2&lt;/h2>
&lt;p>Like I said at the outset, this didn&amp;rsquo;t work for me. Frustration set in, and I forgot the idea. But, as I was putting together this blog post, re-deploying the components as my demo system had expired, it worked!&lt;/p>
&lt;p>So, moving on, we need to sent an email to the user with the playbook for the account. I want to list the last 5 critical cases, last 5 open opportunities, last 5 notes and any description the user has put in.&lt;/p>
&lt;p>It triggers an HTTP request, the schema defined by a sample payload, but contains who triggered the workflow and which account.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-62.png?w=501"
loading="lazy"
>&lt;/p>
&lt;p>Then, a great time for a parallel branch. The Flow retrieves the cases, notes and opportunities in a parallel branch.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-64.png?w=1024"
loading="lazy"
>&lt;/p>
&lt;p>Each branch does a similar thing, looking at the Notes branch, firstly retrieve the records with a CDS List Records action, using an OData filter and order by, return the top 5 only.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-65.png?w=497"
loading="lazy"
>&lt;/p>
&lt;p>Next, put this in an HTML table, selecting the output from the Get Notes action. I select Advanced option, then Custom columns, this way I can define the order and which columns I want to display.&lt;/p>
&lt;p>The final step is to send an email&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-66.png?w=494"
loading="lazy"
>&lt;/p>
&lt;p>Obviously, this can be customised to your business need, but my example list the cases, opportunities &amp;amp; notes, and reminds them to fill in a contact report.&lt;/p>
&lt;h2 id="summary">Summary&lt;/h2>
&lt;p>So, the user selects a button on an account form, which allows them to receive updates about one of their customers when they enter the location of the account. Easy.&lt;/p>
&lt;p>I tested this with my home address and with a different user and you can see that I get the email through. Veronica is in the US, I wasn&amp;rsquo;t up at 1am writing blogs &amp;amp; fixing Flows.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-67.png?w=1024"
loading="lazy"
>&lt;/p>
&lt;p>You can also see that Flow notifies the user that it has made them an administrator on a Flow.&lt;/p>
&lt;p>This Flow starts with a Flow button on a record, making it a user-initiated process. It could be triggered off a record creation process - If the user follows an Account, create this automation for them, as long as they have opted in.&lt;/p>
&lt;p>There is location tracking in the Field Service application, but that requires the Field Service mobile app and not suited to a Sales person. They just need to install the Flow app on their device and forget it is there.&lt;/p></description></item><item><title>AI Builder - Text AI</title><link>https://linked365.blog/2019/09/05/ai-builder-text-ai/</link><pubDate>Thu, 05 Sep 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/09/05/ai-builder-text-ai/</guid><description>&lt;img src="https://linked365.blog/images/2019/09-image-30.png" alt="Featured image of post AI Builder - Text AI" />&lt;p>My blogging journey started with using &lt;a class="link" href="https://www.luis.ai" target="_blank" rel="noopener"
>LUIS&lt;/a>, one of Microsoft&amp;rsquo;s Cognitive Services to automate case assignment. This &lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365-part-1/" >blog&lt;/a> goes into detail about how this all hung together, using a model defined in LUIS, calling the LUIS endpoint when a new cases are created and classifying the case, by the subject, with the result from the call.&lt;/p>
&lt;p>After my summer break (sorry, but family etc comes first) I thought I would revisit this scenario, but using one of Microsoft&amp;rsquo;s shiny, new AI Builder capabilities, &lt;a class="link" href="https://docs.microsoft.com/en-us/ai-builder/text-classification-overview" target="_blank" rel="noopener"
>Text Classification AI Model&lt;/a>.&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Scenario&lt;/li>
&lt;li>Training your Model&lt;/li>
&lt;li>Getting Data&lt;/li>
&lt;li>Publishing the Model&lt;/li>
&lt;li>Using the Tags&lt;/li>
&lt;/ul>
&lt;h2 id="the-scenario">The Scenario&lt;/h2>
&lt;p>In my first blog, I went through the scenario, so not wanting to repeat myself, but for the lazy who don&amp;rsquo;t want to click &lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365-part-1/" >through&lt;/a>&amp;hellip;..&lt;/p>
&lt;p>Big Energy is a supplier of energy products to end users. They have a call centre which handles any query form the customer. As a perceived leader in the sector, it is always wiling to use the latest technology to allow users to interact with them, which reduces the pressure on the customer support centre.&lt;/p>
&lt;p>Big Energy has a mail box configured to accept customer emails about anything and, rather than have a group of 1st line support employees filtering out and categorising the emails based on the content, want to use cognitive services to improve the process of getting the email (the generated case) to the right team.&lt;/p>
&lt;h2 id="using-ai-to-file-the-case">Using AI to file the case&lt;/h2>
&lt;p>LUIS does a great job of this, with a BA providing sample utterances for the model and training it.&lt;/p>
&lt;p>Text Classification AI Model does it slightly differently. The model expects users to provide data (in the CDS) in the form of text blocks and representative tags for the data. Both need to be in the same entity in CDS.&lt;/p>
&lt;p>On a standard Case record, the classification or tag is the subject field. This is a parent record of Case and the tag would be the name of the subject. As subject and case are separate entities, the Text Classification AI model will not work. A field, be it a calculated one, has to be introduced to enable the classification AI to work. Adding data to an entity from a parent entity breaks my &lt;a class="link" href="https://en.wikipedia.org/wiki/Database_normalization" target="_blank" rel="noopener"
>Third Normal Form&lt;/a> training (anyone remember that? Is it still a thing?).&lt;/p>
&lt;p>I have raised this issue as a new &lt;a class="link" href="https://powerusers.microsoft.com/t5/PowerApps-Ideas/Parent-fields-available-as-tags-for-Text-Classification/idi-p/354238" target="_blank" rel="noopener"
>idea&lt;/a> on the PowerApps ideas forum, go there and give it a vote!&lt;/p>
&lt;p>The new logic for our AI model is that the AI will classify the incoming case, adding a tag. This will trigger a flow, changing the subject of the linked case accordingly. This will trigger re-routing of the case like it did in the original LUIS method.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-30.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="training-your-ai">Training your AI&lt;/h2>
&lt;p>With any AI model, it needs training. The AI needs to separate the wheat from the chaff. Creating a model is simple in PowerApps.&lt;/p>
&lt;p>Start at &lt;a class="link" href="https://make.powerapps.com" target="_blank" rel="noopener"
>make.powerapps.com&lt;/a> and select AI Builder, then Build&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-1.png"
loading="lazy"
>&lt;/p>
&lt;p>There are 4 options here&lt;/p>
&lt;p>Binary Classification is useful to give a yes / no decision on whether data meets certain criteria. The criteria can be up to 55 fields on the same entity. For example, is a lead with a low current credit limit, high current account value, no kids but has a pink toe nail (shout out to &lt;a class="link" href="https://twitter.com/Themarkchristie" target="_blank" rel="noopener"
>Mark Christie&lt;/a>) likely to get approved for a new loan?&lt;/p>
&lt;p>Form processing is intended to assist users in automated scanned documents to prevent re-keying. An example would be any forms hand written as part of a sales or service process (before you convert to a PowerApp obviously).&lt;/p>
&lt;p>Object detection assists in classification of items, be in types of drink, crisps or bikes, etc.&lt;/p>
&lt;p>Text classification decides on a tag for a block of text, for example, a user could enter a review of a product online and text classification could understand what product it was for or whether it is a positive review.&lt;/p>
&lt;p>All 4 of these have origins in the Cognitive services provided by Azure, LUIS being the big brother of Text Classification.&lt;/p>
&lt;p>Ensure you are in the correct environment. Text Classification only works on data within your CDS environment, so don&amp;rsquo;t expect to reach out to your on-premise SQL server. There are ways to bring data into CDS, not in scope for this discussion.&lt;/p>
&lt;p>Selecting Text Classification displays a form to give you more understanding, and it is here that you name your model&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-2.png"
loading="lazy"
>&lt;/p>
&lt;p>Hit Create and then Select Text. This will list all your entities in your CDS environment (in my case, a D365 demo environment).&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-3.png"
loading="lazy"
>&lt;/p>
&lt;p>Select the entity you want, Case for our PoC.&lt;/p>
&lt;p>The interface will then list all the fields suitable for the AI model, namely anything that is a text field. I chose the description field, which is typically the email that the user enters when emailing in a case to the support department.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-4.png"
loading="lazy"
>&lt;/p>
&lt;p>Hit the Select Field button and it will present you with a preview of the data in that table.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-5.png"
loading="lazy"
>&lt;/p>
&lt;p>The next screen is to select your tags. This needs to be in the same table, and as already discussed, is a bit of a limitation to the AI builder. Less normalised data is more common in Canvas apps or SharePoint linked apps, but for structured data environments with relationships and normalised data this is a limitation that will hopefully be removed as Text Classification matures.&lt;/p>
&lt;p>Also, option sets are not available, again another common categorisation technique. Multi-select option sets are an ideal tagging method too. Assume that this will come in time.&lt;/p>
&lt;p>For my PoC, I created a new field, put it on the Case form and started filling it in for a few records.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-6.png"
loading="lazy"
>&lt;/p>
&lt;p>Select the separator. If your tag field contains multiple tags, separated by a comma or semi-colon, this is where you configure it.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-7.png"
loading="lazy"
>&lt;/p>
&lt;p>It also gives you a preview of what the tags the AI build would find using your chosen method. You can see in the No separator option, &amp;ldquo;printer; 3d&amp;rdquo; is one tag, rather than the assume 2 tags as displayed if semi-colon is selected. This depends on your data.&lt;/p>
&lt;p>The next page displays a review for your data and the tags that the AI builder finds.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-8.png"
loading="lazy"
>&lt;/p>
&lt;p>Next, select a language for the text field dependent on your data.&lt;/p>
&lt;p>Once selected, train your model. This is where I started to run into problems. My initial population of tags was not enough. The training came back quickly with an error. There should be a minimum of 10 texts per tag, which I didn&amp;rsquo;t have. That would be hundreds of rows. How was I going to automate creating data to give the Text AI enough data to be a suitable demo?&lt;/p>
&lt;h2 id="getting-data">Getting Data&lt;/h2>
&lt;p>I need thousands of records to train my model properly, thousands of records relevant to the tags I create. No online data creator seemed suitable, as it wasn&amp;rsquo;t specific enough, so how? A flow.&lt;/p>
&lt;p>First I created a column in the Contact table to store a number for my contact, a unique no so I can randomise the selection of a contact.&lt;/p>
&lt;p>Next, I need some data for the case description and the tags. This is already done as it is the same as the utterances and intents I used for LUIS, so I exported the LUIS configuration, put the data in an excel file &amp;amp; added a number to that.&lt;/p>
&lt;h2 id="ready-for-the-flow">Ready for the Flow&lt;/h2>
&lt;p>My simple flow is described below.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-10.png"
loading="lazy"
>&lt;/p>
&lt;p>Ask for the number of cases to create, keep creating cases until you have reached that limit using a random contact and a random description.&lt;/p>
&lt;p>This flow is triggered manually so I start with a manual trigger and also prompt for the number of cases to create,&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-9.png"
loading="lazy"
>&lt;/p>
&lt;p>The Subject variable is used later to define the reference for the subject we have chosen.&lt;/p>
&lt;p>The default for loops is 60. I realised late on in the day that you can change that, but breaking up loops is good practice, to limit the scope of what could go wrong, so created a loop within a loop structure for my flow.&lt;/p>
&lt;p>I restrict the inner loop to 50 loops maximum, which means the number of times I run this loop has to be calculated. If I want a 920 cases created, my outer loop would occur 45 times, each creating 50 cases. I would then do a final set for the rest.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-11.png"
loading="lazy"
>&lt;/p>
&lt;p>The next steps will initialise some counters used in the loops. I also want to ensure that if the user wants to create less than 50 records, the outer loop doesn&amp;rsquo;t run at all.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-13.png"
loading="lazy"
>&lt;/p>
&lt;p>The outer loop will run for the number of loops I have calculated. This is the loop condition. The counter increments as the last thing in the outer loop. The first thing in my outer loop is to reset the case counter. This is the counter for the 0-50. If we are in this inner loop, at least 50 cases will be created.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-14.png"
loading="lazy"
>&lt;/p>
&lt;p>The first thing it does is get a random contact by using a odata filter to filter on the number field created specifically using a random number from 0-875 (875 being the highest number in that table).&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-15.png"
loading="lazy"
>&lt;/p>
&lt;p>Once the contact is retrieved, find a random description / tag combination. The data from the LUIS utterances is held in an Excel file on a Teams site. Again, a rand() function takes a random number up to the maximum in that file.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-16.png"
loading="lazy"
>&lt;/p>
&lt;p>Because more than one subject row could be returned and the fact I don&amp;rsquo;t like apply to each inside each other, set the subject Id variable.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-17.png"
loading="lazy"
>&lt;/p>
&lt;p>Ready to create a case now.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-18.png"
loading="lazy"
>&lt;/p>
&lt;p>Nothing special. It also populates the tag field.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-19.png"
loading="lazy"
>&lt;/p>
&lt;p>After some testing, to ensure that the case has the necessary fields entered, the flow was run for a thousand records without an issue.&lt;/p>
&lt;p>Creating data this way isn&amp;rsquo;t quick, 20 mins for 1000 records, but it is easy and allows you to bring in reference data quickly. Superb for PoC environments.&lt;/p>
&lt;h2 id="training-your-model-with-data">Training your Model (with data)&lt;/h2>
&lt;p>Once this data is generated, it was time to re-train my model. It ran through with success this time.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-20.png"
loading="lazy"
>&lt;/p>
&lt;p>The model is 97% sure that whatever I throw at it, it should be able to match it against the tags. There is a quick test option here too, which allows entry of a sample phrase to check your model&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-21.png"
loading="lazy"
>&lt;/p>
&lt;p>All ready to publish.&lt;/p>
&lt;h2 id="publishing-your-model">Publishing your Model&lt;/h2>
&lt;p>Publishing the model allows it be used within Flow and PowerApps.&lt;/p>
&lt;p>Clicking Publish generates a child table of the entity you first chose where the predictions are stored. The &lt;a class="link" href="https://docs.microsoft.com/en-us/ai-builder/publish-text-classification-model" target="_blank" rel="noopener"
>documentation&lt;/a> states the table will be TC_{model_name} but it created mine with gobbledegook.&lt;/p>
&lt;p>The link on the form helpfully allows you to go straight to the entity in the new customisation interface, where you can change the label of the entity.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-22.png"
loading="lazy"
>&lt;/p>
&lt;p>Also, it is useful to change some of the views, particularly the associated results view. By default it includes name &amp;amp; date, which is pretty useless, so add the tag and the probability.&lt;/p>
&lt;p>As this is a child table of Case, it is by default visible in the case form Related navigation item. In the classic customisation interface, you can change the label of this view.&lt;/p>
&lt;p>As it is published, users can use flow and the Predict action to predict the tag for a given section of text, useful if you want to do stuff before it reaches an environment.&lt;/p>
&lt;p>Now that it is published, you need to allow the model to run. This means it runs every time there is a change to the text field. This is all done via Flow, so will use your flow runs. It stores the result in the new entity.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-23.png"
loading="lazy"
>&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-24.png"
loading="lazy"
>&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-25.png"
loading="lazy"
>&lt;/p>
&lt;p>If a case is created now, it automatically creates the tag secondary record.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-case-creation.gif"
loading="lazy"
>&lt;/p>
&lt;h2 id="using-the-tags">Using the tags&lt;/h2>
&lt;p>As AI builder generates a record for you with its prediction, and the data is in CDS, it is a simple Flow to utilise that. As it creates a record in the AI Tags table, update the corresponding case to change the subject accordingly.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-26.png"
loading="lazy"
>&lt;/p>
&lt;p>Simple trigger when a record is created. The first action is to find the subject from the tag.&lt;/p>
&lt;p>Update the case record with the subject and the tag so the AI can be retrained later.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-27.png"
loading="lazy"
>&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/09-image-28.png"
loading="lazy"
>&lt;/p>
&lt;p>That&amp;rsquo;s it. Replacing LUIS with a more user friendly environment is definitely a tick in the box for Microsoft. The AI in PowerApps feels like a simple, user friendly stepping stone for a lot of businesses into the AI world. Hopefully, businesses will embrace these simple models to leverage tools to shortcut processes, improving Employee and customer experiences.&lt;/p></description></item><item><title>User Admin - Published App</title><link>https://linked365.blog/2019/07/19/user-admin-published-app/</link><pubDate>Fri, 19 Jul 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/07/19/user-admin-published-app/</guid><description>&lt;img src="https://linked365.blog/images/2019/07-image-33.png" alt="Featured image of post User Admin - Published App" />&lt;p>After being asked on LinkedIn to publish both the apps that I built for the User Security Admin walk-through I have done so on Dynamics Communities &lt;a class="link" href="https://dynamics365society.uk/pab-directory/" target="_blank" rel="noopener"
>Power Platform Bank&lt;/a>&lt;/p>
&lt;h2 id="stand-alone-security--user-app">Stand-Alone Security / User App&lt;/h2>
&lt;p>The first one, which if you remember is a stand-alone application detailed &lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/" >here&lt;/a> can be downloaded here&lt;/p>
&lt;p>&lt;a class="link" href="https://dynamics365society.uk/powerappsbanklist/dynamics-ce-security-user-profile-powerapp/" target="_blank" rel="noopener"
>https://dynamics365society.uk/powerappsbanklist/dynamics-ce-security-user-profile-powerapp/&lt;/a>&lt;/p>
&lt;h2 id="embedded-security-app">Embedded Security App&lt;/h2>
&lt;p>The second app was the one after I converted the original to a embedded form in the User record, detailed &lt;a class="link" href="https://linked365.blog/2019/07/07/user-admin-powerapp-part-4/" >here&lt;/a>&lt;/p>
&lt;p>&lt;a class="link" href="https://dynamics365society.uk/powerappsbanklist/dynamics-ce-embedded-security-powerapp/" target="_blank" rel="noopener"
>https://dynamics365society.uk/powerappsbanklist/dynamics-ce-embedded-security-powerapp/&lt;/a>&lt;/p>
&lt;p>Both apps require the custom connector to read and update teams and role, which are included in the package.&lt;/p>
&lt;p>Please let me know if it works for you via &lt;a class="link" href="https://twitter.com/linked365" target="_blank" rel="noopener"
>Twitter&lt;/a> or &lt;a class="link" href="https://www.linkedin.com/in/carlcookson/" target="_blank" rel="noopener"
>LinkedIn&lt;/a>&lt;/p>
&lt;p>Thanks goes to &lt;a class="link" href="https://twitter.com/WeAreTDG" target="_blank" rel="noopener"
>Those Dynamics Guys&lt;/a> for the great Dynamics Community &amp;amp; the PPB as well as &lt;a class="link" href="https://www.linkedin.com/in/schladot/" target="_blank" rel="noopener"
>Joergen Schladot&lt;/a> to giving me the kick up the arse to get it done.&lt;/p></description></item><item><title>User Admin PowerApp (Part 4)</title><link>https://linked365.blog/2019/07/07/user-admin-powerapp-part-4/</link><pubDate>Sun, 07 Jul 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/07/07/user-admin-powerapp-part-4/</guid><description>&lt;img src="https://linked365.blog/images/2019/07-image-33.png" alt="Featured image of post User Admin PowerApp (Part 4)" />&lt;p>As putting a canvas app on a model driven form is now out of &lt;a class="link" href="https://docs.microsoft.com/en-us/business-applications-release-notes/April19/microsoft-powerapps/embedding-canvas-apps-model-driven-forms-generally-enhanced" target="_blank" rel="noopener"
>preview&lt;/a> I thought that my &lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/" >PowerApp to add security roles&lt;/a> and teams might be a suitable candidate to be migrated to an embedded canvas app.&lt;/p>
&lt;h2 id="not-going-to-repeat">Not going to repeat&lt;/h2>
&lt;p>There are lots of &lt;a class="link" href="https://www.youtube.com/watch?v=ivvh49bsH0M" target="_blank" rel="noopener"
>videos&lt;/a> and blog &lt;a class="link" href="https://the365hero.com/blog/2018/12/24/embedded-canvas-apps-for-dynamics-365/" target="_blank" rel="noopener"
>posts&lt;/a> out there which detail how to embed a canvas app into model, so there is no point repeating that, just stand on their shoulders.&lt;/p>
&lt;p>Needless to say, there are a few gotchas. I will walk through how I addressed each one.&lt;/p>
&lt;h2 id="the-connection-isnt-there-straight-away">The connection isn&amp;rsquo;t there straight away&lt;/h2>
&lt;p>Rather than displaying the first user selection screen, the embedded app goes straight to the display of user roles and teams. The user selected should come from the record the end user is on. In the original code, I used the selected record, which is available as the user clicked on it.&lt;/p>
&lt;p>From the embedded app, there is a connection to the underlying record, using the ModelDrivenFormIntegrationData property. I found that this was not populated straight away, prior to form visible anyway. To get around this, and I think &lt;a class="link" href="https://twitter.com/ScottDurow" target="_blank" rel="noopener"
>Scott Durrow&lt;/a> demoed this in a &lt;a class="link" href="https://twitter.com/d365uguk" target="_blank" rel="noopener"
>D365 User Group&lt;/a> meeting, you need a wait screen.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-29.png"
loading="lazy"
>&lt;/p>
&lt;p>The Timer has configured to have a duration of 2000ms, with Auto start enabled. On Timer End Event is a simple navigation to the actual start screen.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-30.png"
loading="lazy"
>&lt;/p>
&lt;p>I found that this was more than enough to get the data available in my application, so that the On Visible on the main screen could do all the things it needed to do.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-loadscreen.gif"
loading="lazy"
>&lt;/p>
&lt;h2 id="dont-forget-to-publish">Don&amp;rsquo;t forget to publish&lt;/h2>
&lt;p>The only way you can really see what is going on in your app is to run it within the D365 form. The debugging of the application is a little contrived when using the embedded app, so I used a liberal amount of labels with string values in there to understand what is being set and which value is being used.&lt;/p>
&lt;p>Fundamentally, you need to publish everytime you need to see the application in your environment. Without the publish, the previous version is shown.&lt;/p>
&lt;h2 id="screen-size-wows">Screen size wows&lt;/h2>
&lt;p>This app is now configured with landscape mode, with Scale to fit, locked aspect ration and locked orientation. This seems to work more effectively for higher resolution screens on Windows machines. The screen scales with its size, which is great, but I would like to see the option for better use of the real estate.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-32.png"
loading="lazy"
>&lt;/p>
&lt;p>As you can see, when the screen is large, the buttons and text in the PowerApp gets very big, over the top for mouse users.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-screensizing.gif"
loading="lazy"
>&lt;/p>
&lt;p>If you change the screen properties to remove scale to fit, and alter some of the properties to ensure proper positioning as the screen moves, you get a more appropriate display for large screens, but are limited on tablets etc. Know your audience I guess.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-screensizing2.gif"
loading="lazy"
>&lt;/p>
&lt;h2 id="back-to-the-code">Back to the code&lt;/h2>
&lt;p>The first part is to create a variable with the user data in it. ModelDriverFormIntegration will always be a table, all be it with only row in our case. Using a variable, this single record is available elsewhere. Just a method of not having to repeat that long property line throughout the application.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">userdata&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">First&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ModelDrivenFormIntegration&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The next step, was copy and paste from the other version, replacing where the app is expecting a selection of a user with the user id taken from the userdata. Firstly, creating a FetchXML string to derive the teams for the user, then passing this into the flow connector to retrieve the teams.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teamstring&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch top=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; &amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">team&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">isdefault&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemmanaged&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teammembership&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">from&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teamid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">to&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teamid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">intersect&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuserid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&amp;#34; &amp;amp; userdata.SystemUserId &amp;amp; &amp;#34;&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Stick it in a collection for display on the form
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">ClearCollect&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teams&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">D365FlowConnector&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">GetTeams&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">teamstring&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="n">value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The format of the application has changed, to a landscape view. I made both the teams and roles grid visible, with a search field at the top. The Teams grids items is set to the collection, with filtering and sorting applied&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-31.png"
loading="lazy"
>&lt;/p>
&lt;p>Next in the on visible event, the FetchXML is built to help in adding teams to the user. Firstly, create a table with the snippets in for the existing teams filters, then creating the actual FetchXML&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teamTable&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span> &lt;span class="nf">ForAll&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teams&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;condition attribute=&amp;#34;&amp;#34;teamid&amp;#34;&amp;#34; operator=&amp;#34;&amp;#34;neq&amp;#34;&amp;#34; value=&amp;#34;&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">teamid&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&amp;#34; /&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// create the fetchXML to restrict the teams to those that user has not already got
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teamsNotGot&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch top=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; &amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">team&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">isdefault&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemmanaged&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; Concat(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teamTable&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The process above is also done for the roles. The one gotcha around roles is that there is a business Id field user, but that gives you the name of the BU. If you use the BusinessUnitIdName field, that actually holds the GUID of the BU. Seems counter intuitive to me.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rolesNotGot&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch top=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; &amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">role&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; Concat(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rolesTable&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">businessunitid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; userdata.BusinessUnitIdName &amp;amp; &amp;#34;&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="o">/&amp;gt;&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The final app I think is a much better interface to manage roles and teams for a user. It works well in this context and allows managers to quickly change the roles for who they are concerned with.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-33.png"
loading="lazy"
>&lt;/p></description></item><item><title>Adaptive Cards - Improved Approvals (Part 2)</title><link>https://linked365.blog/2019/07/05/adaptive-cards-improved-approvals-part-2/</link><pubDate>Fri, 05 Jul 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/07/05/adaptive-cards-improved-approvals-part-2/</guid><description>&lt;img src="https://linked365.blog/images/2019/07-image-24.png" alt="Featured image of post Adaptive Cards - Improved Approvals (Part 2)" />&lt;p>Continuing on a walkthrough of creating a more effective adaptive card for approvals, this part will describe the flow I created to generate the card as well as complete the action in D365 depending on the response&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Scenario (&lt;a class="link" href="https://linked365.blog/2019/07/04/adaptive-cards-improved-approvals-part-1/" >Part 1&lt;/a>)&lt;/li>
&lt;li>Preventing progress of an Opportunity ( &lt;a class="link" href="https://linked365.blog/2019/07/04/adaptive-cards-improved-approvals-part-1/" >Part 1&lt;/a> )&lt;/li>
&lt;li>Using Flow to create a basic Approval ( &lt;a class="link" href="https://linked365.blog/2019/07/04/adaptive-cards-improved-approvals-part-1/" >Part 1&lt;/a> )&lt;/li>
&lt;li>Creating an Adaptive Card ( &lt;a class="link" href="https://linked365.blog/2019/07/04/adaptive-cards-improved-approvals-part-1/" >Part 1&lt;/a> )&lt;/li>
&lt;li>Using Flow to create the Approval (This Part)&lt;/li>
&lt;li>Updating the Opportunity (This Part)&lt;/li>
&lt;/ul>
&lt;h2 id="starting-out">Starting out&lt;/h2>
&lt;p>As previously described, the Flow is triggered when a user updates the Develop Propsal checkbox. In the first stages, the flow also retrieves some records that are needed later on for population of the card. There are also initialisations of 2 arrays that are used to populate the approvers and product lines on the card.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-15.png"
loading="lazy"
>&lt;/p>
&lt;p>The next section is used to retrieve the approvers for the territory. In part 1, a many to many relationship was added, linking User to Territory via the territory approvers table.&lt;/p>
&lt;p>As the territory approvers table is a many to many relationship, it does not appear as a standard table in the common data service connector, nor the D365 connector. There are various blog posts out there which state you can just use a custom value, naming the table, but I couldn&amp;rsquo;t get it working, so I fell back to my custom connector.&lt;/p>
&lt;p>In my previous post on &lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/" target="_blank" rel="noopener"
>Security roles via a PowerApp&lt;/a>, the custom connector which allows an FetchXML string to be sent against an object is used a lot to get the teams and the roles for a user. This connector is again used to find the users associated with a territory via the new relationship. The FetchXML is below.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;fetch&lt;/span> &lt;span class="na">top=&lt;/span>&lt;span class="s">&amp;#39;50&amp;#39;&lt;/span> &lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;entity&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#39;systemuser&amp;#39;&lt;/span> &lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#39;internalemailaddress&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#39;fullname&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;link-entity&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#39;cc\_territory\_approver&amp;#39;&lt;/span> &lt;span class="na">from=&lt;/span>&lt;span class="s">&amp;#39;systemuserid&amp;#39;&lt;/span> &lt;span class="na">to=&lt;/span>&lt;span class="s">&amp;#39;systemuserid&amp;#39;&lt;/span> &lt;span class="na">intersect=&lt;/span>&lt;span class="s">&amp;#39;true&amp;#39;&lt;/span> &lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#39;territoryid&amp;#39;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#39;eq&amp;#39;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;@{body(&amp;#39;&lt;/span>&lt;span class="err">Get\_Account\_Manager&amp;#39;)?\[&amp;#39;\_territoryid\_value&amp;#39;\]}&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/link-entity&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/entity&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/fetch&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p> This will return JSON which corresponds to the users linked as approvers to the territory.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;@odata.etag&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;W/\\&amp;#34;&lt;/span>&lt;span class="mi">3421832&lt;/span>&lt;span class="err">\\&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;internalemailaddress&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;veronicaq@CRM568082.OnMicrosoft.com&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;fullname&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Veronica Quek&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;systemuserid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;824da0b2-6c88-e911-a83e-000d3a323d10&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ownerid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;824da0b2-6c88-e911-a83e-000d3a323d10&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;@odata.etag&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;W/\\&amp;#34;&lt;/span>&lt;span class="mi">1742271&lt;/span>&lt;span class="err">\\&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;internalemailaddress&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;danj@CRM568082.OnMicrosoft.com&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;fullname&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Dan Jump&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;systemuserid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;e3b305bf-6c88-e911-a83e-000d3a323d10&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ownerid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;e3b305bf-6c88-e911-a83e-000d3a323d10&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;@odata.etag&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;W/\\&amp;#34;&lt;/span>&lt;span class="mi">3422353&lt;/span>&lt;span class="err">\\&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;internalemailaddress&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CarlC@CRM568082.onmicrosoft.com&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;fullname&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Carl Cookson&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;systemuserid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;113f1e3a-db90-e911-a822-000d3a34e879&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ownerid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;113f1e3a-db90-e911-a822-000d3a34e879&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">\&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p> An approval needs a list of email addresses, separated with a ; . To achieve this, firstly put each of the returned email addresses in an array, then use the Join function to create the string used for approvers&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-17.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="populated-the-main-approval">Populated the Main approval&lt;/h2>
&lt;p>The next part the body of the approval that is going to be sent. I&amp;rsquo;ll link the full version of this at the end of the article, but effectively, you copy your design, remembering to insert appropriate dynamic content on the way.&lt;/p>
&lt;p>Here, I create the 2 URLs that are displayed in the card, which combine the starting point of url and append Account or Opportunity Id.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-18.png"
loading="lazy"
>&lt;/p>
&lt;p>This is displayed at the top of the card.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-19.png"
loading="lazy"
>&lt;/p>
&lt;p>Further, formatting currencies is difficult in Flow. (I stand to be corrected). I found this &lt;a class="link" href="https://powerusers.microsoft.com/t5/Using-Flows/Format-number-with-thousands-separator-in-Flow-email/m-p/305263/highlight/true#M7484" target="_blank" rel="noopener"
>post&lt;/a> on Power Platform community which highlights the issue and degvalentine has the solution, which I have tweaked to take into account of null values in the fields in D365. This example is for one of the fields on the secondary grid.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">empty&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">manualdiscountamount&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">])),&lt;/span> &lt;span class="sc">&amp;#39;0&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">concat&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">greaterOrEquals&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">manualdiscountamount&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="mi">1000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">concat&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">substring&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">manualdiscountamount&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">]),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">max&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nf">sub&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">length&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">first&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">manualdiscountamount&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">]),&lt;/span> &lt;span class="sc">&amp;#39;.&amp;#39;&lt;/span>&lt;span class="p">))),&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sc">&amp;#39;,&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">substring&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">first&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">manualdiscountamount&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">]),&lt;/span> &lt;span class="sc">&amp;#39;.&amp;#39;&lt;/span>&lt;span class="p">)),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">max&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nf">sub&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">length&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">first&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">manualdiscountamount&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">]),&lt;/span> &lt;span class="sc">&amp;#39;.&amp;#39;&lt;/span>&lt;span class="p">))),&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">)),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">min&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nf">length&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">first&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">manualdiscountamount&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">]),&lt;/span> &lt;span class="sc">&amp;#39;.&amp;#39;&lt;/span>&lt;span class="p">))))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">first&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">manualdiscountamount&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">]),&lt;/span> &lt;span class="sc">&amp;#39;.&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sc">&amp;#39;.&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">contains&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">manualdiscountamount&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">]),&lt;/span> &lt;span class="sc">&amp;#39;.&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">concat&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">last&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">manualdiscountamount&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">]),&lt;/span> &lt;span class="sc">&amp;#39;.&amp;#39;&lt;/span>&lt;span class="p">)),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">less&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">length&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">last&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">manualdiscountamount&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">]),&lt;/span> &lt;span class="sc">&amp;#39;.&amp;#39;&lt;/span>&lt;span class="p">))),&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sc">&amp;#39;0&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">&amp;#39;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">&amp;#39;&lt;/span>&lt;span class="mo">00&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="populating-product-details">Populating Product details&lt;/h2>
&lt;p>As the approval body is built up, the next stage is to create a table with the product lines in it. Getting the lines is a simple filter query using the primary key on Opportunity.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-20.png"
loading="lazy"
>&lt;/p>
&lt;p>Like with the approvers, an array is populated with a formatted version of each line, taking fields returned and combining them with formatting rules.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-22.png"
loading="lazy"
>&lt;/p>
&lt;p>The first expression deals with the fact one of the products chosen to demo had a double quote (&amp;quot;) in it, which messes up JSON if it isn&amp;rsquo;t escaped as it is the string delimiter. I used a simple replace expression to add a &amp;ldquo;\&amp;rdquo; before it.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nf">items&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Add&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_to&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_Prod&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="n">_LInes&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">productname&lt;/span>&lt;span class="err">&amp;#39;\&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="sc">&amp;#39;&amp;#34;&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="err">&amp;#39;\\&lt;/span>&lt;span class="s">&amp;#34;&amp;#39;)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The next expression is the one above to format the currency with the appropriate commas and decimal places.&lt;/p>
&lt;p>The output of this looping of the product lines is then combined using a join again, then combined with the body main string.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-23.png"
loading="lazy"
>&lt;/p>
&lt;p>The bottom of this string starts the list of actions, which are the buttons.&lt;/p>
&lt;p>The next step is to create the Approval. This is pretty simple, using a first to respond type, and fleshing it out a bit, so if a user uses the standard Flow Approval interface, they have something to relate to. No notification is needed, this will send an email to the approver, but the Flow will alert the approver via Teams.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-24.png"
loading="lazy"
>&lt;/p>
&lt;p>My original design for this PoC was to push this notification / approval to a Team channel, one notice to the Approvers channel. As Teams integrates with D365, it did not seem much of a hop to highlight the Opportunity approval.&lt;/p>
&lt;p>The only issue is that approvals don&amp;rsquo;t work in team channels, only when sent to a user. Until this is resolved by MS, you are limited to sending the approval to an individual in Teams.&lt;/p>
&lt;h2 id="sending-the-approval">Sending the Approval&lt;/h2>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-25.png"
loading="lazy"
>&lt;/p>
&lt;p>The key bits of this action is ensuring you have the Approvers tenant (can you post approvals across tenants?), the respond link, the approval ID and the creation time populated with the data coming from the approval. The same goes for the Reject action.&lt;/p>
&lt;p>That&amp;rsquo;s it, the new approval is sent.&lt;/p>
&lt;h2 id="waiting-for-the-approval">Waiting for the Approval&lt;/h2>
&lt;p>As the approval is configured that anyone could approve or reject, the next action is to wait for that approval to happen. Approvals can happen upto 30 days, which is another issue, but as this is to speed up the approval process, let&amp;rsquo;s not worry about that.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-26.png"
loading="lazy"
>&lt;/p>
&lt;p>If the outcome is approved, then the field Complete Internal Review is checked and a note is created, linked to the Opportunity logging who approved it.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-27.png"
loading="lazy"
>&lt;/p>
&lt;p>This is in a loop, as, in theory, there could be more than one approver on an approval, if you use the Approval setting that forces everyone to approve something.&lt;/p>
&lt;p>The Regarding / Regarding type, highlighted above, need to be populated as you get orphan records and can spend 20 minutes wondering what is wrong (not me obviously)&lt;/p>
&lt;p>On the Reject side of the condition, the Opportunity is put back to the state it was in before the flow started, namely Develop Proposal is reset. This triggers our Flow again, but as long as the first condition is met, it won&amp;rsquo;t go any further. A note is also added, to highlight who rejected it and why.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-28.png"
loading="lazy"
>&lt;/p></description></item><item><title>Adaptive Cards - Improved Approvals (Part 1)</title><link>https://linked365.blog/2019/07/04/adaptive-cards-improved-approvals-part-1/</link><pubDate>Thu, 04 Jul 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/07/04/adaptive-cards-improved-approvals-part-1/</guid><description>&lt;img src="https://linked365.blog/images/2019/07-image-12.png" alt="Featured image of post Adaptive Cards - Improved Approvals (Part 1)" />&lt;p>&lt;a class="link" href="https://adaptivecards.io/" target="_blank" rel="noopener"
>Adaptive cards&lt;/a> are relatively new to the stack of tools available to PowerPlatform users, emerging from Message Cards. They are a great way of interacting with users who are not a typical D365 user, those on the periphery who are interested in the data but not the detail.&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Scenario (This Part)&lt;/li>
&lt;li>Preventing progress of an Opportunity (This Part)&lt;/li>
&lt;li>Using Flow to create a basic Approval (This Part)&lt;/li>
&lt;li>Creating an Adaptive Card (This Part)&lt;/li>
&lt;li>Using Flow to create the Approval&lt;/li>
&lt;li>Updating the Opportunity&lt;/li>
&lt;/ul>
&lt;h2 id="the-scenario">The Scenario&lt;/h2>
&lt;p>Big Energy is going well, they are now involved in some big deals for big enterprises which need a lot of time to land. The proposals that are generated are complicated, and they struggled with some dubious sales people reducing the margins just to get the deals and this is just bad for business.&lt;/p>
&lt;p>An approval process needs to be implemented, where one or more of a designated group of individuals per territory review the opportunity and decide if the margins are appropriate.&lt;/p>
&lt;p>Unfortunately, the approvers tend to be very busy senior directors, who use D365 sporadically, if at all, and Big Energy need to allow them to approve the opportunities where ever they are using Outlook or Teams as the preferred option.&lt;/p>
&lt;h2 id="tweaking-the-standard-sales-process">Tweaking the standard Sales process&lt;/h2>
&lt;p>Microsoft provides a Business Process Flow for Opportunity management, and in our scenario, only the approvers should be able to check the boolean Complete Internal Review. This is part of the standard Propose stage of the BPF.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-3.png"
loading="lazy"
>&lt;/p>
&lt;p>To &amp;ldquo;lock&amp;rdquo; (I know it isn&amp;rsquo;t foolproof, what is?) the progress on Propose, the Complete Internal Review is subject to a simple business rule, if the opportunity is at any stage, lock the field.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-1.png"
loading="lazy"
>&lt;/p>
&lt;p>Now, no one can edit that field, if that field is made mandatory to progress the bpf stage, no one can progress the stage past propose.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-2.png"
loading="lazy"
>&lt;/p>
&lt;p>Territories are often used in Sales to group accounts or account managers and in our scenario, there is a set list of approvers for a territory. I have added a new many - to - many relationship for this, Approvers and ensured it is listed in the user form as one of the relationships&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-16.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="using-flow-to-create-an-approval">Using Flow to create an Approval&lt;/h2>
&lt;p>In the standard Propose stage, there is another boolean that is of interest, Develop Proposal. The Flow is triggered when this value is changed. A simple CDS update trigger is the starting point.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-4.png"
loading="lazy"
>&lt;/p>
&lt;p>The next stage is to confirm that this trigger is coming with the correct record state, the record has been marked with Develop Proposal, but the other field, Complete Internal Review is still empty.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-5.png"
loading="lazy"
>&lt;/p>
&lt;p>The flow to create the adapted card is fairly intense, well, from my experience, as you will see, so for now, create an Approval using enough details to get the default experience that can be built on.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-7.png"
loading="lazy"
>&lt;/p>
&lt;p>In Details, there is a lot you can do, using &lt;a class="link" href="https://docs.microsoft.com/en-us/flow/approvals-markdown-support" target="_blank" rel="noopener"
>markdown&lt;/a> but this is not as comprehensive as the formating you get from adaptive cards.&lt;/p>
&lt;p>When this flow is run, you will get an email to the assigned to with a simple, standard approval, which is in itself, an adaptive card, but it is fairly plain.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-8.png"
loading="lazy"
>&lt;/p>
&lt;p>Using the Flow history, this action also shows the adaptive card that was built&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-9.png"
loading="lazy"
>&lt;/p>
&lt;p>Copying this value into the Adaptive card designer JSON section gives the format for a basic design, which can be augmented to show some proper information&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-10.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="building-an-adaptive-card">Building an Adaptive card&lt;/h2>
&lt;p>Adaptive Cards are a means to interact with your users via email, teams or any other app that handles the rendering of them. They have actions, allow images to be presented and can format text in a markup that imitates a comprehensive website. They are supported in Outlook mobile apps as well as O365, either using the main app or online.&lt;/p>
&lt;p>They work by rendering a JSON object, which can be formatted to match the host application (the dark black Teams theme for example renders it very differently, but the core actions are still there.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-11.png"
loading="lazy"
>&lt;/p>
&lt;p>Microsoft has built a superb tool to manage Adaptive cards, the new version, at adaptivecards.io/designer. This site has lots of examples to get you started, the &lt;a class="link" href="https://adaptivecards.io/samples/ExpenseReport.html" target="_blank" rel="noopener"
>Expense Report&lt;/a> is a good starting point from a design point of view, but the standard approval card forms the base for the card. There are bits in it that you need to incorporate into your card to allow the approval to work.&lt;/p>
&lt;p>The parts in the data section are the essential bits that, in our adopted JSON need to be duplicated or populated by Flow to allow our card to act as an approval.&lt;/p>
&lt;p>My card is a bit different than the standard, displaying key parts of the Opportunity and the associated product lines.&lt;/p>
&lt;p>&lt;img src="https://linkd365home.files.wordpress.com/2019/07/image-12.png?w=457"
loading="lazy"
>&lt;/p>
&lt;p>As you can see, there is a lot more information on what is happening on the opportunity, probably enough for a sales manager to make a decision in most cases. Included in the card are links to the Account and Opportunity if further review is needed.&lt;/p>
&lt;p>I would recommend starting from a sample and building your content, with dummy data, so you can get the layout correct.&lt;/p>
&lt;p>Each of the buttons are also cards on their own, allowing a comment to be made before the approval is approved or rejected.&lt;/p>
&lt;p>These have been copied from the standard adaptive card produced by the Flow approval so that the submitted approval works like a standard approval.&lt;/p>
&lt;h2 id="some-considerations-and-limitations">Some considerations and limitations&lt;/h2>
&lt;p>I first started trying to reproduce the Expense Approval card in full from the samples&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/07-image-13.png"
loading="lazy"
>&lt;/p>
&lt;p>This has a great use of hidden / visible sections of the expense lines which could give you a lot of real estate for Opportunity lines. Unfortunately, these are not rendered in Teams.&lt;/p>
&lt;p>Also, I thought I would be able to use HTTP trigger, but again, any button with an HTTP trigger is ignored in teams, you are only allowed to create actions for opening URLs, submitting, hiding parts and showing a secondary card.&lt;/p>
&lt;p>Below the main part of the designer is the JSON, which is created by any changes you make above but also can be edited and reflected in the visualiser. The snippet below is taken from the standard card, which contains all the bits that need duplicating to ensure the new, improved approval works correctly.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="s2">&amp;#34;actions&amp;#34;&lt;/span>&lt;span class="err">:&lt;/span> &lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Action.ShowCard&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Approve&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;card&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;AdaptiveCard&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;body&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TextBlock&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Comments&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;wrap&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Input.Text&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;comments&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;placeholder&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Enter comments&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;maxLength&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;isMultiline&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">\&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;actions&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Action.Submit&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Submit&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Environment&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Default-2821cf92-86ad-4c7b-ba9a-5c79a70d4a21&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ApprovalTitle&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Appoval required for Opportunity&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ApprovalLink&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://flow.microsoft.com/manage/environments/Default-2821cf92-86ad-4c7b-ba9a-5c79a70d4a21/approvals/received/6cce94f6-603c-40e7-adb6-8b20c75f724f&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ApprovalName&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;6cce94f6-603c-40e7-adb6-8b20c75f724f&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ItemLink&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://.crm.dynamics.com/main.aspx?newWindow=true&amp;amp;pagetype=entityrecord&amp;amp;etn=opportunity&amp;amp;id=b7c47c42-a290-e611-80e3-c4346bacba3c&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ItemLinkDescription&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Opportunity for 7-Eleven and Udaside label - &amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;OnBehalfOfNotice&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Requested by Carl Cookson &amp;lt;CarlC@CRM.onmicrosoft.com&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;CreatorName&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Carl Cookson&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;CreatorEmail&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CarlC@CRM.onmicrosoft.com&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;CreationTime&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;\\&amp;#34;&lt;/span>&lt;span class="mi">2019-07-03&lt;/span>&lt;span class="err">T&lt;/span>&lt;span class="mi">14&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">30&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">02&lt;/span>&lt;span class="err">Z\\&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;MessageTitle&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Appoval required for Opportunity&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Options&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;Approve&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;Reject&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">\&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;SelectedOption&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Approve&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ActionType&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">\&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;$schema&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;http://adaptivecards.io/schemas/adaptive-card.json&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>User Admin PowerApp (Part 3)</title><link>https://linked365.blog/2019/06/23/user-admin-powerapp-part-3/</link><pubDate>Sun, 23 Jun 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/06/23/user-admin-powerapp-part-3/</guid><description>&lt;img src="https://linked365.blog/images/2019/06-image-22.png" alt="Featured image of post User Admin PowerApp (Part 3)" />&lt;p>The user has been notified that they have a new report, the manager has updated some fields on their user record, they now want to add some roles and teams to allow them to start work.&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Scenario (&lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1//" >Part 1&lt;/a>)&lt;/li>
&lt;li>Notifying the manager of a new Employee (&lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/" >Part 1&lt;/a>)&lt;/li>
&lt;li>PowerApp to display and update User Data (&lt;a class="link" href="https://linked365.blog/2019/06/18/user-admin-powerapp-part-2/" >Part 2&lt;/a>)&lt;/li>
&lt;li>Update Roles and Teams (This Part)&lt;/li>
&lt;/ul>
&lt;h2 id="listing-roles-that-user-hasnt-got">Listing Roles that user hasn&amp;rsquo;t got&lt;/h2>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-21.png"
loading="lazy"
>&lt;/p>
&lt;p>The grid at the bottom of the user screen shows the roles that the user has. If we want to add a role to that list, firstly lets display the roles available to them.&lt;/p>
&lt;p>On the form visible event, there is a lot going on. I have already discussed defining the XML to get the list of roles and teams for the user. In this code I also create XML to retrieve the roles the user hasn&amp;rsquo;t got. Again, &lt;a class="link" href="https://jonasr.app/fxb/" target="_blank" rel="noopener"
>FetchXML Builder&lt;/a> is your friend.&lt;/p>
&lt;p>A looping concatenation isn&amp;rsquo;t available (well not this week) in PowerApps, so you have to get around this by populating a table with one or more strings then concatenating the output of the table.Using the Set command, create a variable and populate it with a string like below using the ForAll command to repeat the string build for each of the roles the user has got.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rolesTable&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span> &lt;span class="nf">ForAll&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">secGroups&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;condition attribute=&amp;#34;&amp;#34;roleid&amp;#34;&amp;#34; operator=&amp;#34;&amp;#34;neq&amp;#34;&amp;#34; value=&amp;#39;&amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">role2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="err">&amp;#39;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;&amp;#39; /&amp;gt;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This, when you then use the ConCat command creates one string with these as many parts in in as roles the user has.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#34;neq&amp;#34;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;0699ab9b-984c-4896-9c8a-38352fdc3c93&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#34;neq&amp;#34;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;d77e2e20-4eac-4fbf-b1a8-5bec6f853ebf&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The final string combines this string with the other bits that I am interested in, selecting the attributes that is required as well as filtering the roles return to only those in the users BU. If this condition is not put in, all the roles that are associated with all the BUs will be returned. In D365, a role is duplicated for each BU you create, and you need to associate the user with the right role for their BU.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rolesNotGot&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch top=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; &amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">role&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; Concat(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rolesTable&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">businessunitid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; MyReports.Selected.&amp;#39;Business Unit&amp;#39;.businessunitid &amp;amp; &amp;#34;&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="o">/&amp;gt;&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>This produces an XML that looks like the below.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;fetch&lt;/span> &lt;span class="na">top=&lt;/span>&lt;span class="s">&amp;#34;50&amp;#34;&lt;/span> &lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;entity&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;role&amp;#34;&lt;/span> &lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;name&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;filter&lt;/span> &lt;span class="na">type=&lt;/span>&lt;span class="s">&amp;#34;and&amp;#34;&lt;/span> &lt;span class="nt">&amp;gt;&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#34;neq&amp;#34;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;0699ab9b-984c-4896-9c8a-38352fdc3c93&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#34;neq&amp;#34;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;d77e2e20-4eac-4fbf-b1a8-5bec6f853ebf&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#34;businessunitid&amp;#34;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#34;eq&amp;#34;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;ec0e9d51-0e91-e911-a822-000d3a34e879&amp;#39;&lt;/span>&lt;span class="nt">/&amp;gt;&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/entity&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/fetch&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>On selecting the plus button at the top of the grid for Roles, another collection is populated using the custom connector, passing the XML to the Roles definition.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Collect&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">groupsandteams&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="n">D365FlowConnector&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">GetAllRoles&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rolesNotGot&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="n">value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="add-role-screen">Add Role screen&lt;/h2>
&lt;p>The final screen is a simple gallery, with the name of the role displayed.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-22.png"
loading="lazy"
>&lt;/p>
&lt;p>All the work is done on the + icon. This calls another custom connector, adding the role to the user. Postman is your friend here. My Postman to insert a role for a user is shown below&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-23.png"
loading="lazy"
>&lt;/p>
&lt;p>Basically, this is posting a body containing a systemuserroles_asscociation to the the webapi, which creates a new one. The user reference is in the URL and the roleId is in the body.&lt;/p>
&lt;p>Now, I confess I am not the most offay on the best way to use the Web API. This is one of the reasons I am writing a blog, learning. See that little highlighted $ref? I spent hours trying to get this working and only found that this is required at the end. If you omit the $ref, it returns a positive result. Same if you try to add a role that belongs to a BU that the user doesn&amp;rsquo;t. Someone tell me where this is logged so next time I can do some troubleshooting rather than trial &amp;amp; error?&lt;/p>
&lt;p>The D365 &lt;a class="link" href="https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/webapi/associate-disassociate-entities-using-web-api#associate-entities-on-update-using-collection-valued-navigation-property" target="_blank" rel="noopener"
>document&lt;/a> does mention it, but it is simply missed and it is part of the OData standard for &lt;a class="link" href="http://docs.oasis-open.org/odata/odata/v4.0/cs01/part2-url-conventions/odata-v4.0-cs01-part2-url-conventions.html#_Toc365046422" target="_blank" rel="noopener"
>addressing references between entities&lt;/a>. As I say, learn everyday.&lt;/p>
&lt;p>To convert this to a custom connector definition the GUID of the user account in the URL needs to be replaced with a parameter, note the curly brackets and looks like the below&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-25.png"
loading="lazy"
>&lt;/p>
&lt;p>In PowerApps, after refreshing the connector, there is a new method on our connector. On click of the + in the Add role screen, this is called.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="n">D365FlowConnector&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">AddRole&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">MyReports&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Selected&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">User&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;https://urlofyourcrm.crm.dynamics.com&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;/api/data/v9.0/roles(&amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">roleid&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="s">&amp;#34;)&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Even though the second parameter has been hidden and given a default value in the connector, it still prompts to be entered. Not sure why.&lt;/p>
&lt;p>The Teams addition is the same logic, but a different connecting entity. The postman for this is below&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-26.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="deleting-a-role">Deleting a Role&lt;/h2>
&lt;p>To complete the circle, a manager should be able to delete a role or team that the user belongs to. This is again done via a custom connector, the postman is below&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-27.png"
loading="lazy"
>&lt;/p>
&lt;p>As with the create definition, the 2 guids in the url need to be swapped out so the definition is created like this&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-28.png"
loading="lazy"
>&lt;/p>
&lt;p>Once refreshed in PowerApps, this is connected to the remove button on the Roles grid.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="n">D365FlowConnector&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">DeleteRole&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">MyReports&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Selected&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">User&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">role2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>After this call, the grids are refreshed to show the action has taken effect.&lt;/p>
&lt;p>Teams works in the same way, using the url like this&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-29.png"
loading="lazy"
>&lt;/p>
&lt;p>And that is it! This app works well to bridge the gap for onboarding users in a busy enterprise, especially as a PowerApp, it is available to users on the go.&lt;/p>
&lt;p>Custom Connectors really bring the availability of all the standard Customer Engagement functionality to the &amp;ldquo;citizen developer&amp;rdquo;. As enterprise level organisations get on board with PowerApps, small apps that make the employee experience easier will become necessary. This is only an example of how this could be done. Reach out if you would like me to share the app with you.&lt;/p></description></item><item><title>User Admin PowerApp (Part 2)</title><link>https://linked365.blog/2019/06/18/user-admin-powerapp-part-2/</link><pubDate>Tue, 18 Jun 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/06/18/user-admin-powerapp-part-2/</guid><description>&lt;img src="https://linked365.blog/images/2019/06-image-3.png" alt="Featured image of post User Admin PowerApp (Part 2)" />&lt;p>So, after notifying the user that there is a new employee in their team, the manager needs to be able to update the data.&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Scenario (&lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/" >Part 1&lt;/a>)&lt;/li>
&lt;li>Notifying the manager of a new Employee (&lt;a class="link" href="https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/" >Part 1&lt;/a>)&lt;/li>
&lt;li>PowerApp to display and update User Data (This Part)&lt;/li>
&lt;li>Update Roles and Teams&lt;/li>
&lt;/ul>
&lt;h2 id="my-reports">My Reports&lt;/h2>
&lt;p>I am not going to go through how to create a PowerApp, there are numerous blogs and pages that step you through this, may I recommend the Microsoft &lt;a class="link" href="https://powerapps.microsoft.com/en-us/blog/microsoft-powerapps-learning-resources/" target="_blank" rel="noopener"
>page&lt;/a> with it all on?&lt;/p>
&lt;p>My PowerApp is pretty straight forward at the start. The first screen is to retrieve all the users that the current logged in user manages, connected to a User data source in the CDS.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-4.png"
loading="lazy"
>&lt;/p>
&lt;p>Start with a new List form, connect it to your CDS User data set and select a few fields. With the List form, there are several parts that you need to configure, to make the buttons at the top of the screen to work correctly.&lt;/p>
&lt;p>Firstly, the Items property needs to be configured to correctly display and filter the data according to the search the user has selected and the sort.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">SortByColumns&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Search&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Filter&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Users&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Manager&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">internalemailaddress&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">User&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">Email&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">TextSearchBox2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Text&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;fullname&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;fullname&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">If&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">SortDescending&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">SortOrder&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Descending&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">SortOrder&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Ascending&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>The core to this is the Filter, where the Users (the data source) is filtered to only show those where the email address of the manager of the user is the current users email address.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Filter&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Users&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Manager&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">internalemailaddress&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nf">User&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">Email&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Wrapped around this is functionality to sort and search this grid.&lt;/p>
&lt;p>BTW, the picture is the &amp;lsquo;Entity Image&amp;rsquo; field in the data set, the picture that a user can upload into D365 against their user account.&lt;/p>
&lt;h2 id="user-details">User Details&lt;/h2>
&lt;p>The next screen is a standard edit form, navigated to via the little arrow with this logic&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Parent&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Navigate&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">Employee&lt;/span> &lt;span class="n">Edit&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ScreenTransition&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">CoverRight&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-5.png"
loading="lazy"
>&lt;/p>
&lt;p>The form again connects to the User data set, with the item in the edit portion being the significant bit&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-6.png"
loading="lazy"
>&lt;/p>
&lt;p>I have just selected some random fields to display here, where I think it would be appropriate to manage. The Business Unit is a key field for a user, and is a selection and needs a little help to display the right data and update the record appropriately.&lt;/p>
&lt;p>Start by adding the field. If you select the datacardvalue control (the drop down itself in the form), notice that a couple of things are wrong.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-8.png"
loading="lazy"
>&lt;/p>
&lt;p>Business Unit is a parent of User, a relationship Lookup, and PowerApps has decided (not sure why, the default for lookups surely should be the name field, which is how D365 works) to select the Address1_City field to display to the user when they are selecting. Change this to &amp;ldquo;name&amp;rdquo;. Change the search as well to match.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-9.png"
loading="lazy"
>&lt;/p>
&lt;p>Now, the form will display the BU of the user as well as allowing an update of this field.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-10.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="displaying-security-roles">Displaying Security Roles&lt;/h2>
&lt;p>At the bottom of the edit form are 2 grids to display the users security roles and their teams. Both operate in the same way.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-11.png"
loading="lazy"
>&lt;/p>
&lt;p>To get at the roles for a user, you have to use a bit of FetchXML. There is a hidden link table, or a collection value navigation, systemuserroles_association, which links a role with a user.&lt;/p>
&lt;p>If you are using any sort of FetchXML, &lt;a class="link" href="https://jonasr.app/fxb/" target="_blank" rel="noopener"
>&lt;/a>&lt;a class="link" href="https://jonasr.app/fxb/" target="_blank" rel="noopener"
>FetchXML Builder&lt;/a> (FXB) by &lt;a class="link" href="https://twitter.com/rappen" target="_blank" rel="noopener"
>Jonas Rapp&lt;/a> is essential. It allows a developer to define the exact fields, the connections and filters to form a query for data by looking at the data model. Start with a blank query, select the systemuser entity.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-12.png"
loading="lazy"
>&lt;/p>
&lt;p>In our scenario, the query should return the roles for one user, the one that has been selected by the manager. Add a filter, then a condition, select the systemuserroles entity, and the systemuserid attribute (field). The operator is equals and the value is the GUID of the user account.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-14.png"
loading="lazy"
>&lt;/p>
&lt;p>To test the query, paste in the GUID of the user. Another great tool is the Chrome Addon, &lt;a class="link" href="https://chrome.google.com/webstore/detail/level-up-for-dynamics-365/bjnkkhimoaclnddigpphpgkfgeggokam" target="_blank" rel="noopener"
>Level Up for Dynamics&lt;/a> by &lt;a class="link" href="https://twitter.com/RajYRaman/" target="_blank" rel="noopener"
>Natraj Yegnaraman&lt;/a> allows you to quickly get to the GUID of any record, as well as some other useful tools (please don&amp;rsquo;t tell an end user about God Mode). The query should retrieve all the fields on the User entity for the chosen user.&lt;/p>
&lt;p>Next, select a link-entity, namely the many to many systemuserroles.systemuserid -&amp;gt; systemuserid.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-13.png"
loading="lazy"
>&lt;/p>
&lt;p>Executing this query will result in a lot of fields been returned, most of no interest to our query, so add some attributes, which limits the fields returned. Only interested in the roleId and the name.&lt;/p>
&lt;p>Hit execute this time and this will display the roles that are associated with the user selected.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-18.png"
loading="lazy"
>&lt;/p>
&lt;p>This is all well and good, but how is this data getting into the PowerApp? A custom connector of course. I have used custom connectors a lot to get at the bits the standard CDS connector can&amp;rsquo;t in my other posts. I won&amp;rsquo;t discuss how to create the connector, my post on &lt;a class="link" href="https://linked365.blog/2019/04/03/connecting-luis-d365-part-4-custom-connector/" target="_blank" rel="noopener"
>LUIS&lt;/a> covers that. I expand on it fixing the &lt;a class="link" href="https://linked365.blog/2019/05/11/creating-attachments-in-d365/" target="_blank" rel="noopener"
>bug on creating attachments in D365&lt;/a>.&lt;/p>
&lt;h2 id="creating-the-connector-definition">Creating the Connector Definition&lt;/h2>
&lt;p>Again, Postman is your friend here. Each of the main entities will accept FetchXML as a parameter, as in this is what is created in Postman&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">{{WebAPIUrl}}/systemusers?fetchXml=&lt;span class="nt">&amp;lt;fetch&lt;/span> &lt;span class="na">mapping=&lt;/span>&lt;span class="s">&amp;#34;logical&amp;#34;&lt;/span> &lt;span class="na">count=&lt;/span>&lt;span class="s">&amp;#34;50&amp;#34;&lt;/span> &lt;span class="na">version=&lt;/span>&lt;span class="s">&amp;#34;1.0&amp;#34;&lt;/span>&lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;entity&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;systemuser&amp;#34;&lt;/span>&lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;fullname&amp;#34;&lt;/span> &lt;span class="nt">/&amp;gt;&amp;lt;filter&lt;/span> &lt;span class="na">type=&lt;/span>&lt;span class="s">&amp;#39;and&amp;#39;&lt;/span>&lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;condition&lt;/span> &lt;span class="na">attribute=&lt;/span>&lt;span class="s">&amp;#39;systemuserid&amp;#39;&lt;/span> &lt;span class="na">operator=&lt;/span>&lt;span class="s">&amp;#39;eq&amp;#39;&lt;/span> &lt;span class="na">value=&lt;/span>&lt;span class="s">&amp;#39;EBD3707B-6C88-E911-A83E-000D3A323D10&amp;#39;&lt;/span> &lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/filter&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;link-entity&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;systemuserroles&amp;#34;&lt;/span> &lt;span class="na">from=&lt;/span>&lt;span class="s">&amp;#34;systemuserid&amp;#34;&lt;/span> &lt;span class="na">to=&lt;/span>&lt;span class="s">&amp;#34;systemuserid&amp;#34;&lt;/span>&lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;link-entity&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;role&amp;#34;&lt;/span> &lt;span class="na">from=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span> &lt;span class="na">to=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span>&lt;span class="nt">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="nt">/&amp;gt;&amp;lt;attribute&lt;/span> &lt;span class="na">name=&lt;/span>&lt;span class="s">&amp;#34;roleid&amp;#34;&lt;/span>&lt;span class="nt">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/link-entity&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/link-entity&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/entity&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/fetch&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Paste this into a new connector action and PowerApps will convert the fetchXML as a new parameter for the action.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-15.png"
loading="lazy"
>&lt;/p>
&lt;p>Test this action with a copy and paste of the XML that you generated in FetchXML Builder and the action will return a bit of XML itself&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-17.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="using-the-connector-in-the-app">Using the Connector in the app&lt;/h2>
&lt;p>Add the custom connector as a Data source in the App.&lt;/p>
&lt;p>To call the connector, on the OnVisible of the Employee Edit form, generate the XML first. Set a variable to the XML generated from FXB, substituing the current selected user id as appropriate&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">secString&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch mapping=&amp;#34;&amp;#34;logical&amp;#34;&amp;#34; count=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; version=&amp;#34;&amp;#34;1.0&amp;#34;&amp;#34;&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuser&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">fullname&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">systemuserid&lt;/span>&lt;span class="err">&amp;#39;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="err">&amp;#39;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="s">&amp;#34; &amp;amp; MyReports.Selected.User &amp;amp; &amp;#34;&lt;/span>&lt;span class="err">&amp;#39;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuserroles&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">from&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuserid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">to&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuserid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">role&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">from&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">to&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">roleid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>MyReports is the list on the first screen, Selected is the user that the manager has selected. PowerApps converts the User to the GUID of the user (handy). Be careful with the quotes here, I found when pasting, curly versions of the straight quotes came in ( “ rather than &amp;ldquo;) which took me a while to resolve. Also, ensure all the double quotes are present. FXB provides single quotes and hence you need to double up for PowerApps to infer an actual quote rather than the end of the string.&lt;/p>
&lt;p>Update: Thanks to &lt;a class="link" href="https://twitter.com/rappen" target="_blank" rel="noopener"
>Jonas Rapp&lt;/a> for reaching out on Twitter to put me right. In FXB there is a setting to use single quotes rather than double in the rendered XML&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-30.png"
loading="lazy"
>&lt;/p>
&lt;p>This then allows a straight copy / paste into your PowerApp&lt;/p>
&lt;p>Set(
secString,&amp;quot;&lt;fetch top='50' >
&lt;entity name='systemuser' >
&lt;filter type='and' >
&lt;condition attribute='systemuserid' operator='eq' value='" &amp; MyReports.Selected.User &amp; "' />
&lt;/filter>
&lt;link-entity name='systemuserroles' from='systemuserid' to='systemuserid' intersect='true' >
&lt;link-entity name='role' from='roleid' to='roleid' >
&lt;attribute name='name' />
&lt;attribute name='roleid' />
&lt;/link-entity>
&lt;/link-entity>
&lt;/entity>
&lt;/fetch>&amp;rdquo;&lt;/p>
&lt;p>After the string is created, pass this to the custom connector, inserting the return into a collection. This is the collection that is shown in the grid.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Get the groups for the selected user
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="nf">ClearCollect&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">secGroups&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">D365FlowConnector&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nf">GetSecGroups&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">secString&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="n">value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Put a gallery on the form, and use this collection as its items list, and sorted by the role just for usability.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-19.png"
loading="lazy"
>&lt;/p>
&lt;p>The Teams grid is populated very much the same. The connector is based around the teams entity rather than the system user (in hindsight, I should have based the roles one of roles, rather than user, but achieves the same result, and it is all about learning isn&amp;rsquo;t it?). The XML looks like this.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="cl">&lt;span class="nf">Set&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">teamstring&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;&amp;lt;fetch top=&amp;#34;&amp;#34;50&amp;#34;&amp;#34; &amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">team&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">attribute&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">isdefault&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemmanaged&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teammembership&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">from&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teamid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">to&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">teamid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">intersect&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="nb">true&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">filter&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">and&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">condition&lt;/span> &lt;span class="n">attribute&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">systemuserid&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="n">eq&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&amp;#34; &amp;amp; MyReports.Selected.User &amp;amp; &amp;#34;&amp;#34;&amp;#34;&lt;/span> &lt;span class="o">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">filter&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">link&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">entity&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;/&lt;/span>&lt;span class="n">fetch&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>teammembership is the connecting table.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-20.png"
loading="lazy"
>&lt;/p>
&lt;p>So, that is enough for now, the app displays users that report to me, I can see their teams and roles. Next post will show how the teams and roles are updated.&lt;/p></description></item><item><title>User Admin PowerApp (Part 1)</title><link>https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/</link><pubDate>Mon, 10 Jun 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/06/10/user-admin-powerapp-part-1/</guid><description>&lt;img src="https://linked365.blog/images/2019/06-image-3.png" alt="Featured image of post User Admin PowerApp (Part 1)" />&lt;p>Sorry it has been a while since my last blog post, this scenario has taken a while to get it to the state where I was happy to show it off. Mainly due to my own lack of understanding of the intricacies of the D365 API, but also been busy external to the blog, you know real life.&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Scenario (This part)&lt;/li>
&lt;li>Notifying the manager of a new Employee (This Part)&lt;/li>
&lt;li>PowerApp to display and update User Data&lt;/li>
&lt;li>Update Roles and Teams&lt;/li>
&lt;/ul>
&lt;h2 id="the-scenario">The Scenario&lt;/h2>
&lt;p>Big Energy Co is going from strength to strength, presumably because of the innovative solutions using &lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365-part-1/" >LUIS&lt;/a>, &lt;a class="link" href="https://linked365.blog/2019/04/19/alexa-field-service-and-me-part-1/" >Alexa&lt;/a> and &lt;a class="link" href="https://linked365.blog/2019/05/04/ifttt-flow-d365/" >IFTTT&lt;/a>.&lt;/p>
&lt;p>The HR department is ramping up recruitment and new teams are being shaped to support all the growth.&lt;/p>
&lt;p>One of the criticisms from the managers is that it takes a while for the IT / D365 administrators to get users in the correct teams and security roles so they can be effective in D365.&lt;/p>
&lt;p>A clever chap in the management team suggested that they be given an app that would allow a manager to update the roles and teams (and other relevant parts of a user) without resorting to logging into D365 administration. Something they can use wherever they have WiFi or a data connection.&lt;/p>
&lt;p>It would also be good to get a notification when they have a new employee, or someone is added to their reports.&lt;/p>
&lt;h2 id="the-flow">The Flow&lt;/h2>
&lt;p>This flow is quite simple, trigger an email when a user has the Manager field (parentsystemuserid) field updated. O365 will create the user for us (assuming you are in the cloud) and an administrator will still have to update the users manager.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image.png"
loading="lazy"
>&lt;/p>
&lt;p>Here, the attribute I am interested on is parentsystemuserid.&lt;/p>
&lt;p>Next, just check to see if the manager is actually populated. In a lot of businesses, removing their manager is part of the process on off-boarding an employee, to tidy up selection lists etc.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-1.png"
loading="lazy"
>&lt;/p>
&lt;p>Then, get the manager user record from D365 so that the email can be sent to it.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/06-image-2.png"
loading="lazy"
>&lt;/p>
&lt;p>Told you it was simple. I am sure that this can have more logic - Do we need an approval step before assigning this user? Do we have to wait for HR to do some work and only activate the user once all the checks are done?&lt;/p>
&lt;p>Next, I&amp;rsquo;ll step through the PowerApps set up to retrieve data from my reports.&lt;/p></description></item><item><title>Creating Attachments in D365</title><link>https://linked365.blog/2019/05/11/creating-attachments-in-d365/</link><pubDate>Sat, 11 May 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/05/11/creating-attachments-in-d365/</guid><description>&lt;img src="https://linked365.blog/images/2019/05-squirrel-eating.jpg" alt="Featured image of post Creating Attachments in D365" />&lt;p>This isn&amp;rsquo;t one of my usual posts as I always like to start with a business case. I intend to create a blog about the business case / solution that created this issue once all the other  pieces fall into place, so watch out for that (keep them keen by teasing they say)&lt;/p>
&lt;h2 id="the-problem">The Problem&lt;/h2>
&lt;p>You might not know there is a problem, but there is. Squirrels are a problem, but not my field of expertise, &lt;a class="link" href="https://twitter.com/dynamiccrmcat" target="_blank" rel="noopener"
>@dynamiccrmcat&lt;/a> will have other opinions.&lt;/p>
&lt;p>Attachments are a problem. More specifically, trying to add an attachment to D365 via a Flow or PowerApp is a problem. Yes I know we should be using SharePoint or Teams etc, but sometimes you want to keep your data in D365.&lt;/p>
&lt;p>You should just be able to &amp;ldquo;Patch&amp;rdquo; the Notes entity in a PowerApp with the file you want in the documentbody field of the entity, but you run into problems (bug) with objecttypecodes (it is expecting a GUID and all you know is an entity name).&lt;/p>
&lt;p>&lt;a class="link" href="https://twitter.com/jukkan" target="_blank" rel="noopener"
>@JukkaN&lt;/a> pointed me to this &lt;a class="link" href="https://powerusers.microsoft.com/t5/General-Discussion/Not-able-to-create-the-attachment-regarding-any-entity/td-p/193465" target="_blank" rel="noopener"
>article&lt;/a> on the PowerApp forum which explains the problem in more detail and clearer than I have. This was via a conversation with him and &lt;a class="link" href="https://twitter.com/TattooedCRMGuy" target="_blank" rel="noopener"
>@TattooedCRMGuy&lt;/a> where we came to the conclusion that there is a bug in the CDS connector.&lt;/p>
&lt;p>So my next thought was to call a Flow from the PowerApp, passing in the file as a parameter. This doesn&amp;rsquo;t work either. Any which way you try, it ends up with the file being passed as the link to the Azure blob the PowerApp is temporarily using to store the attachment.&lt;/p>
&lt;p>Then I started using the developers friend, Google. My first thought is that if I could pass to the Flow a file rather than the URL, this would work. This thought led me to an excellent Youtube &lt;a class="link" href="https://www.youtube.com/watch?v=mp-8B1fLrqs&amp;amp;feature=youtu.be" target="_blank" rel="noopener"
>video&lt;/a> by Paul Culmsee. He shows how to pass a Photo from PowerApps to Flow to save it to Sharepoint. He has the same issue, how to pass a file to flow, and thanks to him, I have duplicated it for saving a file to D365.&lt;/p>
&lt;p>So the logic I have deployed is&lt;/p>
&lt;p>PowerApps → Custom Connector → Flow → Custom Connector into D365&lt;/p>
&lt;p>2 custom connectors here, this is a relative expensive solution, as the user require a PowerApps Plan 1 license for this which might be an addon to their license.&lt;/p>
&lt;h2 id="the-d365-connector">The D365 Connector&lt;/h2>
&lt;p>Starting at the final step, I utilised a custom connector like in my &lt;a class="link" href="https://linked365.blog/2019/05/04/ifttt-flow-d365/" >previous&lt;/a> &lt;a class="link" href="https://linked365.blog/2019/04/03/connecting-luis-d365-part-4-custom-connector/" >posts&lt;/a> to interact with the D365 API directly. I am not going to go through the method of creating the connector, just this custom action. Again, PostMan is your friend. Using this tool, I generated a JSON template to post against the Annotations entity. Firstly, add an action to the connector. &lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-8.png"
loading="lazy"
>&lt;/p>
&lt;p>Next, select Import from sample, and populate as below, obviously using your own instance API endpoint.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-9.png"
loading="lazy"
>&lt;/p>
&lt;p>Couple of things here, Annotation is the name of the table that Notes are stored in. &amp;ldquo;objectid_contact@odata.bind&amp;rdquo; is the single value navigation for linking Contact to the note. In the CDS connector, this field is not visible, you are expected to enter a pair of _objectid_value and objecttypecode, which doesn&amp;rsquo;t work, hence this blog post (I hope they fix it, but not too soon now I have worked it out). Finally, documentbody is the field where the attachment is stored, as a Base64 string. This is weirdly different than the binary data store used by Sharepoint.&lt;/p>
&lt;p>Select Import and the first connector is done.&lt;/p>
&lt;h2 id="the-flow">The Flow&lt;/h2>
&lt;p>The flow is pretty simple, a HTTP trigger, messing around with the inputs and sending the information to the D365 connector. Simple, but I needed the video by Paul Culmsee to guide me through. The premise being, rather than the usual approach of looking at the body of the web call, we need to take out parts from the query string and the content of the call would be a file. He does a much better job at explaining it that I do, so head over to the &lt;a class="link" href="https://www.youtube.com/watch?v=mp-8B1fLrqs&amp;amp;feature=youtu.be" target="_blank" rel="noopener"
>video&lt;/a> to actually learn.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-10.png"
loading="lazy"
>&lt;/p>
&lt;p>A standard HTTP trigger. I then use a Compose data operation to take data from the trigger using a formula based on the query parameters passed.&lt;/p>
&lt;p>trigger()[&amp;lsquo;outputs&amp;rsquo;][&amp;lsquo;queries&amp;rsquo;][&amp;lsquo;filename&amp;rsquo;]&lt;/p>
&lt;p>This states that I want find and store the filename parameter passed in the url when the trigger was triggered&lt;/p>
&lt;p>The Get File Body does the same but looks at the content of the body that was passed in.&lt;/p>
&lt;p>triggerMultipartBody(0)[&amp;rsquo;$content&amp;rsquo;]&lt;/p>
&lt;p>The final part is a call to the D365 custom connector, passing in the compose operation outputs&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-11.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="another-custom-connector">Another Custom Connector&lt;/h2>
&lt;p>You can&amp;rsquo;t call a webservice triggered flow from a PowerApp directly. You can call a Flow, but the flow doesn&amp;rsquo;t pass the appropriate parameters. It only deals with strings. You can&amp;rsquo;t convert your file to a string in PowerApps. I am obviously going to be proved wrong here, but I will learn. That&amp;rsquo;s one of the reasons I blog.&lt;/p>
&lt;p>Hence, why you need to create a custom connector to pass from PowerApps to the Flow above.&lt;/p>
&lt;p>Connectors can be created by uploading a swagger definition. &lt;a class="link" href="https://en.wikipedia.org/wiki/Swagger_%28software%29" target="_blank" rel="noopener"
>Swagger&lt;/a> is an open-source framework to document APIs and has been recently converted to the OpenAPI specification. Obviously connectors can be built from scratch, but because of the file upload that is required, a definition of the API is required.&lt;/p>
&lt;p>Paul again comes to my rescue, he has a great &lt;a class="link" href="http://www.cleverworkarounds.com/2017/11/13/a-sample-openapiswagger-file-for-powerapps/" target="_blank" rel="noopener"
>blog&lt;/a> post that he goes through in detail the file that was produced to support his video. In the Youtube post, he uses a tool that I can not find, but this file walkthrough was enough for me to produce my own &lt;a class="link" href="https://1drv.ms/u/s!AueNWhtMOmpUiqszYVB8owfI-DLujA" target="_blank" rel="noopener"
>file&lt;/a>. I am not going to go through the detail here, Paul does a much better job.&lt;/p>
&lt;p>In custom connectors, hit the +, then select Import an OpenAPI file.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-12.png"
loading="lazy"
>&lt;/p>
&lt;p>Give your new connector a name and select your newly created file definition. If your file is correct, you are now presented with a pre-populated definition of your connector. The query parameters displayed include lots of configuration items that should be pre-populated from your Swagger file.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-14.png"
loading="lazy"
>&lt;/p>
&lt;p>You can see the connector is not expecting a Body.&lt;/p>
&lt;p>If you test the connector action there is also an extra parameter it is expecting&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-15.png"
loading="lazy"
>&lt;/p>
&lt;p>This File parameter is essential. Now it&amp;rsquo;s reading for use!&lt;/p>
&lt;h2 id="the-powerapp">The PowerApp&lt;/h2>
&lt;p>To demonstrate the connector, create a new PowerApp. Because this is for the contact entity, use a drop down to get a list of Contacts to attach the note to from D365.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-16.png"
loading="lazy"
>&lt;/p>
&lt;p>Associate this with D365 using the Common Data Service&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-17.png"
loading="lazy"
>&lt;/p>
&lt;p>Select the Contacts Entity, back in the properties of the control, use Full Name as the Value. Next, add a &amp;ldquo;Add Picture&amp;rdquo; control.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-18.png"
loading="lazy"
>&lt;/p>
&lt;p>Also add a datatable. This time connect to the Annotation (Notes) entity in D365. Make sure you use the D365 connector though. For some reason, the Common Data Service connector does not return the Regarding as a field you can use. Select a few relevant fields, Title, Note, File Name and Document.&lt;/p>
&lt;p>In the Values field, filter the datatable by the Contact that is selected in the dropdown and only show those where there is an attachment.&lt;/p>
&lt;p>Filter(Notes, Regarding = GUID(ContactDD.Selected.Contact) &amp;amp;&amp;amp; !IsBlank(Document))&lt;/p>
&lt;p>Selecting a contact now should deliver a list of notes that are attached to that record.&lt;/p>
&lt;p>To Upload a document, add a button. This will trigger the custom connector, so this needs to be added to the PowerApp. Select Data sources, add data source&lt;/p>
&lt;p>The custom connector that was created earlier should appear. Select it.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-19.png"
loading="lazy"
>&lt;/p>
&lt;p>In the button OnSelect action, if all is well, enter the name of the connector and action and it should give you a list of parameters you need.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-20.png"
loading="lazy"
>&lt;/p>
&lt;p>The final call to the connector looks like this&lt;/p>
&lt;p>FileUploader.UploadFile(
AddMediaButton1.FileName,
ContactDD.Selected.Contact,
&amp;ldquo;Added from PowerApps&amp;rdquo;,
&amp;ldquo;Added from PowerApps&amp;rdquo;,
UploadedImage1.Image
);
Refresh(Notes)&lt;/p>
&lt;p>The filename comes from the control within the Image upload control, the contact Id is from the selected contact, some text stuff to fill out (you could add a text control to take that input obviously) and then the image.&lt;/p>
&lt;p>I refresh the notes data set after I am done so that the list has got the data.&lt;/p>
&lt;p>So that&amp;rsquo;s it, a complicated solution to a &amp;ldquo;bug/feature&amp;rdquo; currently in Powerapps.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-21.png"
loading="lazy"
>&lt;/p>
&lt;p>A screenshot of that squirrel note against the contact in D365, just so you know I am not bluffing.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-22.png"
loading="lazy"
>&lt;/p>
&lt;p>BTW, squirrels are evil, rats with marketing, don&amp;rsquo;t believe everything &lt;a class="link" href="https://twitter.com/dynamiccrmcat" target="_blank" rel="noopener"
>@dynamiccrmcat&lt;/a> says, though it is probably just squirrels she is wrong about.&lt;/p></description></item><item><title>IFTTT Flow D365</title><link>https://linked365.blog/2019/05/04/ifttt-flow-d365/</link><pubDate>Sat, 04 May 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/05/04/ifttt-flow-d365/</guid><description>&lt;img src="https://linked365.blog/images/2019/05-image-67.png" alt="Featured image of post IFTTT Flow D365" />&lt;p>This will be a quick post, as the connector doesn&amp;rsquo;t take a lot of configuration.&lt;/p>
&lt;h2 id="the-business-scenario">The Business Scenario&lt;/h2>
&lt;p>Big Energy has a lot of sales people, all over the country, which make a lot of calls, usually on their mobiles, to potential or current customers, arranging opportunities and resolving any issues.&lt;/p>
&lt;p>The Sales Director at Big Energy is concerned about the number of calls that the sales people don&amp;rsquo;t always log those calls, only when they deem it important and have no traceability about how many calls an individual has made.&lt;/p>
&lt;p>Could a solution be found that would log every call a sales person makes to a number D365 knows about?&lt;/p>
&lt;h2 id="ifttt">IFTTT&lt;/h2>
&lt;p>&lt;a class="link" href="https://ifttt.com" target="_blank" rel="noopener"
>IFTTT&lt;/a> (IF This Then That) is a free web service that allows users to create applets to connect their devices with their services. There are lots of sample applets to automate tasks, my favourite is linking Alexa&amp;rsquo;s shopping list with Tesco to add everything I add to Alexa to my Tesco order. Simples.&lt;/p>
&lt;p>IFTTT works with a lot of devices and it has a stand alone app for smart phones, allowing interaction with the device.&lt;/p>
&lt;h3 id="getting-started">Getting Started&lt;/h3>
&lt;p>Log in to IFTTT and go to My Applets, then New Applet. Hit the big blue this&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-64.png"
loading="lazy"
>&lt;/p>
&lt;p>Search for phone, and select Android Phone Call (sorry think this is only Android users)&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-65.png"
loading="lazy"
>&lt;/p>
&lt;p>This presents you with several triggers, the IF part. Select Any Phone Call placed. You will have to make another App for received, but same logic.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-66.png"
loading="lazy"
>&lt;/p>
&lt;p>The next step is to tell IFTTT what you want to do, select the big That button&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-67.png"
loading="lazy"
>&lt;/p>
&lt;p>IFTTT lets you search for all the available services that you can trigger from your data. Search for Web and select Webhooks.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-68.png"
loading="lazy"
>&lt;/p>
&lt;p>The only option here is to make a web request.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-69.png"
loading="lazy"
>&lt;/p>
&lt;p>If you have read my previous articles (if not go &lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365-part-1/" >here&lt;/a> or &lt;a class="link" href="https://linked365.blog/2019/04/19/alexa-field-service-and-me-part-1/" >here&lt;/a> now and shame on you), creating a Flow trigger from a web request should be straight forward.&lt;/p>
&lt;h2 id="create-the-flow">Create the Flow&lt;/h2>
&lt;p>As in the previous articles, start with a generic http trigger in Flow. Firstly, select HTTP trigger, and enter a default body for the JSON. This is generic enough to allow the call so the schema passed from IFTTT can be created.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-70.png"
loading="lazy"
>&lt;/p>
&lt;p>As the action, send yourself an email, with the Body of the email being the body of the request.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-71.png"
loading="lazy"
>&lt;/p>
&lt;p>Hit save and go back to the trigger. This URL is the bit you need to pop back into IFTTT.&lt;/p>
&lt;h2 id="connecting-flow-and-ifttt">Connecting Flow and IFTTT&lt;/h2>
&lt;p>Back in the IFTTT Web Request, paste in the URL. I have changed the Method to Post, content type to json and included in the Body 3 ingredients (data returned by the call placed method trigger into the body. This is formatted appropriately to become a valid JSON Request&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-72.png"
loading="lazy"
>&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-74.png"
loading="lazy"
>&lt;/p>
&lt;p>This is now ready for testing.&lt;/p>
&lt;h2 id="testing">Testing&lt;/h2>
&lt;p>For testing to commence, a call needs to be logged. This means you need to install the IFTTT app on your phone, log in and check the app you created is available.&lt;/p>
&lt;p>Once this is done, make a call.&lt;/p>
&lt;p>If successfully, your Flow should run, sending you an email. If not, you can look in the IFTTT log by checking the activity log.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-75.png"
loading="lazy"
>&lt;/p>
&lt;p>The log highlights what happened for each run, when it was updated etc. Not as user friendly as Flow, but at least you get an error code. I found I was getting 400 errors, as the format for the JSON wasn&amp;rsquo;t correct.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-77.png"
loading="lazy"
>&lt;/p>
&lt;p>My email also has the information sent from the request, this is used to tell Flow properly what is expected, allowing access to the properties.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-79.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="is-the-contact-known">Is the Contact known?&lt;/h2>
&lt;p>The assumption is that not all calls made by the user will be to known contacts. Either unknown to D365 or personal calls. The first thing that is required is to find the contact. Using the List Records component, use a filter query to return all contacts that match the data coming from IFTTT with any of the phone numbers held against contact. Be careful here, as the number as entered by the user in the contact on their phone or as dialed is used here.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-80.png"
loading="lazy"
>&lt;/p>
&lt;p>The next step is to check if any contacts were found. As previously, check the length of the return from the previous step has one or more contacts in it. Add the contact id to a variable if contacts were returned, terminate with grace if not.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-83.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="create-the-phone-call">Create the Phone Call&lt;/h2>
&lt;p>Creating the phone call is a straight forward call to the CDS Create Record action.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image.png"
loading="lazy"
>&lt;/p>
&lt;p>Couple of formulas here, firstly the timestamp that comes from IFTTT looks like&lt;/p>
&lt;p>May 01, 2019 at 05:50PM&lt;/p>
&lt;p>Flow doesn&amp;rsquo;t like this, so the expression for Due is&lt;/p>
&lt;p>replace(triggerBody()?[&amp;lsquo;occuredat&amp;rsquo;], &amp;rsquo; at &amp;lsquo;,&amp;rsquo; &amp;lsquo;)&lt;/p>
&lt;p>Duration from IFTTT is in seconds, in D365 is minutes. A simple divide by 60 puts in the right value&lt;/p>
&lt;p>div(int(triggerBody()?[&amp;lsquo;callLength&amp;rsquo;]),60)&lt;/p>
&lt;p>Flow is complete.&lt;/p>
&lt;h2 id="can-it-be-be-recorded-better">Can it be be recorded better?&lt;/h2>
&lt;p>The call that Flow creates is missing 2 key components, the From and To&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-1.png"
loading="lazy"
>&lt;/p>
&lt;p>The CDS connector doesn&amp;rsquo;t support &lt;a class="link" href="https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/activity-entities" target="_blank" rel="noopener"
>activity parties&lt;/a> (these fields are both party fields, the user can type and search for multiple contacts, users, leads etc to populate this normally). You can get at these via standard API calls, so back to the custom connector.&lt;/p>
&lt;p>My previous &lt;a class="link" href="https://linked365.blog/2019/04/03/connecting-luis-d365-part-4-custom-connector/" >post&lt;/a> on LUIS used a custom connector to close the incident using an action. This walks through creating the connector, so I won&amp;rsquo;t repeat myself.&lt;/p>
&lt;p>I will step through the specific action for creating the call, as it isn&amp;rsquo;t straight forward. Further, Postman is still your friend. The only way I managed to get this configured is relying on this great tool.&lt;/p>
&lt;p>Using Postman, the format of the JSON can be defined, based on the API reference for &lt;a class="link" href="https://docs.microsoft.com/en-us/dynamics365/customer-engagement/web-api/phonecall?view=dynamics-ce-odata-9" target="_blank" rel="noopener"
>Phonecalls&lt;/a>. This highlights that activity parties are created, and associated with the call to create the phonecall.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;subject&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CC Test&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;scheduledend&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2019-05-01 12:00&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;regardingobjectid\_contact@odata.bind&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/contacts(A651968A-5660-E911-A973-000D3A3ACAF8)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;directioncode&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;scheduleddurationminutes&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">6&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;phonenumber&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;test&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;phonecall\_activity\_parties&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="err">\&lt;/span>&lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;partyid\_contact@odata.bind&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/contacts(A651968A-5660-E911-A973-000D3A3ACAF8)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;participationtypemask&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;partyid\_systemuser@odata.bind&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/systemusers(C3AE1146-AD6D-E911-A984-000D3A3AC0C2)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;participationtypemask&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="err">\&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Take this JSON body and copy into a new action in your custom connector.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-2.png"
loading="lazy"
>&lt;/p>
&lt;p>Enter details in the general page, just enough to uniquely identify your action. Of course, you need to be a bit more descriptive if you plan on shipping out the connector.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-3.png"
loading="lazy"
>&lt;/p>
&lt;p>Select Import from Sample, Select Post, the URL should be just PhoneCalls, paste the JSON above into the body&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-4.png"
loading="lazy"
>&lt;/p>
&lt;p>Flow does some magic and now you can update your connector. I tried testing this, but got a little confused (me of little brain) so I assumed that Flow is good and would handle it and went straight to using the connector in Flow.&lt;/p>
&lt;p>Back in Flow, select a new action, custom connector, the new one you just created and the action established.&lt;/p>
&lt;p>The populate as below. I know the parameters are not the best names, someone with a bit more time would have tidied this up.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-5.png"
loading="lazy"
>&lt;/p>
&lt;p>These are the same formulas that were used earlier. You need to add the &amp;ldquo;/contacts(&amp;rdquo; etc to each GUID as the data bind requires it.&lt;/p>
&lt;p>Run the Flow and just like that, the Phone Call is created in D365 with a Call To correctly established.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/05-image-7.png"
loading="lazy"
>&lt;/p>
&lt;p>Call From is missing, IFTTT doesn&amp;rsquo;t let the Web call know who called it. I have searched, but IFTTT is meant for home grown activity, so if you have registered the app, you should know the call. The easiest way around this is to pass in a hardcoded value (email) specific to the end user so a System user can be looked up and populated in the parties field.&lt;/p></description></item><item><title>Alexa, Field Service and Me (Part 3) - Creating Work Orders</title><link>https://linked365.blog/2019/04/25/alexa-field-service-and-me-part-3-creating-work-orders/</link><pubDate>Thu, 25 Apr 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/04/25/alexa-field-service-and-me-part-3-creating-work-orders/</guid><description>&lt;img src="https://linked365.blog/images/2019/04-image-31.png" alt="Featured image of post Alexa, Field Service and Me (Part 3) - Creating Work Orders" />&lt;p>This is a continuation of my series on a proof of concept to allow Alexa to interact with D365 Field Service&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Business scenario (&lt;a class="link" href="https://linked365.blog/2019/04/19/alexa-field-service-and-me-part-1/" >Part 1&lt;/a>&lt;/li>
&lt;li>Create an Alexa Skill (&lt;a class="link" href="https://linked365.blog/2019/04/19/alexa-field-service-and-me-part-1/" >Part 1&lt;/a>)&lt;/li>
&lt;li>Connect the Skill to D365 (&lt;a class="link" href="https://linked365.blog/2019/04/20/alexa-field-service-and-me-part-2-linking-to-flow/" >Part 2&lt;/a>)&lt;/li>
&lt;li>Use Field Service to book an appointment (This Part)&lt;/li>
&lt;li>Return the information to Alexa (&lt;a class="link" href="https://linked365.blog/2019/04/20/alexa-field-service-and-me-part-2-linking-to-flow/" >Part 2&lt;/a>)&lt;/li>
&lt;/ul>
&lt;p>In this final (unless I need to expand on the scenarios) part of the story, Flow will be used to take the information garnered from the user and create a work order.&lt;/p>
&lt;h2 id="calling-a-sub-flow">Calling a Sub-flow&lt;/h2>
&lt;p>The original flow was all about Alexa, but what about other voice assistants? Flow is no different that any other programming languages and as such we can use the same concepts to writing decent flows, one of them being re-usability. If the code to write the Work order and book it is generic, it can be re-used when Google or Siri is connected to the application.&lt;/p>
&lt;p>To this end, the Flow starts with another HTTP trigger, which is called from the previous flow.&lt;/p>
&lt;p>Just like when connection Flow to Alexa, the URL is required in the child to update the caller. Create a new Flow, using the When a HTTP request is received. As content to the JSON Schema, add just enough to get you going and use the output to send an email so that the schema coming from the parent flow can be seen. This is a repart of the logic used to start our parent flow.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-34.png"
loading="lazy"
>&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-35.png"
loading="lazy"
>&lt;/p>
&lt;p>Once saved, the URL will be generated in the trigger step. Use this to call the child Flow from the parent. This is the HTTP action. The Method is a POST, the URI is the trigger URL defined in the child Flow. No headers are required. In the body, add in the things that are already known, just to ensure repeat calls to D365 are made. The Intent is also passed in, which has all the details about what the user wanted.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-55.png"
loading="lazy"
>&lt;/p>
&lt;p>Now ready for testing, ensure both Flows are in Test mode and trigger Alexa. After a little delay, an email should be sent in the child Flow detailing enough information to create a Work Item.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-56.png"
loading="lazy"
>&lt;/p>
&lt;p>Use this email to populate the JSON as previously, easily creating the schema that is required.&lt;/p>
&lt;h2 id="creating-a-work-order">Creating a Work Order&lt;/h2>
&lt;p>Next, get the Account the contact is associated with. This is done with a call to the D365 Instance using the Common Data Service Connector.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-57.png"
loading="lazy"
>&lt;/p>
&lt;p>A Work Order needs some fields to be set before it can be save, Work Order Type is one of them. This could be hard coded, but Alexa has supplied the intent. To match the Work order type with the intention in Alexa, a field on the Work Order Type was added, Alexa Intent, which is searched for in the CDS List Records action.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-58.png"
loading="lazy"
>&lt;/p>
&lt;p>To make the Flow easier to manage and reduce the dual looping, the Work Order Type is returned to a variable&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-60.png"
loading="lazy"
>&lt;/p>
&lt;p>Once the data for the new Work Order is available, create the Work Order using the CDS Create Record connector.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-61.png"
loading="lazy"
>&lt;/p>
&lt;p>Most of these are obvious, but the one that is not is the Work Order Number. In Field Service, this is automated, with a prefix and a number range. As this doesn&amp;rsquo;t work in Flow, a work number is generated using a random number, using an expression.&lt;/p>
&lt;p>rand(10000,100000)&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-62.png"
loading="lazy"
>&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-63.png"
loading="lazy"
>&lt;/p>
&lt;p>A few other parts of the work order are populated, helping the service manager to match the time as appropriate.&lt;/p></description></item><item><title>Alexa, Field Service and Me (Part 2) - Linking to Flow</title><link>https://linked365.blog/2019/04/20/alexa-field-service-and-me-part-2-linking-to-flow/</link><pubDate>Sat, 20 Apr 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/04/20/alexa-field-service-and-me-part-2-linking-to-flow/</guid><description>&lt;img src="https://linked365.blog/images/2019/04-image-31.png" alt="Featured image of post Alexa, Field Service and Me (Part 2) - Linking to Flow" />&lt;p>This is a continuation of my series on a proof of concept to allow Alexa to interact with D365 Field Service&lt;/p>
&lt;h2 id="objectives">Objectives&lt;/h2>
&lt;ul>
&lt;li>The Business scenario (&lt;a class="link" href="https://linked365.blog/2019/04/19/alexa-field-service-and-me-part-1/" >Part 1&lt;/a>)&lt;/li>
&lt;li>Create an Alexa Skill (&lt;a class="link" href="https://linked365.blog/2019/04/19/alexa-field-service-and-me-part-1/" >Part 1&lt;/a>)&lt;/li>
&lt;li>Connect the Skill to D365 (This part)&lt;/li>
&lt;li>Use Field Service to book an appointment (&lt;a class="link" href="https://linked365.blog/2019/04/25/alexa-field-service-and-me-part-3-creating-work-orders/" >Part 3&lt;/a>)&lt;/li>
&lt;li>Return the information to Alexa (This part)&lt;/li>
&lt;/ul>
&lt;p>In this post I will be linking Alexa to D365 and returning some information back to the end user.&lt;/p>
&lt;h2 id="receiving-information-from-alexa">Receiving information from Alexa&lt;/h2>
&lt;p>Alexa interacts with the outside world with a HTTPS request. Once Alexa has determined that it understands the user and they have asked for something of your skill, it posts to the web service you have configured.&lt;/p>
&lt;p>That API Guy had a great &lt;a class="link" href="https://thatapiguy.tech/2019/03/11/alexa-ask-microsoft-flow-to-read-out-my-latest-e-mail/" target="_blank" rel="noopener"
>post&lt;/a> where he links his Alexa to his O365 email account and has Alexa read out his new email. This article steps through linking Alexa and Flow, and it showed me how simple that part of the integration is. Microsoft has done the hard work by certifying it&amp;rsquo;s connections, you just need to create one.&lt;/p>
&lt;p>Flow provides several methods of subscribing to HTTP events, but the one we are interested in is at the bottom&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-33.png"
loading="lazy"
>&lt;/p>
&lt;p>The URL is generated for you, and is the bit you need to post into Alexa Skill configuration once we have created the Flow. In the JSON schema, we just want a stub for now. The schema is defined by Alexa and how you configure the skill. It is best to get the connection up and running and use the initial call to substitute the schema later.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-34.png"
loading="lazy"
>&lt;/p>
&lt;p>Every Flow needs at least one action to be able to save, so to aid testing and understand the JSON sent by Alexa, the first step is to send an email to myself with the content of the call.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-35.png"
loading="lazy"
>&lt;/p>
&lt;p>Saving the flow and go back to the trigger&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-36.png"
loading="lazy"
>&lt;/p>
&lt;p>A specific trigger URL for our Flow is now generated.&lt;/p>
&lt;h3 id="back-in-alexa">Back in Alexa&lt;/h3>
&lt;p>In Alexa, on the left in the Skill is Endpoints. Alexa allows different endpoints to the skill depending on the Alexa region as well as a fall back. As this is a POC, using the default is appropriate.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-37.png"
loading="lazy"
>&lt;/p>
&lt;p>The important part of this is the drop down below the URL copied from Flow, this needs to be the second option &amp;ldquo;&lt;em>My development endpoint is a sub-domain of a domain that has a wild card certificate from a certificate authority&lt;/em>&amp;rdquo;. Basically, Microsoft has certified all their Flow endpoints with wild card certificates, allowing Amazon to trust that it is genuine.&lt;/p>
&lt;p>One saved, Build your skill again. I found every time I touched any configuration or indeed anything in Alexa, I needed to rebuild.&lt;/p>
&lt;h2 id="testing">Testing&lt;/h2>
&lt;p>Ready to test. Alexa allows you to test your connection via the Test tab within your skill.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-38.png"
loading="lazy"
>&lt;/p>
&lt;p>You have to select Development from the drop down. You can also use this interface to check Production skills.&lt;/p>
&lt;p>A word of warning, everytime you build, to test that new build, I found I had to re-select Development in this window by toggling between &amp;ldquo;Off&amp;rdquo; and &amp;ldquo;Development&amp;rdquo;.&lt;/p>
&lt;p>Back in Flow, test your flow by confirming that you will conduct the action.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-39.png"
loading="lazy"
>&lt;/p>
&lt;p>In the Test panel in Alexa, enter a phrase with your Invocation and Utterance in Alexa entry and if Alexa understands it is for your invocation, your flow should be triggered! Alexa will complain, as our simple flow hasn&amp;rsquo;t returned anything to it. We&amp;rsquo;ll worry about that later.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-40.png"
loading="lazy"
>&lt;/p>
&lt;p>In our simple Flow, I used email as the action, as can be seen below.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-41.png"
loading="lazy"
>&lt;/p>
&lt;p>This is the raw JSON output of the Alexa skill and this is used to tell Flow what to expect. This way it will provide the rest of the Flow with properties that are more appropriate.&lt;/p>
&lt;p>Back in the Flow trigger, select Use sample payload to generate schema, which presents the text entry, where you paste in the email body.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-42.png"
loading="lazy"
>&lt;/p>
&lt;p>Flow does the hard work now and presents you with a schema for what Alexa is sending your Flow&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-43.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="authenticating-the-user">Authenticating the user&lt;/h2>
&lt;p>Taking triggers from Alexa, hence a user is all well and good, but they expect a rapid response. Alexa Skills are public domain once you publish it, anyone can enable your skill, hence a little work needs to be done to understand who is calling our skill and whether Big Energy Co supports them.&lt;/p>
&lt;h3 id="which-user-is-it">Which User is it?&lt;/h3>
&lt;p>The request from Alexa does include a unique reference of the user, but normally businesses like Big Energy Co work on email addresses, which you can get from Alexa, but the user has to give you permission. This can be pre-approved when the end user installs the skill or you can ask for approval.&lt;/p>
&lt;p>Alexa needs to be told that your skill would like this permission. This allows Alexa to request this permission for you when your skill is enabled by the user&lt;/p>
&lt;p>On the left hand menu, there is a Permissions link, where our skill asks for the email address&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-45.png"
loading="lazy"
>&lt;/p>
&lt;p>To ask Alexa for an users email address is a seperate web call with properties from original message sent from Alexa in the trigger.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-44.png"
loading="lazy"
>&lt;/p>
&lt;p>Alexa provides each session an access token so that Flow can ask for more information from Alexa in the context of the users session, location, names, email etc. As this is a globally distributed system, the api End point can vary depending on where the user started their session. The URI at the end asks for the email address of the user of the session.&lt;/p>
&lt;p>Alexa may refuse to return the email address, because the end user has not given permission for our skill to share this information. If the call to get the email was a success, it means that Alexa has returned the value and the Flow can continue&lt;/p>
&lt;p>Without the permission, the call fails and so the Flow captures this. Remember to set a run after for this step to ensure it still runs on failure. Otherwise the flow will fail not so gracefully.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-46.png"
loading="lazy"
>&lt;/p>
&lt;p>Alexa provides standard permission request functionality, the Flow responds to the original call with this detail in a JSON formatted string, with the permissions the Skill wants listed. Finally, for this failure, let the Flow terminate successfully. The Flow can&amp;rsquo;t continue without the information.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-47.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="does-big-energy-co-support-the-user">Does Big Energy Co support the user?&lt;/h3>
&lt;p>It is not enough that the user has asked us for help, they need to be known to Big Energy, as a contact. Querying D365 for this data is the next step&lt;/p>
&lt;p>Using the D365 connector, query the contact entity for the email address that Alexa has given us.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-48.png"
loading="lazy"
>&lt;/p>
&lt;p>A conditional flow checks to see if the return from the Retrieve Contact step has a single record using an expression below&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-54.png"
loading="lazy"
>&lt;/p>
&lt;p>length(body(&amp;lsquo;Retrieve_Contact&amp;rsquo;)?[&amp;lsquo;value&amp;rsquo;])&lt;/p>
&lt;h2 id="responding-to-the-user-quickly">Responding to the user, quickly&lt;/h2>
&lt;p>Like any Alexa Skill, the user expects an immediate response. Flow in itself is quick, but when it comes to updating or creating records, it can take seconds. The timeout for your response to Alexa is 10 seconds, which isn&amp;rsquo;t a lot when you want to look up several things to create the appropriate work order.&lt;/p>
&lt;p>To get around this, respond to the user once you know you have all the information you need to create the appropriate records in D365. Here, the Flow responds if the contact is in our database. In production, you could do some more checks or just assume that if the contact is known, the logic could create an opportunity to sell them a contract if nothing else. Equally, terminate gracefully after responding that Big Energy Co doesnt know the customer, prompting them to ring the service desk.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-51.png"
loading="lazy"
>&lt;/p>
&lt;p>In the switch statement, a response to the user is built up. Specific, personalised responses using the data you have retrieved is essential to give the customer an understanding that you have received the request and will respond.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-50.png"
loading="lazy"
>&lt;/p>
&lt;p>The responses are short and to the point but personalised to the customer and what they asked for with some expressions to add more information if they told Alexa.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-52.png"
loading="lazy"
>&lt;/p>
&lt;p>This snippet adds after &amp;ldquo;request for a Service&amp;rdquo; what the user asked for a service on, relying on the JSON formatted values.&lt;/p>
&lt;p>if(equals(triggerBody()?[&amp;lsquo;request&amp;rsquo;]?[&amp;lsquo;intent&amp;rsquo;]?[&amp;lsquo;slots&amp;rsquo;]?[&amp;lsquo;device&amp;rsquo;]?[&amp;lsquo;value&amp;rsquo;], &amp;lsquo;&amp;rsquo;), &amp;lsquo;&amp;rsquo;, concat(&amp;rsquo; for your &amp;lsquo;,triggerBody()?[&amp;lsquo;request&amp;rsquo;]?[&amp;lsquo;intent&amp;rsquo;]?[&amp;lsquo;slots&amp;rsquo;]?[&amp;lsquo;device&amp;rsquo;]?[&amp;lsquo;value&amp;rsquo;]))&lt;/p>
&lt;p>This snippet adds to the end a sentence including the date that the user asked for.&lt;/p>
&lt;p>if(equals(triggerBody()?[&amp;lsquo;request&amp;rsquo;]?[&amp;lsquo;intent&amp;rsquo;]?[&amp;lsquo;slots&amp;rsquo;]?[&amp;lsquo;date&amp;rsquo;]?[&amp;lsquo;value&amp;rsquo;],&amp;rsquo;&amp;rsquo;),&amp;rsquo;&amp;rsquo;,concat( &amp;lsquo;We will endeavour to send an engineer on &amp;lsquo;,triggerBody()?[&amp;lsquo;request&amp;rsquo;]?[&amp;lsquo;intent&amp;rsquo;]?[&amp;lsquo;slots&amp;rsquo;]?[&amp;lsquo;date&amp;rsquo;]?[&amp;lsquo;value&amp;rsquo;]))&lt;/p>
&lt;p>Finally, for the Alexa response part, the Flow returns a response to the user. This combines the body with a little standard text. This is what Alexa will say. You can also add a response to the screen for those devices able to do that.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-53.png"
loading="lazy"
>&lt;/p>
&lt;p>The final part of this flow goes on and creates the work order. I seperated out the flows using a sub flow, which is discussed in the next part of the blog.&lt;/p></description></item><item><title>Alexa, Field Service and Me (Part 1)</title><link>https://linked365.blog/2019/04/19/alexa-field-service-and-me-part-1/</link><pubDate>Fri, 19 Apr 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/04/19/alexa-field-service-and-me-part-1/</guid><description>&lt;img src="https://linked365.blog/images/2019/04-image-31.png" alt="Featured image of post Alexa, Field Service and Me (Part 1)" />&lt;p>As we all now have smart devices in our home, linking them to business applications could be a key differentiator between winners and the also rans. This series of posts will demonstrate how I connected Alexa to D365 Field service.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-31.png"
loading="lazy"
>&lt;/p>
&lt;h4 id="objectives">Objectives&lt;/h4>
&lt;ul>
&lt;li>The Business scenario (this part)&lt;/li>
&lt;li>Create an Alexa Skill (this part)&lt;/li>
&lt;li>Connect the Skill to D365 (&lt;a class="link" href="https://linked365.blog/2019/04/20/alexa-field-service-and-me-part-2-linking-to-flow/" target="_blank" rel="noopener"
>Part 2&lt;/a>)&lt;/li>
&lt;li>Use Field Service to book an appointment (&lt;a class="link" href="https://linked365.blog/2019/04/25/alexa-field-service-and-me-part-3-creating-work-orders/" target="_blank" rel="noopener"
>Part 3&lt;/a>)&lt;/li>
&lt;li>Return the information to Alexa (&lt;a class="link" href="https://linked365.blog/2019/04/20/alexa-field-service-and-me-part-2-linking-to-flow/" target="_blank" rel="noopener"
>Part 2&lt;/a>)&lt;/li>
&lt;/ul>
&lt;h2 id="our-scenario---big-energy-co">Our Scenario - Big Energy Co&lt;/h2>
&lt;p>Our generic big energy company is diversifying into support and maintenance of home energy products, boilers, central heating, plumbing, electricals and numerous other aspects of a consumer&amp;rsquo;s home life. A client will ring up, tell the support desk that they have an issue with the appliance and the employee will book a suitable engineer in to come out to their home. This is all done via Field Service in D365. Big Energy also have scheduled servicing of Boilers on an annual basis.&lt;/p>
&lt;p>What the CTO wants to do is embrace the in home virtual assistant to promote Big Energy as a forward thinking organisation which is at the forefront of technology to allow Big Energy&amp;rsquo;s customers to book an engineers visit via their smart device. Her expectation is that Alexa, Google Home or Siri will allow a service call to be booked without talking to the support desk. This will allow meaningful interactions with their customers 24/7.&lt;/p>
&lt;p>The proof of concept will start with the front runner in the war of virtual assistance, mostly because I have one.&lt;/p>
&lt;h2 id="alexa">Alexa&lt;/h2>
&lt;p>If you have read my introduction to &lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365/" target="_blank" rel="noopener"
>LUIS&lt;/a> in Alexa Skill concepts are a mirror of the concepts introduced in LUIS. Alexa has Utterances &amp;amp; Intents. Entities are called Intent Slots for Alexa. Alexa has also got another concept, that being the Invocation.&lt;/p>
&lt;p>First off, get yourself an Amazon account &amp;amp; sign up for the developer program at &lt;a class="link" href="https://developer.amazon.com/" target="_blank" rel="noopener"
>developer.amazon.com.&lt;/a> This is all free. People can buy skills, but not sure Big Energy&amp;rsquo;s customers would think this is appropriate.&lt;/p>
&lt;p>Use the Create Skill button, enter a name &amp;amp; select a language. I also choose Custom &amp;amp; Provision your own to allow us to send data to Flow which is hosting our integration.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-23.png"
loading="lazy"
>&lt;/p>
&lt;p>Then I select Start from scratch, none of the others seem to match our scenario&lt;/p>
&lt;h3 id="invocation">Invocation&lt;/h3>
&lt;p>An Invocation is the starting point and is the differentiator between you and every other Alexa skill out there. It is effectively a name for your skill, what the user would say to call your skill. I have slightly altered my invocation to put some spaces in there so it is more natural to the end user.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-24.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="intents">Intents&lt;/h3>
&lt;p>Like in LUIS, intents are a category or what the user is looking for or asking. You can have many intents per skill. In our scenario around home appliances the user can ask for a service, a repair or an emergency as a starting point. Let&amp;rsquo;s start with a request for service.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-25.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="utterances">Utterances&lt;/h3>
&lt;p>Utterances are samples to train Alex to understand the intent in natural language. Add as many utterances as you like as samples of how a person would ask for a service or repair, but ensure they are different.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-26.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="slots">Slots&lt;/h3>
&lt;p>In my sample utterances above you can see I have added Slots. Slots are the same as entities in LUIS, data that the user gives us when they are saying their utterance in addition to the type of thing they want.&lt;/p>
&lt;p>Each Slot has a type, and I have used the default Amazon types except for device, which is a custom one.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-28.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="slot-types">Slot Types&lt;/h3>
&lt;p>Amazon has 43 of it&amp;rsquo;s own list types or 6 built in types for numbers &amp;amp; dates, but devices are not in the list. I want to know what type of thing the engineer is going out to fix, not sure I need to be that specific, but would be good to know if I need to send an electrician, gas engineer or plumber. I have added my own Slot Type, called it device and I now list the values I expect.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-29.png"
loading="lazy"
>&lt;/p>
&lt;p>You also should also enter synonyms, not everyone calls it a telly, just us northeners.&lt;/p>
&lt;p>Once you have entered enough intents &amp;amp; utterances, time to build and test. A nice message lets you know when it is done building. Ready for the utterance profiler or testing&lt;/p>
&lt;h2 id="utterance-profiler">Utterance Profiler&lt;/h2>
&lt;p>In the top right, is a pop out to test your utterances. Enter an utterance you haven&amp;rsquo;t used before to check you are getting the expected results.&lt;/p>
&lt;p>The text I wrote is in blue, it has decided that this is a service intent, with a device of boiler &amp;amp; the day of wednesday.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-30.png"
loading="lazy"
>&lt;/p>
&lt;p>You can carry on fine tuning your utterances, intents and slots to get the most accurate model. Like any language understanding, this will be an ongoing model.&lt;/p>
&lt;p>This is Alexa done, we have configured everything we need to in Alexa, apart from our link to Flow. This needs a bit of pre-work in Flow to activate, in the next &lt;a class="link" href="https://linked365.blog/2019/04/20/alexa-field-service-and-me-part-2-linking-to-flow/" target="_blank" rel="noopener"
>post&lt;/a>.&lt;/p></description></item><item><title>Connecting LUIS &amp; D365 (part 4) - Custom Connector</title><link>https://linked365.blog/2019/04/03/connecting-luis-d365-part-4-custom-connector/</link><pubDate>Wed, 03 Apr 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/04/03/connecting-luis-d365-part-4-custom-connector/</guid><description>&lt;img src="https://linked365.blog/images/2019/04-luisd365-e1554192911124.jpg" alt="Featured image of post Connecting LUIS &amp; D365 (part 4) - Custom Connector" />&lt;p>In my previous &lt;a class="link" href="https://linked365.blog/2019/04/02/connecting-luis-to-d365-part-3/" >post&lt;/a>, the fact that I had to &amp;ldquo;fudge&amp;rdquo; the routing and closure of the case irked me. Whilst at D365 EU Summit in Amsterdam, I spent an hour listening to Serge Luca (his excellent blog is &lt;a class="link" href="https://sergeluca.wordpress.com/" target="_blank" rel="noopener"
>here)&lt;/a>. He inspired me to think that we could close this loop using a Custom Connector in Flow connected to our D365 instance, allowing an API call directly to the closure action.&lt;/p>
&lt;p>Back in the UK, I did some digging, found another excellent blog from Andrew Butenko which steps through doing this for Won Opportunity &lt;a class="link" href="https://butenko.pro/2018/11/30/calling-d365-actions-functions-from-flow/" target="_blank" rel="noopener"
>here&lt;/a>, so just to complete the circle I will step through how I did this.&lt;/p>
&lt;h2 id="create-the-app-in-azure">Create the App in Azure&lt;/h2>
&lt;p>This is a bit heavy for a citizen developer &amp;amp; in the real world you will have to ask your O365 admin to do this, but in my trail I have the appropriate access.&lt;/p>
&lt;p>Go to &lt;a class="link" href="http://portal.azure.com" target="_blank" rel="noopener"
>portal.azure.com&lt;/a> &amp;amp; log in using your CRM Admin credentials.&lt;/p>
&lt;p>In the left pane, select Azure Active Directory, then App Registrations (Preview) then New registration. Give it a name, select Accounts in this organizational directory only &amp;amp; enter localhost as a temporary redirect URL, this will change later. Select Register &amp;amp; allow Azure to do it&amp;rsquo;s stuff&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-3.png"
loading="lazy"
>&lt;/p>
&lt;p>On the next screen, select API Permissions, then Add a permission&lt;/p>
&lt;p>The one we are interested in is Dynamics CRM. Select it.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-4.png"
loading="lazy"
>&lt;/p>
&lt;p>Check the box next to user_impersonation. Select Add permissions &amp;amp; now you should have 2 permissions for your new application. Now we need to ensure only we can access it.&lt;/p>
&lt;p>In Certificates &amp;amp; secrets, select New client secret. Give it a Description and decide how long you want to wait before it expires. Not an issue for our demo, our trial wont last as long as this expiry. Once created, make sure you copy the value information, you won&amp;rsquo;t be able to retrieve this at a later stage.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-5.png"
loading="lazy"
>&lt;/p>
&lt;p>We also need the application id, this is available on the Overview tab&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-6.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="create-a-custom-connector">Create a Custom Connector&lt;/h2>
&lt;p>Back in flow, under Data &amp;amp; then Custom Connectors there is a Create custom connector drop down, select Create from blank and give it a name.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-7.png"
loading="lazy"
>&lt;/p>
&lt;p>On the next screen, you can customise the description &amp;amp; logo if you want, but the important bit is the Host, which is your instance url, and the Base URL which is the api access path.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-11.png"
loading="lazy"
>&lt;/p>
&lt;p>Select Security next &amp;amp; choose OAuth 2.0. Identity Provider should be Azure Active Directory, Client Id is the Application Id from previous &amp;amp; Client Secret is also from the previous step. Login URL, Tenant ID &amp;amp; Scope should be left to their default. Resource URL is the url to your environment.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-9.png"
loading="lazy"
>&lt;/p>
&lt;p>Save the connector by using the Update Connector now. There is an important piece of information, the Redirect URL, which we have to copy &amp;amp; add to our connector back in Azure.&lt;/p>
&lt;p>Select the App Registration in Azure, select Redirect URIs&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-12.png"
loading="lazy"
>&lt;/p>
&lt;p>Add a new one from your copied redirect (I think it is standard, as I have only seen one, but just to be sure)&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-13.png"
loading="lazy"
>&lt;/p>
&lt;p>The next screen allows you to add Actions &amp;amp; triggers. I think there could be a whole new blog post on using triggers this way. As custom connector is generic across all apis, the flexibility is great. Select New Action.&lt;/p>
&lt;p>The General section describes the connector in Flow, so useful but nothing special is required apart from the Operation Id, which is what api action you want to call &amp;amp; must be unique within each connector.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-15.png"
loading="lazy"
>&lt;/p>
&lt;p>Select Import from sample. This would usually be a sample JSON function. I built mine using Postman, and this is a bit more than a citizen developer would be able to handle without experience. Federico Jousset has a great &lt;a class="link" href="http://www.fedejousset.com/2018/10/03/dynamics-365-web-api-postman-collection/" target="_blank" rel="noopener"
>blog pos&lt;/a>t on using Postman to &amp;ldquo;play&amp;rdquo; with D365 end points, including a link to an extensive Postman collection with lots of examples which were the key to understanding the call, particularly the parameters.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-16.png"
loading="lazy"
>&lt;/p>
&lt;p>When you hit import, you will get this section under Request. The bit we are interested in is at the bottom, the body.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-17.png"
loading="lazy"
>&lt;/p>
&lt;p>Click on body, then edit you will see a list of the parameters that Flow inferred from the sample body we gave it.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-18.png"
loading="lazy"
>&lt;/p>
&lt;p>Select Incident Id for example, we can now give it a little more information &amp;amp; more importantly give the end user of the low more information with the Title &amp;amp; default value &amp;amp; whether it is required&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-19.png"
loading="lazy"
>&lt;/p>
&lt;p>We are now ready to Test. Select the test button, choose New Connection &amp;amp; connect to your D365 system. Enter the appropriate values, but be careful over the incident Id, as it is expecting a odata conversion. Someone better at connectors could tell me why.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-21.png"
loading="lazy"
>&lt;/p>
&lt;p>If everything is good, you will get a blank body response back, as this is how the CloseIncident works&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-20.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="using-the-connector-in-flow">Using the connector in Flow&lt;/h2>
&lt;p>In the previous article, I showed you how we had to use a custom field &amp;amp; workflow in D365 to close the incident. I can now replace that with my custom connector call&lt;/p>
&lt;p>Where I was updating a record because they were asking for their next bill, I remove the change to the CloseByFlow field and replace it with a seperate call&lt;/p>
&lt;p>In Flow, I add a new action, select the Custom Tab, my connector &amp;amp; the action I want, this case the CloseIncident. We need to mimic how the api is expceting the Case Id to be passed, which is why we send with the &amp;lsquo;/incidents(&amp;rsquo; prefix &amp;amp; &amp;lsquo;)&amp;rsquo; suffix.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-22.png"
loading="lazy"
>&lt;/p>
&lt;p>Test the flow &amp;amp; we have now completed the scenario. Case closure is now part of the flow.&lt;/p>
&lt;p>Custom connectors are new for Flow &amp;amp; give the Flow creator that step extra of functionality where the OOTB solutions don&amp;rsquo;t work.&lt;/p>
&lt;p>There is a word of caution about licensing here, I have been using a trial of E5, which gives you Flow for Office 365 License. I can create a custom connector to a standard application but not a custom application with it. This is the same for Flow for Dynamics 365, so I don&amp;rsquo;t need an extra license, but be warned.&lt;/p></description></item><item><title>Connecting LUIS to D365 (part 3)</title><link>https://linked365.blog/2019/04/02/connecting-luis-to-d365-part-3/</link><pubDate>Tue, 02 Apr 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/04/02/connecting-luis-to-d365-part-3/</guid><description>&lt;img src="https://linked365.blog/images/2019/04-luisd365-e1554192911124.jpg" alt="Featured image of post Connecting LUIS to D365 (part 3)" />&lt;p>In this 3rd installment of the series devoted to using Language Understanding (LUIS) to categorise emails via Flow, I will describe some of the parts of the D365 solution and walk through a final version of the Flow to extend its capabilities.&lt;/p>
&lt;p>This blog has at least 3 parts, but overall the posts objectives are&lt;/p>
&lt;ul>
&lt;li>Give you an understanding of a real-life scenario where we could implement LUIS – (&lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365-part-1" >Part 1&lt;/a>)&lt;/li>
&lt;li>Introduce you to the concepts of LUIS (&lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365-part-1" >Part 1&lt;/a>)&lt;/li>
&lt;li>Discuss the Microsoft Flow to connect LUIS to D365 (&lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-to-d365-part-2/" >Part 2&lt;/a>)&lt;/li>
&lt;li>Give you some next steps on how you can try to bring LUIS into your organisation&lt;/li>
&lt;/ul>
&lt;h2 id="routing-the-case">Routing the case&lt;/h2>
&lt;p>Standard Save and Route functionality only fires automatically on case creation, or when a user manually hits the button. This action is available in workflow, but not in the CRUD actions of the D365 or CDS connectors. To get around this there is a workflow triggered of the change of the subject field which calls the OOTB action ApplyRoutingRule. This effectively is the same as the user clicking the button.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-16.png"
loading="lazy"
>&lt;/p>
&lt;p>The routing rules are very simple, routing the case based on the subject selected.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-17.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="adding-information-from-the-case">Adding information from the case&lt;/h2>
&lt;p>In our scenario, based around a support desk for a large power company, one of the common requests is to provide meter readings. This data is invaluable.&lt;/p>
&lt;p>In LUIS, this information is called an Entity. You can configure entities for each of the Intents to denote some parcel of information that the user is telling you on top of the intent of their email.&lt;/p>
&lt;p>As you start typing and enter data, LUIS recognises this and replaces the data with a data type that it will use.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-18.png"
loading="lazy"
>&lt;/p>
&lt;p>In Flow, the return from LUIS will contain a list of all the entities it has found in your utterance. The flow then updates the case with this defined data, in a separate field on the case record.&lt;/p>
&lt;p>The first part of the flow checks the length of the array of entities that LUIS returned. If there are no entities, then just do a normal update of the case record. If there are entities, loop through them&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-19.png"
loading="lazy"
>&lt;/p>
&lt;p>As the entities array is looped through, check that the entity is a number. LUIS could return you a date or name. If it is not a number, just do a normal update of the record.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-20.png"
loading="lazy"
>&lt;/p>
&lt;p>If it is a number, pass the meter reading to the case update in the new field on the Case entity.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-21.png"
loading="lazy"
>&lt;/p>
&lt;p>This approach does lead to duplicate updates, 1 for each entity it finds. You may be better suited to extend the logic in a production system to prevent this.&lt;/p>
&lt;h2 id="auto-reply-for-common-intents">Auto-reply for common intents&lt;/h2>
&lt;p>In our scenario, one of the common requests that the help desk gets is to ask when the end user is due a bill. This again could be dealt with in numerous ways via workflow in D365, but doing it in Flow allows the demonstration of Flow&amp;rsquo;s abilities.&lt;/p>
&lt;p>The first part is to check the Top scoring intent is &amp;ldquo;Next Bill due&amp;rdquo;. The flow goes on to check for meter readings if it isn&amp;rsquo;t.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-22.png"
loading="lazy"
>&lt;/p>
&lt;p>Using D365 connector this time (Microsoft changes so quickly, it is hard to keep up with what the best methods are) I retrieve the contact that created the case then send them a nicely formatted email. This will send the email as the account you attach to run the flow, in our scenario the support desk. I have only hardcoded the content here, but you could easily read the date of the next bill from the users account record or something similar.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-23.png"
loading="lazy"
>&lt;/p>
&lt;p>The next step is close the case as we have provided the end user with the appropriate information. In D365, this is another action not readily available via the CRUD of the CDS or D365 connector.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-24.png"
loading="lazy"
>&lt;/p>
&lt;p>I now realise, after attending the EU D365 User Group Summit that this would be possible via Flow, along with routing the case, if you create your own custom connector and associate that with your D365 API instance, but that&amp;rsquo;s for another post.&lt;/p>
&lt;p>To get round the limitations, a new field is populated on the Case record, Close from Flow.&lt;/p>
&lt;p>A workflow is then triggered when this field changes to call the OOTB action if the value is true.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-25.png"
loading="lazy"
>&lt;/p>
&lt;h2 id="sentiment-analysis">Sentiment analysis&lt;/h2>
&lt;p>One of the big uses for social engagement and monitoring is to assess sentiment in the comments made by customers. LUIS provides this information in a textual (positive, neutral or negative) as well as numeric form if enable it on the application.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/04-image-26.png"
loading="lazy"
>&lt;/p>
&lt;p>Once you have this configured, recording this against the case and maybe setting a priority on it&amp;rsquo;s value would be quite straight forward.&lt;/p></description></item><item><title>Connecting LUIS &amp; D365 (part 1)</title><link>https://linked365.blog/2019/03/31/connecting-luis-d365-part-1/</link><pubDate>Sun, 31 Mar 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/03/31/connecting-luis-d365-part-1/</guid><description>&lt;img src="https://linked365.blog/images/2019/03-luisd365-e1554192911124.jpg" alt="Featured image of post Connecting LUIS &amp; D365 (part 1)" />&lt;p>As Microsoft wants us to consider using AI in all aspects of our developments, I wanted to see if I could use one of the cognitive services available to life in a real life scenaro.&lt;/p>
&lt;p>This post &amp;amp; it&amp;rsquo;s other parts will&lt;/p>
&lt;ul>
&lt;li>Give you an understanding of a real-life scenario where we could implement LUIS&lt;/li>
&lt;li>Introduce you to the concepts of LUIS&lt;/li>
&lt;li>Discuss the Microsoft Flow to connect LUIS to D365&lt;/li>
&lt;li>Give you some next steps on how you can try to bring LUIS into your organisation&lt;/li>
&lt;/ul>
&lt;h2 id="the-scenario---big-energy-co">The Scenario - Big Energy Co&lt;/h2>
&lt;p>Imagine a busy helpdesk or contact centre at one of the big electricity or gas companies. They are inundated with calls, emails &amp;amp; chats from their customer base to request numerous changes or additions to their account, provide meter readings, complain or numerous other concerns.&lt;/p>
&lt;p>Email is one of the biggest mediums for support when the matter is not urgent. The standard email to case conversion is commonaly used to bring these support requests into D365 CE.&lt;/p>
&lt;p>But that is traditionally where it stops. A 1st line support user would have to read the content of the case, decide on the appropriate subject for the new case &amp;amp; select save and route. This takes time, upto a couple of minutes, of invaluable time of an educated, talented member of your team.&lt;/p>
&lt;h2 id="luis---language-understanding">LUIS - Language Understanding&lt;/h2>
&lt;p>&lt;a class="link" href="http://www.luis.ai" target="_blank" rel="noopener"
>LUIS&lt;/a> is Microsoft&amp;rsquo;s cloud-based API which tries to understand the meaning behind phrases. LUIS could take a paragraph of text and categorise it to suggest what the writer of the paragraph is trying to say. Bringing machine learning into your app can drastically reduce the time spent scouring tet for meaning .&lt;/p>
&lt;p>In a 1st line support scenario, an email comes into a support mailbox and D365 will create a case with it&amp;rsquo;s auto-creation rules to allow a 1st line support person to read the email, decide what the email is concerning, then route the case to the relevant team.&lt;/p>
&lt;p>Using Flow and LUIS, we can automate this step, reducing the time taken to get the case to the right people, improving SLAs and reducing costs.&lt;/p>
&lt;h2 id="luis-configuration">LUIS Configuration&lt;/h2>
&lt;p>For all of this, I am using a trial environment, Microsoft makes it easy for you to play with all it&amp;rsquo;s tools, and LUIS is no exception. The free licenses gives you 5 text requests per seconds, definetly adequate for development and trial purposes. It is then £1.11 per 1000 transactions above this, with a max of 50 transactions a second.&lt;/p>
&lt;p>By going to &lt;a class="link" href="http://luis.ai" target="_blank" rel="noopener"
>luis.ai&lt;/a> &amp;amp; logging in, you will be allowed to create an app. This is the starting point. As you can see my app has been created already.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="intents">Intents&lt;/h3>
&lt;p>Intents are the term for meaning within the app. Each app will have several intents, what are the likely short description or categories of why an email would come into the environment?&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-2.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="utterances">Utterances&lt;/h3>
&lt;p>Each intent has several utterances, which are phrases from which LUIS will learn and define the intent of the text passed to it. It is very simple to add utterances and you should aim to get 15 or so for each intent as a starting point.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-3.png"
loading="lazy"
>&lt;/p>
&lt;p>You can add as many utterances as you like, try to keep your utterance count consist between intents as a higher utterance list on one of the intents will lead to it be chosen more, in effective giving you false results. When you get into a near production scenario, you need to keep adding them from feedback from your users. You could enact a process which, when LUIS fails to assocaite an intent to a case or gives a false classification, this is highlighted for a BA to analyse &amp;amp; apply to the model.&lt;/p>
&lt;p>The next thing to do is train LUIS. This brings any changes you have made into the AI so they also can be used to understand the conversation.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-4.png"
loading="lazy"
>&lt;/p>
&lt;p>Training is complete when you get a green bar across the top.&lt;/p>
&lt;p>Now we have a model, let&amp;rsquo;s test it, using the inbuilt Test functionality available from the top right.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-5.png"
loading="lazy"
>&lt;/p>
&lt;p>If you type a string in the box provided &amp;amp; hit return, you are calling LUIS and the text will be analysed and LUIS will reply with the highest intent &amp;amp; how likely the phrase enters matches it.&lt;/p>
&lt;p>I have entered the phrase &amp;ldquo;can you help me transfer my account&amp;rdquo;, which wasn&amp;rsquo;t part of the utterances I created earlier, but closely matches one of the Account closure utterances.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-6.png"
loading="lazy"
>&lt;/p>
&lt;p>Looking at the response, LUIS is stating that he thinks this phrase is about Account Closure and he is 58% sure that this is correct. If you click on the Inspect link you can use this to train LUIS if the response is not correct by using the Edit link, adding an utterance to one of the other intents or reenforcing the entered text was in the correct intent.&lt;/p>
&lt;h2 id="publishing-luis">Publishing LUIS&lt;/h2>
&lt;p>My LUIS app is ready, it is trained and raring to go. Now we need to allow access from the publicly available API. The Publish button steps you through the process, ensure you go to Production. Don&amp;rsquo;t worry about costs for now, you get 5 requests a second for free, which is great for trialling &amp;amp; developing&lt;/p>
&lt;p>In Application Information, there 2 key bits for connecting LUIS to Flow. Firstly, the Application ID is the key we want later. Secondly, we need to ensure anyone with the Application ID can access our endpoint &amp;amp; use the app we have configured, so ensure the Make this app public is checked.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-7.png"
loading="lazy"
>&lt;/p>
&lt;p>This is a little less secure than you would want in production and there are details about LUIS security available to ensure only the proper users can access fully documented &lt;a class="link" href="https://docs.microsoft.com/en-us/azure/cognitive-services/luis/luis-concept-security" target="_blank" rel="noopener"
>here&lt;/a>.&lt;/p>
&lt;p>That&amp;rsquo;s it, ready to go. In the next part, I will configure D365 and Flow to complete the scenario&lt;/p></description></item><item><title>Connecting LUIS to D365 (Part 2)</title><link>https://linked365.blog/2019/03/31/connecting-luis-to-d365-part-2/</link><pubDate>Sun, 31 Mar 2019 00:00:00 +0000</pubDate><guid>https://linked365.blog/2019/03/31/connecting-luis-to-d365-part-2/</guid><description>&lt;img src="https://linked365.blog/images/2019/04-luisd365-e1554192911124.jpg" alt="Featured image of post Connecting LUIS to D365 (Part 2)" />&lt;p>In the first &lt;a class="link" href="https://linked365.blog/2019/03/25/connecting-luis-d365/" target="_blank" rel="noopener"
>part&lt;/a> of this blog post I explained our scenario for Big Energy Co and it&amp;rsquo;s desire to improve efficiency in the support desk, introduced LUIS and the core concepts around utterances and intents, configured LUIS to allow it to understand the intents we need and published the application.&lt;/p>
&lt;p>Now I need to connect LUIS and D365 to allow automatic classification and routing of cases based on Natural Language inspection of the body of the case.&lt;/p>
&lt;p>This blog has at least 3 parts, but overall the posts objectives are&lt;/p>
&lt;ul>
&lt;li>Give you an understanding of a real-life scenario where we could implement LUIS (&lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365/" target="_blank" rel="noopener"
>Part 1&lt;/a>)&lt;/li>
&lt;li>Introduce you to the concepts of LUIS (&lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365/" target="_blank" rel="noopener"
>Part 1&lt;/a>)&lt;/li>
&lt;li>Discuss the Microsoft Flow to connect LUIS to D365&lt;/li>
&lt;li>Give you some next steps on how you can try to bring LUIS into your organisation&lt;/li>
&lt;/ul>
&lt;p>Nowadays, Microsoft &lt;a class="link" href="https://flow.microsoft.com/" target="_blank" rel="noopener"
>Flow&lt;/a> doesn&amp;rsquo;t need an introduction - it is the cornerstone for the whole of Microsoft Power suite (not sure why it doesn&amp;rsquo;t get the Power prefix) and allow &lt;em>spot&lt;/em> integrations between one or more disparate applications. It also allows you to &amp;ldquo;program&amp;rdquo; some data transformation or logic to control how data flows between applications or actions to take in specific circumstances. Flow is a complex beast, but simple to use in a lot of cases.&lt;/p>
&lt;h2 id="the-flow">The Flow&lt;/h2>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image.png"
loading="lazy"
>&lt;/p>
&lt;p>As you can see, the flow is pretty simple. We get a trigger from D365, strip the body of the case down to raw text, check to see if have anything left, ask LUIS to predict what it is, check how confident LUIS is, then update the case again. This is a simple flow which isn&amp;rsquo;t production ready by any means, but shows you the power of Flow and is enough for you to get started&lt;/p>
&lt;h3 id="triggering-from-d365">Triggering from D365&lt;/h3>
&lt;p>Our first step the trigger from D365&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-1.png"
loading="lazy"
>&lt;/p>
&lt;p>I am using the Common Data Service connectors here, which are the future, so why not? We have to connect to our D365 environment, chose the Cases entity and give it a scope. This is new for the CDS connector and allows a lot more flexibility around what data runs through a flow. You could keep the data to one business unit in an organisation, useful if you have country specific flows for example.&lt;/p>
&lt;h3 id="stripping-that-nasty-html">Stripping that nasty HTML&lt;/h3>
&lt;p>Email contains lots of formatting information that LUIS doesn&amp;rsquo;t understand. CSS, html tags, that heading etc will really upset LUIS, but handly there is an action to return just the actual words. Pass the body of the email, the case description to it.&lt;/p>
&lt;p>Also in this snippet, I am setting up a variable for use later on, to store the Subject ID.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-2.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="checking-for-empty-email">Checking for empty email&lt;/h3>
&lt;p>Another thing that LUIS doesnt handle is sending it an empty request. Just for a bit of house keeping, if, after stripping out all the html tags, the content is empty, rather than calling LUIS, exit gracefully. Always have in mind when running any flow that someone will be bombarded with error alerts if you don&amp;rsquo;t check&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-3.png"
loading="lazy"
>&lt;/p>
&lt;h3 id="passing-to-luis">Passing to LUIS&lt;/h3>
&lt;p>In the previous &lt;a class="link" href="https://linked365.blog/2019/03/31/connecting-luis-d365-part-1/#publishing-luis" >post&lt;/a>, when your LUIS app is published, you get a GUID representing the Application key. When you first connect to LUIS in Flow, this is what you need. If you have many applications in LUIS on that key, Flow wants to know which one, and also which version. This is handy if you are training LUIS and the new version isn&amp;rsquo;t quite ready, stick with a previous version of your app.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-4.png"
loading="lazy"
>&lt;/p>
&lt;p>The Utterance text is the email body, stripped of the html, which LUIS is to analyse.&lt;/p>
&lt;h3 id="is-luis-confident">Is LUIS confident?&lt;/h3>
&lt;p>Like any AI product, LUIS can only predict what it thinks is the likely intent of anything you pass to it. It provides you with a score, 0 being not confident, 1 being overly confident that matches each intent. We basically use this as a percentage. When this returns to flow, LUIS provides the top scoring intent as well as the top scoring intent score. If LUIS isn&amp;rsquo;t confident that what you have sent it, then Flow shouldn&amp;rsquo;t update the case. This case should stay with the 1st line queue for them to resolve.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-5.png"
loading="lazy"
>&lt;/p>
&lt;p>Again, this is about making your code production ready. It would be quite easy to trigger additional steps here to ensure this case is looked at and maybe a training point for LUIS after a human decides on the best route for the case.&lt;/p>
&lt;h3 id="retrieve-the-subject">Retrieve the subject&lt;/h3>
&lt;p>The subject tree in D365 matches the intents. This is a key point for our process to work. You could use other factors or matching, but this is pretty simple.&lt;/p>
&lt;p>Using the CDS link, we use the List Records feature to query the Subject entity. The filter query is the key here, using a piece of OData query notation to find the subject with a title that matches our top scoring intent.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-7.png"
loading="lazy"
>&lt;/p>
&lt;p>Though we will only retrieve one record, the List Records action will always return an array or records, an array of one. To keep your flow in one column, you can set a variable with the value of the subject Id you have retrieved and use this going forward. If not, you will have to do the remainder of these steps within the Apply to each action.&lt;/p>
&lt;h3 id="updating-the-case">Updating the Case&lt;/h3>
&lt;p>The last part of this simple flow is to update the case back in D365. Using the Id from the originally triggered case, we update parts of the case.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-8.png"
loading="lazy"
>&lt;/p>
&lt;p>The description is updated with the html stripped text. There are lots of ways to do this in D365, but seeing as we have done it already, it is neat to use it again. I have also added a new field on the case to log how confident LUIS is. This could be used as a summary later or for managing the training of LUIS.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-9.png"
loading="lazy"
>&lt;/p>
&lt;p>Finally, the subject Id is passed to the Subject field.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-10.png"
loading="lazy"
>&lt;/p>
&lt;p>So that is our flow complete. Now for some testing.&lt;/p>
&lt;h2 id="testing-our-flow">Testing our Flow&lt;/h2>
&lt;p>Flow has some really neat tools to ease testing. In the right corner, is the Test button which gives us this panel. The first time you run a flow, you will have to perform the trigger action, sending in an email to convert to a case or creating a case in our scenario, but after that, we can use previous data. Great for tweaking &amp;amp; checking&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-11.png"
loading="lazy"
>&lt;/p>
&lt;p>If you run a test, you will hopefully get a screen with lots of green ticks next to the parts that ran successfully as well as some crosses against those that didn&amp;rsquo;t.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-12.png"
loading="lazy"
>&lt;/p>
&lt;p>If you drill down to each step, you can see the input and the output from that action.&lt;/p>
&lt;p>In this example, you can see the original html formatted input from an email as well as the output of just the text.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-13.png"
loading="lazy"
>&lt;/p>
&lt;p>The call to LUIS shows the JSON return from LUIS. The LUIS connector gives a lot of properties transformed out of this content.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-14.png"
loading="lazy"
>&lt;/p>
&lt;p>The CDS record update shows only the fields that we update, a standard D365 API call. You can see the Subject ID being set, as well as the html stripped description and the Intent score.&lt;/p>
&lt;p>&lt;img src="https://linked365.blog/images/2019/03-image-15.png"
loading="lazy"
>&lt;/p>
&lt;p>So, flow done. In the next installment, I will show the D365 implementation, how we bring it all together. I also take LUIS and flow a little bit further, to add more complexity and functionality to the both to improve the scenario.&lt;/p></description></item></channel></rss>