Saturday 10 February 2018

add more options to filter&maps in Schedule Board Dynamics CRM 365 PSA

Story: Adding custom filter options to Filter&maps in schedule board in Dynamic 365 PSA

1. Navigate to Schedule Board



2. Double click on the "Initial Public View"
3. It will open the popup
4. Navigate to : Filter Layout
5. click on edit the Filter Layout
6. Sample code is available below

<?xml version="1.0" encoding="utf-8" ?>
<filter>
  <controls>
    <control type="characteristic" key="Characteristics" label-id="ScheduleAssistant.West.Skills" />
    <control type="combo" source="entity" key="Roles" inactive-state="1" label-id="ScheduleAssistant.West.Roles" entity="bookableresourcecategory" multi="true" />
    <control type="combo" source="entity" key="Territories" unspecified-key="UnspecifiedTerritory" label-id="ScheduleAssistant.West.Territories" entity="territory" multi="true" />
    <!--<control type="combo" source="entity" key="Countries"  label-id="Country" entity="new_country" multi="true" />-->
    <control type="combo" source="entity" key="SubRegions" inactive-state="1"  label-id="SubRegion" entity="new_subregion" multi="true" />
    <control type="combo" source="entity" key="Regions"  label-id="Region" entity="new_region" multi="true" />
    <control type="combo" source="entity" key="Marketid"  label-id="MarketID" entity="new_marketid" multi="true" />
    <control type="combo" source="entity" key="OrganizationalUnits" label-id="SB_FilterPanel_OrganizationalUnitsFilter_Title" inactive-state="1" entity="msdyn_organizationalunit" multi="true" />
    <control type="combo" source="optionset" key="ResourceTypes" label-id="SB_FilterPanel_ResourceTypesFilter_Title" entity="bookableresource" attribute="resourcetype" multi="true">
      <data>
        <value id="2" />
        <value id="3" />
        <value id="4" />
        <value id="5" />
      </data>
    </control>
    <control type="combo" source="entity" key="Teams" label-id="SB_FilterPanel_TeamsFilter_Title" entity="team" multi="true" />
    <control type="combo" source="entity" key="BusinessUnits" label-id="SB_FilterPanel_BusinessUnitsFilter_Title" entity="businessunit" multi="true" />
    <control type="order" key="Orders" label-id="FilterControl_OrderLabel">
      <order name="name" entity="bookableresource" attribute="name" />
      <order name="proficiencyscore" entity="bookableresourcecharacteristic" attribute="ratingvalue" />
    </control>
  </controls>
</filter>

