hospitality.occupancy-adr-revpar@1.0.0
impl/rust.rs
2,639 bytes · the Rust 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.
use super::funejson::Value; ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::math_round_div::round_div; ← from math.round-div ^1.0.0 · built alongside by fune
use super::money_amount::{money, money_from_value, money_to_value, Money}; ← from money.amount ^1.0.0 · built alongside by fune
/// 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.
///
/// # Panics
/// Panics when there are no rooms available, the counts are out of range or
/// the revenue is negative.
pub fn occupancy_adr_revpar(room_nights_available: i64, room_nights_sold: i64, room_revenue: &Money) -> HotelPerformance {
if room_nights_available < 1 {
panic!("roomNightsAvailable must be at least 1, received {}", room_nights_available);
}
if room_nights_sold < 0 {
panic!("roomNightsSold must not be negative, received {}", room_nights_sold);
}
if room_nights_sold > room_nights_available {
panic!(
"roomNightsSold ({}) cannot exceed roomNightsAvailable ({})",
room_nights_sold, room_nights_available
);
}
if room_revenue.minor < 0 {
panic!("roomRevenue must not be negative, received {}", room_revenue.minor);
}
HotelPerformance {
room_nights_available,
room_nights_sold,
room_revenue: room_revenue.clone(),
occupancy_basis_points: round_div(room_nights_sold * 10000, room_nights_available, "half-up"),
adr: if room_nights_sold == 0 {
None
} else {
Some(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,
),
}
}
pub fn hotel_performance_to_value(p: &HotelPerformance) -> Value {
Value::obj(vec![
("roomNightsAvailable", Value::Int(p.room_nights_available)),
("roomNightsSold", Value::Int(p.room_nights_sold)),
("roomRevenue", money_to_value(&p.room_revenue)),
("occupancyBasisPoints", Value::Int(p.occupancy_basis_points)),
(
"adr",
match &p.adr {
Some(a) => money_to_value(a),
None => Value::Null,
},
),
("revpar", money_to_value(&p.revpar)),
])
}
pub fn fune_vector(args: &[Value]) -> Value {
hotel_performance_to_value(&occupancy_adr_revpar(
args[0].as_i64(),
args[1].as_i64(),
&money_from_value(&args[2]),
))
}