Search resource availability and create bookings for requirement groups
Use the Search Resource Availability for Requirement Group API and the Create Requirement Group Bookings API to book the resources that meet the needs you identify in your requirement groups.
- The Search Resource Availability for Requirement Group API returns available time slots for resources when you search by using requirement groups.
- The Create Requirement Group Bookings API uses the available time slots for resources to generate booking records for your requirement groups.
You pass the details of a requirement group in your API calls and retrieve a list of available resources and their open time slots. This list is helpful for self-scheduling scenarios where a user wants to view the availability of resources, or for portal scheduling scenarios where a customer wants to view resource availability from a website or app.
Prerequisites
- Dynamics 365 version 9.0 or above with Universal Resource Scheduling version 3.12.x.x
Search Resource Availability for Requirement Group API
Use the following input and output parameters for the Search Resource Availability for Requirement Group (msdyn_SearchResourceAvailabilityForRequirementGroup) API.
Parameters
Name | Type | Required | Description |
---|---|---|---|
Version | String | Yes | The version number of the API. The version number identifies the version of the API that should be invoked. The version number is a semantic version number of the format major.minor.patch. The request doesn't have to contain the complete version number. |
RequirementGroup | Yes | An entity reference to the requirement group entity. | |
RequirementSpecification | Integer | No | If left null, respects the targeting requirement group duration by default. |
Settings | Entity<InputSettings> |
No | Sets the settings for the request. |
Inputsettings
Name | Type | Required | Description |
---|---|---|---|
ConsiderSlotsWithLessThanRequiredDuration | Boolean | No | Specifies if a time slot with less than the required remaining duration should be considered when computing potential time slots. It's false by default. |
ConsiderSlotsWithOverlappingBooking | Boolean | No | Specifies if time slots with overlapping bookings should be considered when computing potential time slots. It's false by default. |
ConsiderSlotsWithProposedBooking | Boolean | No | Specifies if time slots with proposed bookings should be considered when computing potential time slots. It's false by default. |
MaxResourceTravelRadius | Distance | No | Specifies the maximum travel radius for resources when computing available time slots. |
SortOrder | Integer | No | Specifies the requirement group order for the response. |
PageSize | Integer | No | Numbers of item returned in a page. It's 20 by default. |
PagingCookie | String | No | Paging cookie retrieved from previous searching result. |
OrganizationUnits | List<Guid> | No | A collection of organization unit IDs. A qualified resource must be a member of one of the specified organization units. |
MustChooseFromResources | List<Guid> | No | Evaluate and select results from resources in this list. |
RequiredResources | List<Guid> | No | Evaluate all resources, filter the results based on this list. In general, use MustChooseFromResources instead for improved performance. |
IgnoreTimeSlots | Boolean | No | Specifies if the returned time slots should be ignored. When true, list of time slots returned is empty. It's false by default. |
ConsiderAppointments | Boolean | Set to True for search resource availability API to respect existing Dataverse appointments as bookings on the resource, provided the organization and resource level settings are set. Appointments with busy or completed statuses are considered as unavailable for scheduling operations. |
Output
Returns | Name(Type) | Description |
---|---|---|
TimeSlots (List<OutputTimeSlot>) | StartTime (DateTime) | The start time. |
EndTime (DateTime) | The end time. | |
ArrivalTime (DateTime) | The arrival time. | |
Travel(OutputTimeSlotTravel) OutputTimeSlotTravel
|
The time slot travel information. Is only present if the resource requirement contains values for latitude and longitude. | |
Effort (Double) | The effort/capacity. | |
IsDuplicate (Boolean) | A Boolean value indicating if the time slot is a duplicate. | |
Resource(OutputResource) OutputResource
|
The Resource entity as explained in this article. | |
Location(OutputTimeSlotLocation) OutputTimeSlotLocation:
|
The entity contains details about the location of a time slot. For more information, see TimeSlotLocation in this article. | |
TimeGroup(TimeSlotTimeGroup) OutputTimeSlotTimeGroup:
|
The entity contains details about a time group. For more information, see TimeSlotTimeGroup in this article. | |
AvailableIntervals (List<<Guide>OutputTimeSlot> ) |
A collection of available intervals. | |
Resources (List<OutputResource>) | Resource (EntityReference) | An entity reference to the bookable resource. |
BusinessUnit (EntityReference) | An entity reference to the bookable resource group. | |
OrganizationalUnit (EntityReference) | An entity reference to the organizational unit. | |
ResourceType (Int) | The resource type. See the resourcetype attribute on the BookableResource entity for possible values. | |
PoolId (Guid) | The ID of the pool that the resource is a member of during the time slot. | |
CrewId (Guid) | The ID of the crew that the resource is a member of during the time slot. | |
Email (String) | The resource’s email address. | |
Phone (String) | The resource’s phone number. | |
ImagePath (String) | The path to the resource’s image. | |
Requirements (List<OutputRequirements>) | Requirement (EntityReference) | An entity reference to the Resource Requirement record. |
ConstraintBag (String) | Requirement constraint in ufx bag(internal) | |
Resources (List<<EntityReference>EntityReference> ) |
Entity reference list of resource that is available to the requirements. | |
ProposalResourceAssignmentSets (List<OutputProposalResourceAssignmentSet>) | IntervalStart (DateTime) | Start time for each proposal resource assignment set. |
ProposalResourceAssignments (List<OutputProposalResourceAssignments> OutputProposalResourceAssignments:
|
List of Resources assigned to Requirement. | |
PagingInfos (OutputPagingInfo) | MoreResults (Boolean) | If there are more results or not. |
PagingCookie (String) | Paging cookie that can be used in the future search. |
Example
{
"RequestName": "msdyn_SearchResourceAvailabilityForRequirementGroup",
"Parameters": [
{
"Key": "Version",
"Value": "1"
},
{
"Key": "RequirementGroup",
"Value": {
"Id": "6927721a-0137-42be-8092-26995625a9d9",
"LogicalName": "msdyn_requirementgroup",
"Name": null,
"KeyAttributes": [],
"RowVersion": null
}
}
],
"RequestId": null
}
Response
{
"ResponseName": "msdyn_SearchResourceAvailabilityForRequirementGroup",
"Results": [
{
"Key": "TimeSlots",
"Value": {....}
},
{
"Key": "Requirements",
"Value": {....}
},
{
"Key": "ProposalResourceAssignmentSets",
"Value": {....}
},
{
"Key": "PagingInfos",
"Value": {....}
}]
}
Create Requirement Group Bookings API
Use the following input and output parameters for the Create Requirement Group Bookings (msdyn_CreateRequirementGroupBookings) API.
Parameters
Name | Type | Required | Description |
---|---|---|---|
Version | String | Yes | The version number of the API. The version number identifies the version of the API that should be invoked. The version number is a semantic version number of the format major.minor.patch. The request doesn't have to contain the complete version number. |
RequirementGroup | EntityReference | Yes | An entity reference to the requirement group entity, usually is a GUID, as shown in the following sample. |
Start | DateTime | Yes | Start time of the Timeslot. |
Duration | Integer | Yes | The Duration of the Booking to be created. |
ResourceAssignments | EntityCollection | Yes | It's an entity collection of the Resource Assignments that are to be made for the Bookings to be created. Look at the Resource Assignment entity table for more details |
Resource Assignments
Name | Type | Required | Description |
---|---|---|---|
RequirementId | Guid | Yes | The resource requirement ID of the Requirement for which the booking record is to be created. |
ResourceId | Guid | Yes | The bookable resource ID of the Resource for which you want to create the booking. |
BookingStatusId | Guid | Yes | The booking status ID of the booking to be created. |
Effort | Integer | No | The capacity of the Bookable Resource that this booking consumes. |
TravelTime | Integer | No | The travel time in minutes. |
Output
Returns HandlerExecuted
that is of Boolean type.
Using the Requirement Group API
In the following scenario, you schedule a requirement group via API. You need a service created with resources before you can schedule a booking. Follow these steps to create a service activity.
Service configuration
- In the site map, under Scheduling, select Service.
- Go to Resource Requirements.
- Create a service activity. For this example, we created Test Requirement Group.
Service Activity configuration
- In the site map, under Scheduling, select Service Activities.
- Go to Service Activities.
- For Subject, select Test Requirement Group.
- For Service, select Test Requirement Group.
Note
This configuation automatically creates a resource requirement group that has the same name as the service activity.
Now you have a requirement group automatically created that has one technician (resource) to be scheduled to perform service at your customer's location.
Resource Requirement Group grid
The following image is an example configuration of the Resource Requirement Group page.
Note
To access the Requirement Group page from the Customer Service Hub app, you need to navigate there via a URL.
Important
Use the following URL to reach the Resource Requirements Group page: <<YourOrgURL>YourOrgURL>?appid=guid&pagetype=entitylist&etn=msdyn_requirementgroupr
.
- Go to General.
- Name field Test Requirement Group.
- Enter name in Owner field.
- Template field.
- Template Required, select No.
Search against your organization
In this next scenario, we show how to pass values for a specific requirement group (Entity Reference - GUID), Required Resources to complete work and match the resource to the organizational unit.
Important
- To run the Requirement Group API, you need GUIDs for:
- Requirement group
- Bookable resources
- Organizational unit (which can be retrieved by using the Web API)
- If the API is called from a client (browser or canvas app) based on JavaScript, you need to have the extended SOAP SDK. The extended SOAP SDK is not an official Microsoft release, but you can is provided in the downloadable sample files for guidance.
- We recommend that you test this search in your development or test environments to validate your scenarios and results before running it in your production environment.
- This API uses the complex object type in the input and output, so it only supports the SOAP endpoint. It doesn't support the OData endpoint.
To execute this search against your organization, you need to download the sample files, and then complete the following steps.
- Modify the hard-coded input parameters in the msdyn_SearchResourceAvailabilityForRequirementGroupSample.js file to reflect the GUIDs of records in your org. (Example: requirement group, resources, organizational unit).
Sample Search Requirement Group
- Add the files in the sample folder as web resources in your organization
- Navigate to the newly added new_msdyn_SearchResourceAvailabilityForRequirementGroupSample.htm page. Example:
<<YourOrgURL>>//WebResources/new_msdyn_SearchResourceAvailabilityForRequirementGroupSample.htm
- Open the browser's developer tools by using the F12 function key. Set breakpoints as needed, and inspect the request/responses in the developer tool's console.
We can see that there are multiple sets of time slots that are returned with each set, corresponding to a matching available resource that's mapped to the underlying requirement of the requirement group.
After the time slot Sets are returned by the API, you can display them on your custom web portal, app, or a Power App (model/canvas).
- After you choose a specific time slot set (Set number 1 in this example), update your new_msdyn_CreateRequirementGroupBookingsSample.js web resource in your org to pass the resource assignments (Requirement guid, Resource guid) and the Requirement Group, as shown in the following example.
Important
Find the complete sample code here: Create Requirement Group.
- Navigate to the newly added new_ msdyn_CreateRequirementGroupBookingsSample.htm page. (Example:
<<YourOrgURL>>//WebResources/new_msdyn_CreateRequirementGroupBookingsSample.htm
) to invoke a call to the Booking API and create the booking.
- Open the browser's developer tools by using the F12 function key. Here, you see that the handler executed value is set to true, indicating that the bookings were created successfully.
We can also verify this value by going back into the organization and checking the associated bookings of the Service/Requirement group we created, as shown in the following images.
Other possible scenarios that might use these APIs are:
- Build a custom web app or a Dynamics 365 portal to provide appointment scheduling for users. The app shows available time slots for the service or product being offered by using multiresource requirements (requirement groups).
- Build a Power Apps canvas app to support self-scheduling scenarios for line-of-business apps.
See the Additional resources section for links to more help resources.
Sample code
The following sample code shows how to implement msdyn_SearchResourceAvailabilityForRequirementGroup
message.
{
// Authentication
String machineName = "contoso?????";
String orgName = "?????";
String domain = $"{machineName}dom.extest.microsoft.com";
String uri = $"http://{machineName}.{domain}/{orgName}/XRMServices/2011/Organization.svc";
String username = "?????";
String password = "?????";
OrganizationServiceManager osm = new
OrganizationServiceManager(new Uri(@uri), username, password, domain);
_serviceProxy = osm.GetProxy();
_service = (IOrganizationService)_serviceProxy;
searchResourceAvailabilityForRequirementGroup();
createRequirementGroupBookings();
}
static void searchResourceAvailabilityForRequirementGroup()
{
var req = new OrganizationRequest()
{
RequestName = "msdyn_SearchResourceAvailabilityForRequirementGroup"
};
//Version
req["Version"] = "1";
req["RequirementGroup"] = new EntityReference("msdyn_requirementgroup", Guid.Parse("e5e4f033-150d-eb11-a822-000d3aaf102a"));
Entity requirementSpecification = new Entity();
requirementSpecification.Attributes.Add("msdyn_fromdate", DateTime.Today.AddDays(1));
requirementSpecification.Attributes.Add("msdyn_todate", DateTime.Today.AddDays(3));
req["RequirementSpecification"] = requirementSpecification;
try
{
var response = _service.Execute(req);
Console.WriteLine("Response from search: {0}", JsonConvert.SerializeObject(response));
}
catch (Exception e)
{
Console.WriteLine("msdyn_SearchResourceAvailabilityForRequirementGroup failed with the following error: {0}", e.Message);
}
}
static void createRequirementGroupBookings()
{
var req = new OrganizationRequest()
{
RequestName = "msdyn_createRequirementGroupBookings"
};
req["Version"] = "1";
req["RequirementGroup"] = new EntityReference("msdyn_requirementgroup",
Guid.Parse("d74260ee-180d-eb11-a822-000d3aaf102a"));
req["Start"] = DateTime.Today.AddDays(1);
req["Duration"] = 60;
EntityCollection resourceAssignment = new EntityCollection();
var entity = new Entity();
entity["RequirementId"] = Guid.Parse("df4260ee-180d-eb11-a822-000d3aaf102a");
entity["ResourceId"] = Guid.Parse("268e3d0d-5e0c-eb11-a822-000d3aaf102a");
entity["BookingStatusId"] = Guid.Parse("10de5842-cf5e-4092-9006-d0aa9f9c1f74");
resourceAssignment.Entities.Add(entity);
req["ResourceAssignments"] = resourceAssignment;
try
{
var response = _service.Execute(req);
Console.WriteLine("Response JSON : " + JsonConvert.SerializeObject(response));
}
catch (Exception e)
{
Console.WriteLine("msdyn_createRequirementGroupBookings request failed with the following exception: {0}", e.Message);
}
Console.ReadKey();
}
How to migrate from the legacy API to Universal Resource Scheduling
To migrate from the legacy Search API and Book API to the Universal Resource Scheduling API, use the following required input and output fields to map the APIs.
Input mapping data for the Search API
Legacy input | Universal Resource Scheduling input | Description |
---|---|---|
ServiceId | Requirement group | Service/requirement group GUID |
SearchWindowStart | Start date | Start date for the appointment search |
SearchWindowEnd | End date | End date for the appointment search |
Duration | Duration | Appointment duration |
No of results | Page size | Total number of proposals or number of appointments on a page |
Sites | OrganizationUnits | Site/OU GUID |
RequiredResource | Preferred Resources | Resources the customer prefers to schedule |
Constraints | Constraints | Customer entity(ufx) |
RecurrenceDuration | In a recurrence appointment search, the duration of the appointment | |
RecurrenceTimeZoneCode | Time zone for a recurring request | |
SearchDirection | Forward or backward search for slots, based on the dates given | |
AnchorOffSet | Offset in hours from midnight | |
UserTimeZoneCode | Time zone set for the user | |
SearchRecurrenceRule | Frequency, interval, count, and so on | |
Resource Types | Type of resource | |
Restricted Resources | Restricted for scheduling the appointment |
Output mapping for the Search API
Legacy output | Universal Resource Scheduling output |
---|---|
Appointment proposals | ProposalsResourceAssignmentSet |
TraceInfo | |
ExtensionDataObject | |
Time Slots | |
Requirements(constraintbag) | |
PagingInfos |
Example scenarios for migrating from the legacy scheduling API to Universal Resource Scheduling
The scenario-based examples in this section add more details about mapping from the legacy API to the new Universal Resource Scheduling API.
Scenario 1: Get two resources for each schedule proposal
The following screenshot from the legacy API is provided for reference in this scenario.
Create one site (Site1), one user (User1), and one equipment resource (Facility/Equipment tab), with the name Eq1, with the site set to Site1.
Create the business closure and work hours for the user (8:00 AM to 6:00 PM) and the equipment (8:00 AM to 6:00 PM).
Create a new service (Service1), and then add required resources as Choose 2 from User1, Eq1. Save and close the service.
Go to the homepage and schedule a service activity and then, select Service1, and then select Schedule > Find available slots.
Verify that each proposal returns the two resources in accordance with the criteria you set.
Universal Resource Scheduling API code for scenario 1
void searchRequirementgroup(Microsoft.Pfe.Xrm.OrganizationServiceManager osm)
{
var req = new Microsoft.Xrm.Sdk.OrganizationRequest()
{
RequestName = "msdyn_SearchResourceAvailabilityForRequirementGroup"
};
req["Version"] = "1";
Entity requirementSpecification = new Entity();
//Setting from date
requirementSpecification.Attributes.Add("msdyn_fromdate", DateTime.Parse("2019-12-
26T18:30:00.000Z"));
//Setting to date
requirementSpecification.Attributes.Add("msdyn_todate", DateTime.Parse("2019-12-
27T18:29:00.000Z"));
//Requirement group GUID
req["RequirementSpecification"] = requirementSpecification;
req["RequirementGroup"] = new
Microsoft.Xrm.Sdk.EntityReference("msdyn_requirementgroup", Guid.Parse("XXXXXXXX"));
//Executing the request and getting response
var response = osm.GetProxy().Execute(req);
response.ToString();
response.Dump();
}
Scenario 2: Verify that search results are correct for scheduling
The following screenshot from the legacy API is provided for reference in this scenario.
- Create the following sites and users:
- Two sites: Micr0s0ftSite1 and Site2
- Two users: User1 and User2 (Site2)
- Go to Settings> Service management tab and create a site(with the name
Site1
), two resources on the Facility/Equipment tab (namely, Eq1 and Eq2) and go to setting> Security and create a user(User1). Two equipment resources on the Facility/Equipment tab (Eq1, Eq2), where Eq1 belongs to Site1 and Eq2 belongs to Site2
Create the business closure and work hours for the user (8:00 AM to 6:00 PM) and the equipment (8:00 AM to 6:00 PM).
Create a new service with status Reserved and required resources as Choose 2 from same site from User1, User2, Eq1, Eq2. Save and close the service.
Go to the homepage > Service Activity > Schedule, and then select the service you created in step 3. Select the site as Site1, and then click on Find available time.
Verify that the search results that are returned are correct for the site selected in the search criteria.
Universal Resource Scheduling API code for scenario 2
void searchRequirementgroup(Microsoft.Pfe.Xrm.OrganizationServiceManager osm)
{
var req = new Microsoft.Xrm.Sdk.OrganizationRequest()
{
RequestName = "msdyn_SearchResourceAvailabilityForRequirementGroup"
};
req["Version"] = "1";
Entity requirementSpecification = new Entity();
//Setting from date
requirementSpecification.Attributes.Add("msdyn_fromdate", DateTime.Parse("2019-12-26T18:30:00.000Z"));
//Setting to date
requirementSpecification.Attributes.Add("msdyn_todate", DateTime.Parse("2019-12-27T18:29:00.000Z"));
req["RequirementSpecification"] = requirementSpecification;
//Requirement group GUID
req["RequirementGroup"] = new EntityReference("msdyn_requirementgroup", Guid.Parse("XXXXXX"));
var response = osm.GetProxy().Execute(req);
response.ToString();
response.Dump();
}
Scenario 3: Get proposed schedules that occur within the working hours for an equipment resource
Create two sites (Site1, Site2), and then create three equipment resources (Eq1, Eq2, Eq3).
Create the business closure and work hours for all equipment (3:00 PM to 6:00 PM).
Create a new service (Service1) Choose 1 from (Random) Eq1, Eq2, #q3.
In the Schedule Service Activity dialog box, search for proposals for Service1 by adding a required resource as Eq1 for a specific date range.
Verify that the proposed schedules that are returned occur within the working hours of the equipment for that date.
Universal Resource Scheduling API code for scenario 3
void searchRequirementgroup(Microsoft.Pfe.Xrm.OrganizationServiceManager osm)
{
var req = new Microsoft.Xrm.Sdk.OrganizationRequest()
{
RequestName = "msdyn_SearchResourceAvailabilityForRequirementGroup"
};
req["Version"] = "1";
Entity requirementSpecification = new Entity();
//Setting start date
requirementSpecification.Attributes.Add("msdyn_fromdate", DateTime.Parse("2019-12-26T18:30:00.000Z"));
//Setting end date
requirementSpecification.Attributes.Add("msdyn_todate", DateTime.Parse("2019-12-27T18:29:00.000Z"));
//Setting the eq1 as required resource
requirementSpecification.Attributes.Add("msdyn_resourcerequirementid",Guid.Parse("XXXXXX"));
req["RequirementSpecification"] = requirementSpecification;
//Setting the requirement group GUID
req["RequirementGroup"] = new EntityReference("msdyn_requirementgroup", Guid.Parse("XXXXX"));
//Executing the request and getting response.
var response = osm.GetProxy().Execute(req);
response.ToString();
response.Dump();
}
More resources
Resource | Description |
---|---|
Service Scheduling Guide | Read how you can plan and schedule service activities for your customers. |
Service scheduling FAQ | Frequently asked questions on service scheduling |
Multiresource scheduling with requirement groups | Use requirement groups to mix and match different types of resources. |
Search Resource Availability API for single resource requirements | Blog on how to use the Search resource availability API |
Documentation for resource scheduling | Get started with using Universal Resource Scheduling. |
Learning path for resource scheduling | Learn how to use Universal Resource Scheduling in Microsoft Dynamics 365 for Field Service |
Dynamics 365 application ideas | Use this portal to contribute product feedback and ideas for resource scheduling. |
Community forum | Use the community forum to ask questions, find answers, and see upcoming events. |
Dynamics 365 blog | Read the Dynamics 365 blog for release notes and posts from the product team. |