Resource Preferences Handling in Direct Assignment

With the 25D update, Resource Preferences (i.e., recommended, forbidden, and required resources) are supported for API calls FindMatchingResources and ShowBookingGrid in direct assignment mode.

This enhancement enables organizations to control how activities are assigned to field resources by defining assignment rules in the request. These preferences influence booking behavior by enforcing which resources should be prioritized, avoided, or strictly required. For example, a company may assign activities to specific resources who already have security clearance or access to restricted areas ('required'), prioritize assigning technicians already familiar to the customer or who have previously serviced the location ('preferred'), or exclude resources who may have a potential conflict of interest with the customer or activity, such as being previously involved in a related audit, legal case, or business negotiation ('forbidden').

showBookingGrid API Operation Changes

A new resourcePreferences array has been added to showBookingGrid API operation with the following structure. The array itself is optional, but if included, it must contain the following mandatory fields:

Table: resourcePreferences Array

Array Field  Type Required Description Allowed Values
resourcePreferences - array Optional Resource preference rules container. -
  resourceID string Mandatory The unique identifier of the resource in Oracle Field Service. Existing resources External ID values
  preferenceType string Mandatory Indicates the type of resource preference for the activity in the booking process.
  • Preferred: The resource is preferred for the activity but is not mandatory.
  • Required: The activity can only be assigned to a required resource.
  • Forbidden: The activity cannot be assigned to the specified resource.
"required",
"preferred",
"forbidden"

The following is an example of how the resourcePreferences array should appear in a request:

The description of resourcePreferences node

"resourcePreferences" : [
{
"resourceId":"string",
"preferenceType":"enum"
}
]

In addition to the new resourcePreferences array, the following enhancements have been made:

  • The resourceFields request array now supports the value resourcePreference.
  • The resourcesDictionary response array now supports new calculated value resourcePreference, which may return one of the following: "required" or"preferred".

Note While "forbidden" is a valid resource preference, forbidden resources are never returned as a part of the response.

The following example shows how these changes appear in a typical request and response payload:

Request and response mentioned parts

{
    "dateFrom": "2025-04-14",
    "dateTo": "2025-04-14",
    "includeTimeSlotsDictionary" : true,
    "includeResourcesDictionary" : true,
    "resourceFields": ["resourceId","resourcePreference"],
    "lateStartMitigation": 20,
    "identifyActivityBy": "activityId",
    "activity":
    {
        "activityId":8762762,
        "resourcePreferences": [
            {
                "resourceId": "Tech1AreaN",
                "preferenceType": "required"
            }
        ]
    }
}
{
    "duration": 26,
    "travelTime": 30,
    "workZone": "LONGWOOD",
    "timeSlotsDictionary": [...],
    "resourcesDictionary": [
        {
            "resourceId": "Tech1AreaN",
            "name": "Tech1AreaN",
            "resourcePreference": "required"
        }
    ],
    "areas": [
    ....
    ]
}

showBookingGrid API Resource Preference Processing

When booking a new activity:

  • Required Resources:
    • Only resources marked as "required" are considered.
    • If no "required" resources are available, the response returns "noCapacity" reason.
  • Forbidden Resources:
    • Resources marked as "forbidden" are excluded, even if they are the only available options.
    • If the exclusion leads to no available resources, the operation returns "noCapacity" reason.
  • Preferred Resources:
    • The system prioritizes "preferred" resources.
    • Non-preferred resources will only be returned if no "preferred" resources are available.

When re-booking an existing activity, the same preferences are applied in the following order:

  • Preferences provided in the request take precedence over those defined in the activity
  • An empty preference list (resourcePreferences array) in the request clears existing preferences in the activity
  • Activity-level resources preferences apply only when no resourcePreferences array is included in the request

showBookingGrid API request/response examples

Request / Response example in booking (new activity creation) mode

POST https://frontend.ofsc.team/rest/ofscCapacity/v1/showBookingGrid HTTP/1.1
Accept: application/json 
Content-Type: application/json
 
