直接割当でのリソース・プリファレンス処理

25D更新では、直接割当てモードのAPIコールFindMatchingResources およびShowBookingGrid でリソース・プリファレンス(推奨、禁止および必要なリソース)がサポートされています。

この機能改善により、組織は要求で割当ルールを定義することで、アクティビティをフィールド・リソースに割り当てる方法を制御できます。 これらのプリファレンスは、優先順位付け、回避または厳密に必要なリソースを適用することで、予約動作に影響します。 たとえば、企業は、すでにセキュリティ・クリアランスがある特定のリソース、または制限された領域(必須)にアクセスできる特定のリソースにアクティビティを割り当て、すでに顧客に精通している技術者を割り当てるか、以前にその場所にサービスを提供した技術者を優先させることができます('preferred')、または関連する監査、法的ケース、ビジネス交渉(禁止)に以前関与していたなど、顧客または活動と潜在的な利害対立がある可能性のあるリソースを除外します。

showBookingGrid API操作の変更

新しいresourcePreferences配列が、次の構造を持つshowBookingGrid API操作に追加されました。 配列自体はオプションですが、含まれる場合は、次の必須フィールドが含まれている必要があります。

表: resourcePreferences配列

配列 フィールド  タイプ 必須 説明 許可された値
resourcePreferences - 配列 オプション リソース・プリファレンス・ルール・コンテナ。 -
  resourceID 文字列 必須 Oracle Field Serviceのリソースの一意の識別子。 既存のリソースの外部ID値
  preferenceType 文字列 必須 記帳プロセスのアクティビティのリソース・プリファレンスのタイプを示します。
  • 優先: リソースはアクティビティに対して優先されますが、必須ではありません。
  • 必須: アクティビティは必須リソースにのみ割り当てることができます。
  • 禁止: 指定したリソースにアクティビティを割り当てることはできません。
必須、
優先、
禁止

次に、リクエストでのresourcePreferences配列の表示例を示します。

resourcePreferences nodeの説明

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

新しいresourcePreferences配列に加えて、次の機能改善が行われました。

  • resourceFieldsリクエスト配列で、値resourcePreferenceがサポートされるようになりました。
  • resourcesDictionaryレスポンス配列では、新しい計算値resourcePreferenceがサポートされるようになりました。この値は、「必須」または「優先」のいずれかを返します。

ノート「禁止」は有効なリソース・プリファレンスですが、禁止されているリソースはレスポンスの一部として返されません。

次の例は、これらの変更が通常のリクエスト・ペイロードおよびレスポンス・ペイロードでどのように表示されるかを示しています。

要求および応答の言及された部品

{
    "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リソース・プリファレンスの処理

新規アクティビティを予約する場合:

  • 必須リソース:
    • 「必須」とマークされたリソースのみが考慮されます。
    • 必要なリソースがない場合、レスポンスはnoCapacityの理由を返します。
  • 禁止されているリソース:
    • 「禁止」とマークされたリソースは、使用可能な唯一のオプションであっても除外されます。
    • 除外によって使用可能なリソースがない場合、操作はnoCapacityの理由を返します。
  • 優先リソース:
    • 優先リソースの優先度が設定されます。
    • 使用可能な優先リソースがない場合、非優先リソースのみが返されます。

既存のアクティビティを再予約する場合、同じプリファレンスが次の順序で適用されます。

  • リクエストで指定されたプリファレンスは、アクティビティに定義されているプリファレンスよりも優先されます
  • リクエスト内の空のプリファレンス・リスト(resourcePreferences配列)は、アクティビティ内の既存のプリファレンスをクリアします
  • アクティビティ・レベルのリソース・プリファレンスは、リクエストにresourcePreferences配列が含まれていない場合にのみ適用されます

showBookingGrid APIリクエスト/レスポンスの例

予約(新規アクティビティ作成)モードのリクエスト/レスポンスの例

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"
                            }
                        }
                    ]
                }
            ]
        }
    ]
}

再予約モードのリクエスト/レスポンスの例

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操作の変更

予約および再予約時の柔軟性を向上させ、リソース・プリファレンス処理をサポートするために、次の機能改善が実装されました。

  1. 既存のresourcePreferences リクエスト配列は、再予約モードでもサポートされるようになりました
  2. リソース・レスポンス・オブジェクトは、現在新しい計算値resourcePreferenceをデフォルト・フィールドの一部としてサポートしています。 このフィールドは、次のいずれかの値を返します: "required"または"preferred"。

ノート「禁止」はリソース・プリファレンスとして可能ですが、禁止されているリソースは結果の一部として返されません。

findMatchingResources APIリソース・プリファレンス処理

新規アクティビティを予約する場合:

  • 必須リソース:
    • 「必須」とマークされたリソースのみが考慮されます。
    • 使用可能な「必須」リソースがない場合、リソースは返されません。
  • 禁止されているリソース:
    • 「禁止」とマークされたリソースは、使用可能な唯一のオプションであっても、レスポンスから除外されます。
    • 除外によって使用可能なリソースがなくなった場合、リソースは返されません。
  • 優先リソース:
    • システムは、レスポンスでリソースを提案するときに、優先リソースに優先順位を付けます。

既存のアクティビティを再予約する場合、同じプリファレンスが次の順序で適用されます。

  • リクエストで指定されたプリファレンスは、アクティビティに定義されているプリファレンスよりも優先されます
  • リクエスト内の空のプリファレンス・リスト(resourcePreferences配列)は、アクティビティ内の既存のプリファレンスをクリアします
  • アクティビティ・レベルのリソース・プリファレンスは、リクエストにresourcePreferences 配列が含まれていない場合にのみ適用されます

findMatchingResources APIリクエスト/レスポンスの例

予約(新規アクティビティ作成)モードのリクエスト/レスポンスの例

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
                        }
                    ]
                }
            }
        }
    ]
}

再予約モードのリクエスト/レスポンスの例

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
                        }
                    ]
                }
            }
        }
    ]
}

  • アクティビティをプロセスの早い段階で指定したリソースに割り当てることができるため、特定のビジネス・ニーズ、コンプライアンス標準または業務上の制約に簡単に対応できます。
  • スケジューリング・プロセスにおける手作業やバック・アンド・フォースの必要性を減らすことで、効率性を高めます。

有効化のステップ

この機能は、バージョン25Dから自動的に有効になります。 リクエストにリソース・プリファレンスが含まれる場合、または再予約されるアクティビティにプリファレンスが設定されている場合、FindMatchingResources またはShowBookingGrid へのすべてのコールで機能します。

ヒントと考慮事項

既存のリソース・プリファレンスを無視してアクティビティを再予約するには、リクエスト内のresourcePreferences 配列を空に設定します。 リクエストのリソース・プリファレンスは、アクティビティ内のリソース・プリファレンスよりも優先されます。 変更が存続する必要がある場合は、後でアクティビティ・リソース・プリファレンスを更新することを検討してください。