Almanac
Microsoft/d365fsDynamics 365

Consultant-focused KB for Microsoft Dynamics 365 Field Service: implementation notes, gotchas, and configuration decisions beyond the official docs — across work orders, scheduling and dispatch, resource management, mobile app, asset management, inspections, IoT, Copilot, and administration.

feature-booking-rules-and-validation.mdv1 · history
CurrentApplies to Resource SchedulingUpdated 6 days agoSource Microsoft Learn

What it does

A booking rule is a JavaScript function, registered against a web resource, that runs before a Bookable Resource Booking is saved and can block the save with an error or let it through with a warning. It is the supported way to enforce dispatch policy that the scheduling engine's own constraints don't cover.

Key facts

  • Rules are registered under Field Service > Resources > Booking Settings > Booking Rules, giving a name, the web resource, and the method name to call.
  • The function receives a context object with oldValues and newValues (each carrying ResourceRequirementId, ResourceId, StartTime, EndTime, ResourceScheduleSource), plus isCreate and isUpdate booleans.
  • It returns { IsValid, Message, Type } where Type is "error" or "warning". Error blocks the save; warning lets the user continue.
  • One message per rule. If you need three validations with three messages, you need three rules.
  • Rules fire on the schedule board hourly view only, on the schedule assistant, and on the Bookable Resource Booking form. They do nothing in daily, weekly or monthly views.
  • Rules do not fire on the schedule board's reassign function, do not fire on deletion, and don't work with multi-edit forms.
  • Rules are not available if business process flows are enabled on the booking form. There's an app setting, msdyn_DisableProcessBookingRulesOnSaveBookingForm, read and written through Xrm.Utility.getGlobalContext(), that lets you turn rule processing off on the form so a BPF can be used.
  • A rule can call a custom process action, passing newScheduleStart, newScheduleEnd and newBookableResource, and read back isError, isWarning, errorMessage and warningMessage. That's how you get server-side data into the decision.
  • Deactivating the booking rule record disables the rule. There's no per-user or per-board toggle.

When to use / skip

Use booking rules for policy that must be enforced at the moment of booking and can't be expressed as a requirement constraint: no bookings within four hours of a shift end, no second visit to the same site the same day, no engineer booked without a valid certificate on file. Skip them for anything the scheduling engine already handles — characteristics, territories, roles, promised windows — because duplicating a constraint in JavaScript just gives you two places to maintain and one of them only works in hourly view. Also skip them where a warning is really all you need and a colour on the board would do the job. If the client's ask is "stop dispatchers doing X", check first whether X is even reachable through a path where rules fire; a rule that doesn't cover the reassign action or the weekly view isn't enforcement, it's a suggestion.

Configuration decisions

  • Which validations are errors and which are warnings. Errors stop work in a busy dispatch room, so the list of hard stops should be short and defensible.
  • Whether validation lives in a booking rule, in a plugin on the booking table, or both. Plugins cover every path including API and mobile; rules give a decent user experience but only on the paths listed above.
  • How many rules to split the logic across, given one message each.
  • Whether any rule needs server-side data, which forces the custom action route and adds a round trip to every booking save.
  • Whether business process flows are wanted on the booking form, because that trades directly against rule processing.
  • Message wording, since dispatchers see it mid-task and will judge the whole system by it.

Gotchas

  • The hourly-view-only limitation is the big one. Users scheduling multi-day work in weekly view get no validation at all and assume the rule is broken.
  • Reassigning a booking on the board bypasses rules entirely, which is exactly the action a "don't move committed work" rule is meant to catch.
  • Nothing fires on delete, so a rule protecting a booking can't stop someone removing it.
  • Every rule adds latency to the booking save, and dispatchers book in bursts. A rule calling a custom action that queries related records is felt immediately.
  • Turning on a business process flow on the booking form silently kills rule processing unless you handle the app setting deliberately.
  • Rules run client-side. Bookings created by integrations, Power Automate, RSO or the mobile app never see them, so anything that must always hold needs server-side enforcement as well.

Consultant notes

  • Ask for the list of "the system should stop us from…" statements in discovery, then sort them into engine constraints, booking rules and plugins before writing any code. Most of the list turns out to be constraints.
  • Demo a rule firing and a rule not firing, in weekly view, in the same session. It's an unglamorous demo that prevents a month of misunderstanding.
  • Keep the JavaScript small and put anything with data dependencies behind a custom action, so the logic is testable and can be reused by a plugin.
  • Before go-live, walk every route into a booking — board, assistant, form, mobile, integration, RSO — and mark which are covered. Hand that table to the client rather than saying "validation is in place".
  • Push back on rules that encode a target rather than a rule. "Don't book more than seven jobs a day" is usually a capacity conversation, not an error message.

Worth another look if rule coverage extends beyond hourly view, or when someone asks for a business process flow on the booking form.

Was this accurate?