{
    "dateFrom": "2025-04-30",
    "dateTo": "2025-04-30",
    "returnReasons":"true",
    "resourceFields": ["resourceId", "resourcePreference"],
    "includeTimeSlotsDictionary" : true,
    "includeResourcesDictionary" : true,
    "extended":"false",
    "testMode":"false",
    "lateStartMitigation": 20,
    "activity":
    {
        "resourcePreferences":[
            {
                "resourceId": "Tech1AreaTF",
                "preferenceType": "preferred"
            },
            {
                "resourceId": "Tech1AreaN",
                "preferenceType": "required"
            }
        ],
        "string_text_activity_property": "IN",
        "BookingStatisticProperty_1": "PROP4",
        "BookingStatisticProperty_2": "PROP5",
        "BookingStatisticProperty_3": "PROP6",
        "BookingStatisticProperty_4": "PROP7",
        "duration":60,
        "activityType":"default_customer_activity_type",
        "city": "Merritt Island",
        "googleAddress": "301 Grove Blvd, Merritt Island, FL 32953, USA",
        "address":"301 Grove Blvd",
        "state":"FL",
        "country_code":"US",
        "postalCode": "32953",
        "latitude": 28.3789106,
        "longitude": -80.7103838,
        "timeZone":"Etc/UTC"
    }
}
 
HTTP/2 200 
server: nginx/1.20.1
date: Tue, 29 Apr 2025 17:36:47 GMT
content-type: application/json; charset=utf-8
cache-control: no-store, no-cache
strict-transport-security: max-age=31536000
 
{
    "duration": 60,
    "travelTime": 40,
    "actualAtTime": "2025-04-29 17:36:47",
    "workZone": "ChristmasBKFRD",
    "timeSlotsDictionary": [
        {
            "label": "08-10",
            "name": "08-10",
            "timeFrom": "08:00:00",
            "timeTo": "10:00:00"
        },
        {
            "label": "15-17",
            "name": "15-17",
            "timeFrom": "15:00:00",
            "timeTo": "17:00:00"
        },
        {
            "label": "14-18",
            "name": "14-18",
            "timeFrom": "14:00:00",
            "timeTo": "18:00:00"
        },
        {
            "label": "10-12",
            "name": "10-12",
            "timeFrom": "10:00:00",
            "timeTo": "12:00:00"
        }
    ],
    "resourcesDictionary": [
        {
            "resourceId": "Tech1AreaN",
            "name": "Tech1AreaN",
            "resourcePreference": "required"
        }
    ],
    "areas": [
        {
            "label": "AreaTF",
            "name": "AreaTF",
            "bucket": "AreaTF",
            "averageBucketTravel": 40,
            "averageTravelKeyTravel": 5,
            "timeZone": "Etc/UTC",
            "areaTimeSlots": [
                "08-10",
                "15-17",
                "14-18",
                "10-12"
            ],
            "dates": [
                {
                    "date": "2025-04-30",
                    "hasNearbyActivities": false,
                    "hasForecastedActivities": false,
                    "timeZoneDiff": 0,
                    "timeSlots": [
                        {
                            "label": "10-12",
                            "resourceId": "Tech1AreaN",
                            "recommendationInfo": {
                                "additionalTravel": 13,
                                "travelKeyMatch": false
                            },
                            "setPositionInRoute": {
                                "position": "first"
                            }
                        },
                        {
                            "label": "14-18",
                            "resourceId": "Tech1AreaN",
                            "recommendationInfo": {
                                "additionalTravel": 13,
                                "travelKeyMatch": false
                            },
                            "setPositionInRoute": {
                                "position": "first"
                            }
                        },
                        {
                            "label": "15-17",
                            "resourceId": "Tech1AreaN",
                            "recommendationInfo": {
                                "additionalTravel": 13,
                                "travelKeyMatch": false
                            },
                            "setPositionInRoute": {
                                "position": "first"
                            }
                        },
                        {
                            "label": "08-10",
                            "resourceId": "Tech1AreaN",
                            "recommendationInfo": {
                                "additionalTravel": 13,
                                "travelKeyMatch": false
                            },
                            "setPositionInRoute": {
                                "position": "first"
                            }
                        }
                    ]
                }
            ]
        }
    ]
}

