///|
/// Whether a contractual minimum applies when the trusted quantity is zero.
pub(all) enum ZeroUsageMinimum {
Charge
Waive
} derive(Debug, Eq)
///|
pub extend ZeroUsageMinimum with Debug::{to_repr}
///|
pub extend ZeroUsageMinimum with Eq::{equal, not_equal}
///|
/// Usage-only calculation remains untouched. total = calculation.total + top_up.
/// Only total is settled; no intermediate rounded amount is fed into the floor.
pub(all) struct Charge {
calculation : Calculation
minimum : String
zero_usage : ZeroUsageMinimum
top_up : String
total : String
settlement : Settlement
} derive(Debug, Eq)
///|
pub extend Charge with Debug::{to_repr}
///|
pub extend Charge with Eq::{equal, not_equal}
///|
/// Apply an explicit single-metric minimum before one settlement operation.
///
/// ```mbt check
/// test {
/// let p = @jieheng.compile_plan(
/// id="api",
/// version="v1",
/// metric="calls",
/// unit="call",
/// currency="USD",
/// tiers=[{ up_to: None, unit_price: "0.004", }],
/// )
/// let c = @jieheng.rate_charge(
/// p,
/// { customer: "acme", metric: "calls", period: "2026-10", quantity: "1", },
/// minimum="0.005",
/// zero_usage=Charge,
/// scale=2,
/// rounding=HalfEven,
/// )
/// inspect(c.top_up, content="0.001")
/// inspect(c.total, content="0.005")
/// inspect(c.settlement.amount, content="0.00")
/// }
/// ```
pub fn rate_charge(
plan : Plan,
usage : Usage,
minimum~ : String,
zero_usage~ : ZeroUsageMinimum,
scale~ : Int32,
rounding~ : Rounding,
) -> Charge raise PricingError {
let floor = decimal(minimum, "charge.minimum")
let calculation = rate(plan, usage)
let raw = amount_atoms(calculation.total, "calculation.total")
let applicable = if usage.quantity == "0" && zero_usage == Waive {
0N
} else {
floor
}
let top_up = if applicable > raw { applicable - raw } else { 0N }
let total = format_atoms(raw + top_up)
let charge = {
calculation,
minimum: format_atoms(floor),
zero_usage,
top_up: format_atoms(top_up),
total,
settlement: settle_total(plan.currency, total, scale~, rounding~),
}
verify_charge(plan, usage, charge, minimum~, zero_usage~, scale~, rounding~)
charge
}
///|
/// Verify usage allocation, explicit policy binding, floor conservation and the
/// independently checked rounding interval. Does not invoke rate_charge.
pub fn verify_charge(
plan : Plan,
usage : Usage,
charge : Charge,
minimum~ : String,
zero_usage~ : ZeroUsageMinimum,
scale~ : Int32,
rounding~ : Rounding,
) -> Unit raise PricingError {
let floor = decimal(minimum, "charge.minimum")
verify_calculation(plan, usage, charge.calculation)
if charge.minimum != format_atoms(floor) || charge.zero_usage != zero_usage {
invalid(
"policy", "charge.minimum", "minimum and zero-usage behavior must match the trusted contract",
)
}
let raw = amount_atoms(charge.calculation.total, "calculation.total")
let extra = amount_atoms(charge.top_up, "charge.top_up")
let total = amount_atoms(charge.total, "charge.total")
let active = usage.quantity != "0" || zero_usage == Charge
// Verify inequalities and conservation rather than invoking the producer.
if total != raw + extra ||
total < raw ||
(active && (total < floor || (total != raw && total != floor))) ||
(!active && extra != 0N) ||
charge.top_up != format_atoms(extra) ||
charge.total != format_atoms(total) {
invalid(
"minimum", "charge.total", "total must equal usage plus the exact necessary minimum top-up; no other fee is supported",
)
}
verify_total_settlement(
plan.currency,
charge.total,
charge.settlement,
scale~,
rounding~,
)
}