use super::funejson::Value; use super::math_round_div::round_div; use super::money_amount::{money, money_from_value, money_to_value, Money}; /// 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]), )) }