Request / Response example in re-booking mode

POST https://frontend.ofsc.team/rest/ofscCapacity/v1/showBookingGrid HTTP/1.1
Accept: application/json
Content-Type: application/json
 
{
    "dateFrom": "2025-05-30",
    "dateTo": "2025-05-30",
    "includeTimeSlotsDictionary" : true,
    "includeResourcesDictionary" : true,
    "returnReasons":"true",
    "resourceFields": ["resourceId","resourcePreference"],
    "extended":"false",
    "testMode":"false",
    "lateStartMitigation": 20,
    "identifyActivityBy": "activityId",
    "activity":
    {
        "activityId":8762784,
        "resourcePreferences": [
            {
                "resourceId": "Tech1AreaN",
                "preferenceType": "preferred"
            }
        ]
    }
}
 
HTTP/2 200
server: nginx/1.20.1
date: Tue, 29 Apr 2025 17:37:25 GMT
content-type: application/json; charset=utf-8
cache-control: no-store, no-cache
strict-transport-security: max-age=31536000
 
{
    "duration": 60,
    "travelTime": 40,
    "actualAtTime": "2025-04-29 17:37:24",
    "workZone": "ChristmasBKFRD",
    "timeSlotsDictionary": [
        {
            "label": "08-10",
            "name": "08-10",
            "timeFrom": "08:00:00",
            "timeTo": "10:00:00"
        },
        {
            "label": "15-17",
            "name": "15-17",
            "timeFrom": "15:00:00",
            "timeTo": "17:00:00"
        },
        {
            "label": "14-18",
            "name": "14-18",
            "timeFrom": "14:00:00",
            "timeTo": "18:00:00"
        },
        {
            "label": "10-12",
            "name": "10-12",
            "timeFrom": "10:00:00",
            "timeTo": "12:00:00"
        }
    ],
    "resourcesDictionary": [
        {
            "resourceId": "Tech1AreaN",
            "name": "Tech1AreaN",
            "resourcePreference": "preferred"
        }
    ],
    "areas": [
        {
            "label": "AreaTF",
            "name": "AreaTF",
            "bucket": "AreaTF",
            "averageBucketTravel": 40,
            "averageTravelKeyTravel": 5,
            "timeZone": "Etc/UTC",
            "areaTimeSlots": [
                "08-10",
                "15-17",
                "14-18",
                "10-12"
            ],
            "dates": [
                {
                    "date": "2025-05-30",
                    "hasNearbyActivities": false,
                    "hasForecastedActivities": false,
                    "timeZoneDiff": 0,
                    "timeSlots": [
                        {
                            "label": "10-12",
                            "resourceId": "Tech1AreaN",
                            "recommendationInfo": {
                                "additionalTravel": 13,
                                "travelKeyMatch": false
                            },
                            "setPositionInRoute": {
                                "position": "first"
                            }
                        },
                        {
                            "label": "14-18",
                            "resourceId": "Tech1AreaN",
                            "recommendationInfo": {
                                "additionalTravel": 13,
                                "travelKeyMatch": false
                            },
                            "setPositionInRoute": {
                                "position": "first"
                            }
                        },
                        {
                            "label": "15-17",
                            "resourceId": "Tech1AreaN",
                            "recommendationInfo": {
                                "additionalTravel": 13,
                                "travelKeyMatch": false
                            },
                            "setPositionInRoute": {
                                "position": "first"
                            }
                        },
                        {
                            "label": "08-10",
                            "resourceId": "Tech1AreaN",
                            "recommendationInfo": {
                                "additionalTravel": 13,
                                "travelKeyMatch": false
                            },
                            "setPositionInRoute": {
                                "position": "first"
                            }
                        }
                    ]
                }
            ]
        }
    ]
}

findMatchingResources API Operation Changes

