Functional Weave
Code in Python

hospitality.occupancy-adr-revpar@1.0.0

impl/python.py

1,848 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from .hospitality_occupancy_adr_revpar_types import HotelPerformance
from .math_round_div import round_div  ← from math.round-div ^1.0.0 · built alongside by fune
from .money_amount import Money, money  ← from money.amount ^1.0.0 · built alongside by fune


def _whole(value: object) -> bool:
    return isinstance(value, int) and not isinstance(value, bool)


def occupancy_adr_revpar(room_nights_available: int, room_nights_sold: int, room_revenue: Money) -> HotelPerformance:
    """Occupancy, ADR and RevPAR for a period.

    Each figure is divided out of the raw totals and rounded half-up once.
    RevPAR is revenue over available rooms, not ADR times occupancy:
    multiplying two figures that were each rounded already can be a penny out.
    """
    if not _whole(room_nights_available) or room_nights_available < 1:
        raise ValueError("roomNightsAvailable must be at least 1, received %s" % (room_nights_available,))
    if not _whole(room_nights_sold) or room_nights_sold < 0:
        raise ValueError("roomNightsSold must not be negative, received %s" % (room_nights_sold,))
    if room_nights_sold > room_nights_available:
        raise ValueError(
            "roomNightsSold (%d) cannot exceed roomNightsAvailable (%d)" % (room_nights_sold, room_nights_available)
        )
    if room_revenue.minor < 0:
        raise ValueError("roomRevenue must not be negative, received %d" % (room_revenue.minor,))
    return HotelPerformance(
        room_nights_available=room_nights_available,
        room_nights_sold=room_nights_sold,
        room_revenue=room_revenue,
        occupancy_basis_points=round_div(room_nights_sold * 10000, room_nights_available, "half-up"),
        adr=None
        if room_nights_sold == 0
        else money(round_div(room_revenue.minor, room_nights_sold, "half-up"), room_revenue.currency),
        revpar=money(round_div(room_revenue.minor, room_nights_available, "half-up"), room_revenue.currency),
    )