# hospitality.room-rate Prices a hotel stay night by night from a rate table the caller supplies, then takes off the length-of-stay discount the stay qualifies for. The result lists every night with its date, season and price, then the subtotal, discount and total. ## The rate table is the hotel's Rates are commercial decisions, not published rules, so there is no data file here. Each row covers a range of nights (`firstNight` to `lastNight`, inclusive) and, optionally, only some days of the week: ``` low 2026-01-01 .. 2026-03-31 Sun-Thu 90.00 low weekend 2026-01-01 .. 2026-03-31 Fri-Sat 110.00 high 2026-04-01 .. 2026-09-30 any 140.00 ``` A night is named by the date it starts, so "Friday night" is the night of a Friday, with the ISO weekday of that date (1 Monday to 7 Sunday). **Exactly one row must match each night.** If none does, or two do, the function fails and names the night. The obvious alternatives, "the last row wins" or "the narrowest range wins", both quietly price a stay wrong the day someone adds an event rate on top of a season without removing the season. Make the rows disjoint, for example by splitting the season around the event. ## Length-of-stay discounts `stayDiscounts` is a list of "at least n nights, x% off". The stay gets the discount with the largest `minNights` it reaches (7 nights beats 3 nights), and only that one. The percentage is taken off the subtotal once, rounded half-up, so there is no per-night rounding drift. ## Edge cases - A stay across 29 February, a month end or a year end steps through the calendar with `dates.add-days`. - Every row must be in the same currency as the others the stay uses. - A malformed or impossible date anywhere in the table or the arrival is an error. ## Not covered Per-person pricing, occupancy supplements, children's rates, packages and taxes (see `hospitality.tourist-tax` and `finance.tax.add-vat`) are separate steps.