The following enhancements have been implemented to improve flexibility and support resource preference handling during booking and rebooking:

  1. Already existing resourcePreferences request array is now supported in re-booking mode as well
  2. The resource response object now supports new calculated value resourcePreference as part of its default fields. This field may return one of the following values: "required" or "preferred".

Note While "forbidden" is possible as a resource preference, forbidden resources are never returned as a part of the result.

findMatchingResources API Resource Preference Processing

When booking a new activity:

  • Required Resources:
    • Only resources marked as "required" are considered.
    • If no "required" resources are available, no resources are returned.
  • Forbidden Resources:
    • Any resources marked as "forbidden" are excluded from the response, even if they are the only available options.
    • If the exclusion leads to no available resources, no resources are returned.
  • Preferred Resources:
    • The system prioritizes "preferred" resources when suggesting resources in the response.

When re-booking an existing activity, the same preferences are applied in the following order:

  • Preferences provided in the request take precedence over those defined in the activity
  • An empty preference list (resourcePreferences array) in the request clears existing preferences in the activity
  • Activity-level resources preferences apply only when no resourcePreferences array is included in the request

findMatchingResources API request/response examples

Request / Response example in booking (new activity creation) mode

POST https://frontend.ofsc.team/rest/ofscCore/v1/resources/custom-actions/findMatchingResources HTTP/1.1
Accept: application/json
Content-Type: application/json
 
{
    "criteria": {
        "finalTravelSupport": false,
        "resourcePreference": 0.0,
        "workSkill": 100,
        "workTime": 10,
        "workZone": 100,
        "includeResources": "technicians"
    },
    "limit": 4,
    "fields": [
        "resourceId",
        "resourceType",
        "parentResourceId"
    ],
    "forecastDuringBooking": {
        "useForecastDuringBooking": false,
        "optimizationGoal": "minimizeAdditionalTravel",
        "minForecastRangeDay": 1,
        "maxForecastRangeDay": 10,
        "explainRemovedOptions": true
    },
    "schedulesToReturn": [
        "2025-06-14"
    ],
    "schedulesFields": [
        "forecastDuringBookingDetails",
        "fitness",
        "arrivalTimeOptions",
        "routeDetails",
        "freeTimeWindows"
    ],
    "activity": {
        "resourcePreferences":[
            {
                "resourceId": "Tech1AreaTF",
                "preferenceType": "required"
            },
            {
                "resourceId": "Tech2AreaN",
                "preferenceType": "preferred"
            },
            {
                "resourceId": "Tech2AreaN",
                "preferenceType": "preferred"
            },
            {
                "resourceId": "Tech3AreaN",
                "preferenceType": "forbidden"
            }
        ],
        "string_text_activity_property": "IN",
        "BookingStatisticProperty_1": "PROP4",
        "BookingStatisticProperty_2": "PROP5",
        "BookingStatisticProperty_3": "PROP6",
        "BookingStatisticProperty_4": "PROP7",
        "StringTextActivity": "IN",
        "activityType": "default_customer_activity_type",
        "timeZone": "(UTC+02:00) Athens - Eastern European Time (EET)",
        "customerName": "fmr customer name",
    "city": "Merritt Island",
    "googleAddress": "301 Grove Blvd, Merritt Island, FL 32953, USA",
    "address":"301 Grove Blvd",
    "state":"FL",
    "country_code":"US",
    "postalCode": "32953",
    "latitude": 28.3789106,
    "longitude": -80.7103838,
        "WO_TYPE": "4",
        "duration":60
    }
}
 
HTTP/2 200
server: nginx/1.20.1
date: Wed, 04 Jun 2025 13:12:36 GMT
content-type: application/json; charset=utf-8
cache-control: no-store, no-cache
strict-transport-security: max-age=31536000
 