7. Click on the edit retrieve resource query
<?xml version="1.0" encoding="utf-8" ?>
<bag xmlns:ufx="http://schemas.microsoft.com/dynamics/2017/universalfetchxml">
  <Resources ufx:source="fetch">
    <fetch mapping="logical" aggregate="true">
      <entity name="bookableresource">
        <attribute name="bookableresourceid" alias="bookableresourceid" groupby="true"/>
        <attribute name="name" alias="name" groupby="true"/>
        <attribute name="calendarid" alias="calendarid" groupby="true"/>
        <attribute name="resourcetype" alias="resourcetype" groupby="true"/>
        <attribute name="msdyn_startlocation" alias="startlocation" groupby="true"/>
        <!-- Let the database sort by name, unless we have characteristics - in which case we'll sort by the count of characteristics -->
        <order ufx:if="not($input/Characteristics/bag/characteristic)" alias="name" />

        <!-- Characteristic join -->
        <link-entity name="bookableresourcecharacteristic" from="resource" to="bookableresourceid" link-type="inner" ufx:if="$input/Characteristics/bag/characteristic">
          <attribute name="characteristic" aggregate="countcolumn" alias="characteristiccount" distinct="true" />
          <order alias="characteristiccount" descending="true" />

          <link-entity name="ratingvalue" from="ratingvalueid" to="ratingvalue" link-type="outer">
            <attribute name="value" aggregate="sum" alias="proficiencyscore" distinct="true" />
            <order alias="proficiencyscore" descending="true" />
          </link-entity>

          <filter>
            <condition attribute="statecode" operator="eq" value="0" />
          </filter>
        </link-entity>

        <!-- Characteristic filter -->
        <filter type="or" ufx:if="$input/Characteristics/bag/characteristic">
          <ufx:apply select="$input/Characteristics/bag">
            <filter type="and">
              <condition entityname="bookableresourcecharacteristic" attribute="characteristic" operator="eq">
                <ufx:value select="characteristic" attribute="value" />
              </condition>
              <condition entityname="ratingvalue" attribute="value" operator="ge" ufx:if="ratingvalue">
                <ufx:value select="ratingvalue" attribute="value" />
              </condition>
            </filter>
          </ufx:apply>
        </filter>

        <!-- Category join -->
        <link-entity name="bookableresourcecategoryassn" from="resource" to="bookableresourceid" link-type="inner" ufx:if="$input/Roles/bag">
          <attribute name="resourcecategory" aggregate="countcolumn" alias="rolecount" distinct="true" />

          <filter>
            <condition attribute="statecode" operator="eq" value="0" />
            <condition operator="in" attribute="resourcecategory">
              <ufx:apply select="$input/Roles/bag">
                <value>
                  <ufx:value select="@ufx-id" />
                </value>
              </ufx:apply>
            </condition>
          </filter>
        </link-entity>

        <!-- Territory join -->
        <link-entity ufx:if="$input/Territories/bag | $input/UnspecifiedTerritory[. = 'true']" name="msdyn_resourceterritory" from="msdyn_resource" to="bookableresourceid" alias="territory" link-type="outer">
          <filter>
            <condition attribute="statecode" operator="eq" value="0" />
            <condition attribute="msdyn_territory" operator="not-null" />
          </filter>
        </link-entity>

        <!-- Territory filter -->
        <filter type="or">
          <condition ufx:if="$input/UnspecifiedTerritory[. = 'true']" entityname="territory" attribute="msdyn_territory" operator="null" />

          <condition ufx:if="$input/Territories/bag" entityname="territory" attribute="msdyn_territory" operator="in">
            <ufx:apply select="$input/Territories/bag">
              <value>
                <ufx:value select="@ufx-id" />
              </value>
            </ufx:apply>
          </condition>
        </filter>

        <filter type="and">
          <condition attribute="statecode" operator="eq" value="0" />

          <!-- Preferred resource filter -->
          <condition ufx:if="$input/PreferredResources/bag" attribute="bookableresourceid" operator="in">
            <ufx:apply select="$input/PreferredResources/bag">
              <value>
                <ufx:value select="@ufx-id" />
              </value>
            </ufx:apply>
          </condition>

          <!-- Restricted resource filter -->
          <condition ufx:if="$input/RestrictedResources/bag" attribute="bookableresourceid" operator="not-in">
            <ufx:apply select="$input/RestrictedResources/bag">
              <value>
                <ufx:value select="@ufx-id" />
              </value>
            </ufx:apply>
          </condition>

          <!-- DisplayOnScheduleBoard and DisplayOnScheduleAssistant filter -->
          <condition attribute="msdyn_displayonscheduleboard" operator="eq" value="1" ufx:if="$input/DisplayOnScheduleBoard[. = 'true']" />
          <condition attribute="msdyn_displayonscheduleassistant" operator="eq" value="1" ufx:if="$input/DisplayOnScheduleAssistant[. = 'true']" />

          <!-- Organizational unit filter -->
          <condition operator="in" attribute="msdyn_organizationalunit" ufx:if="$input/OrganizationalUnits/bag">
            <ufx:apply select="$input/OrganizationalUnits/bag">
              <value>
                <ufx:value select="@ufx-id" />
              </value>
            </ufx:apply>
          </condition>

          <!-- country filter -->
          <!--<condition operator="in" attribute="new_country" ufx:if="$input/Countries/bag">
            <ufx:apply select="$input/Countries/bag">
              <value>
                <ufx:value select="@ufx-id" />
              </value>
            </ufx:apply>
          </condition>-->

          <!-- Sub Region filter -->
          <condition operator="in" attribute="new_subregion" ufx:if="$input/SubRegions/bag">
            <ufx:apply select="$input/SubRegions/bag">
              <value>
                <ufx:value select="@ufx-id" />
              </value>
            </ufx:apply>
          </condition>

          <!-- Region filter -->
          <condition operator="in" attribute="new_region" ufx:if="$input/Regions/bag">
            <ufx:apply select="$input/Regions/bag">
              <value>
                <ufx:value select="@ufx-id" />
              </value>
            </ufx:apply>
          </condition>

          <!-- MarketID filter -->
          <condition operator="in" attribute="new_marketid" ufx:if="$input/Marketid/bag">
            <ufx:apply select="$input/Marketid/bag">
              <value>
                <ufx:value select="@ufx-id" />
              </value>
            </ufx:apply>
          </condition>

          <!-- Resource type filter -->
          <condition attribute="resourcetype" operator="in" ufx:if="$input/ResourceTypes/bag/option">
            <ufx:apply select="$input/ResourceTypes/bag/option">
              <value>
                <ufx:value select="." />
              </value>
            </ufx:apply>
          </condition>
        </filter>

        <link-entity name="systemuser" from="systemuserid" to="userid" link-type="outer">
          <!-- If Business Units or Teams are supplied, assume only users are to be returned -->
          <ufx:value ufx:if="$input/BusinessUnits/bag | $input/Teams/bag" select="'inner'" attribute="link-type" />

          <attribute name="systemuserid" alias="systemuserid" groupby="true" />
          <attribute name="entityimage_url" alias="userimagepath" groupby="true"/>

          <!-- User and Teams filter -->
          <link-entity name="teammembership" from="systemuserid" to="systemuserid" link-type="inner" ufx:if="$input/Teams/bag">
            <filter type="and" >
              <condition operator="in" attribute="teamid">
                <ufx:apply select="$input/Teams/bag">
                  <value>
                    <ufx:value select="@ufx-id" />
                  </value>
                </ufx:apply>
              </condition>
            </filter>
          </link-entity>

          <!-- User Businessunits filter -->
          <filter type="and" ufx:if="$input/BusinessUnits/bag">
            <condition operator="in" attribute="businessunitid">
              <ufx:apply select="$input/BusinessUnits/bag">
                <value>
                  <ufx:value select="@ufx-id" />
                </value>
              </ufx:apply>
            </condition>
          </filter>
        </link-entity>

        <link-entity name="contact" from="contactid" to="contactid" link-type="outer">
          <attribute name="contactid" alias="contactid" groupby="true"/>
          <attribute name="entityimage_url" alias="contactimagepath" groupby="true"/>
        </link-entity>

        <link-entity name="account" from="accountid" to="accountid" link-type="outer">
          <attribute name="accountid" alias="accountid" groupby="true"/>
          <attribute name="entityimage_url" alias="accountimagepath" groupby="true"/>
        </link-entity>
      </entity>
    </fetch>

    <bag>
      <imagepath ufx:select="accountimagepath | contactimagepath | userimagepath" />

      <accountimagepath ufx:select="$null" />
      <contactimagepath ufx:select="$null" />
      <userimagepath ufx:select="$null" />
    </bag>
  </Resources>

  <Resources ufx:if="$input/Characteristics/bag/characteristic" ufx:select="list(Resources/bag[characteristiccount = count($input/Characteristics/bag/characteristic)])" />
  <Resources ufx:select="order(Resources, iif($input/Orders/bag, $input/Orders, 'name'))" />
</bag>
9. it should available like below