Measured Behaviour
Published
Every restriction in an availability table is a property of one night. A reservation is a run of nights. One option decides which of the two the rule is applied to, and losing it leaves every individual night correct.
A forty-room house over a holiday
The measured run is a hundred and forty reservations arriving over a fortnight at a forty-room property. The holiday peak carries a three-night minimum, its shoulders a two-night minimum, and Christmas Day itself is closed to arrival. Most of the requests are one- and two-night stays at a higher nightly rate; a smaller number are the long stays the minimums exist to hold the inventory for.
Correct, the house accepts ninety-four reservations, refuses forty-six, consults three hundred and forty-one night-level restrictions and takes 79,701.00 dollars. Eighty-four room-nights are sold on the protected peak dates and none of them to a stay shorter than that night's own minimum.
This is the arrangement the revenue manager built. It deliberately turns away higher-rated business on the peak in order to keep the shoulders full.
A constraint over a span, applied to a single night
restrictionScope says whether a minimum applies to every night a stay occupies or only to the night the guest checks in. The property's setting is stay-through. The library's default is arrival-night, and that is not a careless default -- the arrival date is the one field every distribution channel sends reliably, and it is what booking engines have traditionally checked.
Rename it, and the same table refuses only stays that begin on a protected night. A two-night stay arriving the day before takes a three-night-minimum date and is accepted.
Measured: accepted rises from 94 to 102, peak room-nights from 84 to 92, and SHORT-STAYS-ON-PEAK from 0 to 8. Revenue rises from 79,701.00 to 84,325.00.
Nothing about those bookings is individually wrong. Every night of every one of them was open, had inventory, and satisfied its own arrival-night rule. The constraint was over the span, and the span is what stopped being consulted.
The failing arm earns more money
Revenue is 4,624.00 dollars higher in the broken run, and that is not an artefact of the fixture. It is the reason minimum-stay rules are hard to operate: short stays pay a higher nightly rate, so taking them is the better decision one reservation at a time and the worse decision across a fortnight, because the shoulder nights that the long stays would have filled empty out.
Any monitoring built on the figures a general manager reviews daily -- rooms sold, occupancy, average rate, revenue -- reads better in the arm where the restriction stopped working. The property's own stay rule passes too, because it verifies that every reservation reached a decision and that restrictions were consulted, and both remain true.
The one figure that moves against the broken run is the count of restrictions consulted: 341 becomes 125. That number is on no report anybody reads, and it is the only cheap tell in the file.
The counter that reports the damage is defined over the table
Rename minStayNights -- the table of per-night minimums -- and the house accepts a hundred and twenty reservations, takes 88,685.00 dollars, and sells a hundred and three peak room-nights.
SHORT-STAYS-ON-PEAK reads 0. It looks each night's minimum up in the table, and the table is what went missing. A stay cannot be shorter than a minimum that no longer exists.
This is the second time in one measurement pass that a counter written specifically to report a failure was defined over the configuration that failed. A metric derived from the control it monitors is not a second opinion; it is the same opinion, restated.
The other visible effect in that arm is the mix: room-nights on the long-stay rate plan fall from 261 to 240 while total room-nights rise, which is exactly the displacement the minimums were written to prevent.
What was inert, and what refused
maxStayNights and closedToArrival moved no money at all on this run. Both were read individually rather than assumed: the maximum is not approached by any reservation in the book, and the closed-to-arrival date's traffic is refused by the three-night minimum before the arrival rule is ever reached. They are inert here because a sibling restriction decides first, not because they are safe names.
nightlyCapacity, arriveDay and nights each produce a non-finite value and the engine refuses before booking anything -- the loud, safe direction, and the pattern this series has now measured on every failure shape it has found.
ratePlan is the quiet one. It changes no decision and no money: room-nights on the long-stay plan simply report as 0 instead of 261. The protection works perfectly and the report of what it protected is gone.
defaultMinStay and the unit label were pinned equal to the library's defaults as controls, and both were inert exactly as predicted.
What protection alone did, and what to do about it
Protection alone was clean. Five profiles, five areas, output identical to the unprotected run in every case. The results above needed member renaming aimed at the availability configuration or the reservation records.
Keep those names out of the pattern. If the booking widget is an Angular front end, the Angular protection guide covers the build settings; the general case of inventory that can be promised twice is in inventory reservations.
The design answer is the same one a dropped column in a channel-manager import would call for. Assert the span rather than the night: publish a test that a two-night stay arriving the day before a three-night minimum is refused. And measure what the protected nights were actually sold to, using a source that does not read the restriction table -- a rate-plan mix or a stay-length histogram will do -- because a counter built on the table cannot report the table going missing.
Frequently asked questions
Does obfuscation change hotel availability rules?
Not on its own. Protection with default settings produced byte-identical output on all five profiles. The changes here required member renaming aimed at the availability option keys or the reservation record fields.
What is the difference between stay-through and arrival-night?
A stay-through restriction applies a night's minimum to any reservation occupying that night. An arrival-night restriction applies it only to reservations that begin on it. The library defaults to arrival-night because the arrival date is the field every distribution channel sends reliably.
What did losing that option actually do?
Accepted reservations rose from 94 to 102, peak room-nights from 84 to 92, and eight protected holiday room-nights were sold to stays shorter than their own minimum. Revenue rose from 79,701.00 to 84,325.00.
Why is higher revenue a problem?
Because it is higher on the run and lower across the fortnight. Short stays pay a higher nightly rate, so accepting them looks correct one reservation at a time; the shoulder nights the long stays would have filled are what empty out. Every daily figure a manager reviews reads better in the broken arm.
Is there any cheap tell?
One, and it is on no report: the number of night-level restrictions consulted fell from 341 to 125. Rooms sold, occupancy, rate and revenue all moved in the reassuring direction.
Does a short-stays-on-peak metric catch it?
Not if it is derived from the same table. Renaming the minimum-stay table itself left that counter reading 0, because it looks each night's minimum up in the table that went missing. Use a source that does not read the restriction table, such as a stay-length or rate-plan mix.
Which names were inert, and does that make them safe?
The maximum-stay and closed-to-arrival options moved no money on this run, but only because a stricter sibling restriction refused the same reservations first. They are inert on this data, not safe in general -- which is why each was executed and read rather than grouped into a summary.
Related reading