{
    "totalResults": 1,
    "limit": 4,
    "offset": 0,
    "actualAtTime": "2025-06-04 13:12:36",
    "items": [
        {
            "resource": {
                "resourceId": "Tech1AreaTF",
                "status": "active",
                "language": "en",
                "languageISO": "en-US",
                "resourceType": "field_resourcer_full",
                "parentResourceId": "AreaTF",
                "resourcePreference": "required"
            },
            "schedules": {
                "2025-06-14": {
                    "fitness": {
                        "workTime": 600,
                        "workSkill": 100,
                        "workZone": 100,
                        "resourcePreference": 0.5
                    },
                    "freeTimeWindows": [
                        [
                            "08:00",
                            "18:00"
                        ]
                    ],
                    "arrivalTimeOptions": [
                        {
                            "minStartTime": "11:38",
                            "maxStartTime": "17:00",
                            "workZoneMatch": false,
                            "setPositionInRoute": {
                                "position": "first"
                            },
                            "additionalTravel": 76
                        }
                    ]
                }
            }
        }
    ]
}

Request / Response example in re-booking mode

POST https://frontend.ofsc.team/rest/ofscCore/v1/resources/custom-actions/findMatchingResources HTTP/1.1
Accept: application/json
Content-Type: application/json
 
{
    "criteria": {
        "resourcePreference": 0.0,
        "workSkill": 100,
        "workTime": 10,
        "workZone": 100,
        "includeResources": "technicians"
    },
    "limit": 4,
    "fields": [
        "resourceId",
        "resourceType",
        "parentResourceId"
    ],
    "schedulesToReturn": [
        "2025-06-14"
    ],
    "schedulesFields": [
        "forecastDuringBookingDetails",
        "fitness",
        "arrivalTimeOptions",
        "routeDetails",
        "freeTimeWindows"
    ],
    "activityId":8762789,
    "activity": {
        "resourcePreferences":[
            {
                "resourceId": "Tech1AreaTF",
                "preferenceType": "required"
            },
            {
                "resourceId": "Tech1AreaN",
                "preferenceType": "preferred"
            },
            {
                "resourceId": "Tech2AreaN",
                "preferenceType": "preferred"
            },
            {
                "resourceId": "Tech3AreaN",
                "preferenceType": "forbidden"
            }
        ]
    }
}
 
HTTP/2 200
server: nginx/1.20.1
date: Thu, 05 Jun 2025 07:13:15 GMT
content-type: application/json; charset=utf-8
cache-control: no-store, no-cache
strict-transport-security: max-age=31536000
 
{
    "totalResults": 1,
    "limit": 4,
    "offset": 0,
    "actualAtTime": "2025-06-05 07:13:15",
    "items": [
        {
            "resource": {
                "resourceId": "Tech1AreaTF",
                "status": "active",
                "language": "en",
                "languageISO": "en-US",
                "resourceType": "field_resourcer_full",
                "parentResourceId": "AreaTF",
                "resourcePreference": "required"
            },
            "schedules": {
                "2025-06-14": {
                    "fitness": {
                        "workTime": 120,
                        "workSkill": 100,
                        "workZone": 100,
                        "resourcePreference": 0.5
                    },
                    "freeTimeWindows": [
                        [
                            "08:00",
                            "18:00"
                        ]
                    ],
                    "arrivalTimeOptions": [
                        {
                            "minStartTime": "15:00",
                            "maxStartTime": "17:00",
                            "workZoneMatch": false,
                            "setPositionInRoute": {
                                "position": "first"
                            },
                            "additionalTravel": 20
                        }
                    ]
                }
            }
        }
    ]
}

  • Provides the ability to assign activities to designated resources early in the process, making it easier to accommodate specific business needs, compliance standards, or operational constraints.
  • Enhances efficiency by reducing the need for manual intervention and back-and-forth in the scheduling process.

Steps to Enable

This feature is enabled automatically starting from version 25D. It will work for every call to FindMatchingResources or ShowBookingGrid if the request includes resource preferences or the activity being rebooked has preferences set.

Tips And Considerations

To rebook activities while ignoring the existing resource preferences, set the resourcePreferences array in the request to an empty. Note that the resource preferences in the request override those in the activity. Consider updating the activity resource preferences afterward if changes must persist.