Files
HAMeter/hameter/cost.py
2026-03-06 12:25:27 -05:00

61 lines
1.5 KiB
Python

"""Cost calculation for meter rate components."""
import logging
from dataclasses import dataclass
from hameter.config import RateComponent
logger = logging.getLogger(__name__)
@dataclass
class CostResult:
"""Result of a cost calculation for a single reading delta."""
delta: float
per_unit_cost: float
component_costs: list[dict]
total_incremental_cost: float
def calculate_incremental_cost(
delta: float,
cost_factors: list[RateComponent],
) -> CostResult:
"""Calculate the incremental cost for a usage delta.
Only per_unit rate components contribute to incremental cost.
Fixed charges are NOT included — they are handled separately
via the billing period reset / manual add workflow.
Args:
delta: Usage delta in calibrated units (e.g., kWh).
cost_factors: List of rate components from meter config.
Returns:
CostResult with per-component breakdown and total.
"""
component_costs = []
per_unit_total = 0.0
for cf in cost_factors:
if cf.type == "per_unit":
cost = round(delta * cf.rate, 4)
per_unit_total += cost
else:
cost = 0.0
component_costs.append({
"name": cf.name,
"rate": cf.rate,
"type": cf.type,
"cost": cost,
})
return CostResult(
delta=delta,
per_unit_cost=round(per_unit_total, 4),
component_costs=component_costs,
total_incremental_cost=round(per_unit_total, 4),
)