Functional Weave
Code in TypeScript

hospitality.cancellation-charge@1.0.0

README.md

2,360 bytes · view raw

# hospitality.cancellation-charge

The fee a booking policy charges for cancelling with a given amount of notice.
A policy is a list of bands, for example:

| notice | charge |
|---|---|
| 14 days or more | free |
| 7 to 13 days | 50% of the first night |
| under 7 days, or a no-show | 100% of the whole stay |

which is written as
`[{minDaysNotice: 14, nights: null, basisPoints: 0}, {minDaysNotice: 7, nights: 1, basisPoints: 5000}, {minDaysNotice: 0, nights: null, basisPoints: 10000}]`.

## How notice is counted

Notice is the number of calendar days from the day the guest cancels to the day
they arrive (`dates.days-between`): cancelling on 4 December for 18 December
is 14 days. The band with the largest `minDaysNotice` that the notice still
meets applies, so 14 days falls in the "14 days or more" band. Cancelling on
the arrival day, or recording a no-show after it, is 0 days' notice. The result
still reports the true signed count (-1 for the day after), so a caller can
tell the two apart.

Times of day are not modelled. A policy that says "48 hours before 3pm check-in"
has to be turned into whole days by the caller first.

## The charge

`nights` picks the nights the percentage is taken of: the first `n` nights
(capped at the length of the stay) or, when it is `null`, the whole stay.
`nightlyRates` lists the price of each night in order, so a stay whose first
night is cheaper than the weekend is charged correctly. The percentage is
applied once to those nights' total and rounded half-up.

## Edge cases and errors

- The bands may be listed in any order. Two bands with the same
  `minDaysNotice` are an error, and so is notice that no band covers (a policy
  should always have a 0-day band).
- Every night must be in the same currency.

## Not covered

- **Fairness.** A cancellation charge is a term of a consumer contract. Under
  the Consumer Rights Act 2015, Part 2, an unfair term does not bind the
  consumer, and the CMA's guidance on unfair contract terms (CMA37) treats
  charges that exceed the trader's likely loss as a risk. This function applies
  whatever policy it is given. It does not judge whether that policy is fair.
- **VAT.** How VAT applies to a retained deposit or a cancellation fee depends
  on HMRC's current view of early termination and cancellation payments. This
  function works out the amount only.