feat(billing): metered charge math (quota + overage)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-27 02:50:14 -04:00
parent a1cfab6fe9
commit 1e34a67384
3 changed files with 67 additions and 1 deletions

View File

@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1
from odoo import fields, models
import math
from odoo import api, fields, models
class FusionBillingCharge(models.Model):
@@ -51,3 +53,21 @@ class FusionBillingCharge(models.Model):
"res.currency", default=lambda self: self.env.company.currency_id,
)
active = fields.Boolean(default=True)
def _compute_billable(self, total_quantity):
"""Return (overage_units, amount) for total period usage under this charge.
- overage_units = usage above included_quota (never negative)
- 'standard'/'package'/'volume': priced per `unit_batch` block, partial block rounds up.
(graduated tiers are out of scope for the core; treated as 'standard'.)
"""
self.ensure_one()
overage = max(0.0, (total_quantity or 0.0) - (self.included_quota or 0.0))
batch = self.unit_batch or 1.0
if self.charge_model == 'package':
# whole packages over the RAW quantity (quota ignored for package counting)
blocks = math.ceil((total_quantity or 0.0) / batch) if total_quantity else 0
return overage, round(blocks * (self.price_per_unit or 0.0), 2)
# standard / volume / graduated-fallback: price the overage in (rounded-up) batches
blocks = math.ceil(overage / batch) if overage > 0 else 0
return overage, round(blocks * (self.price_per_unit or 0.0), 2)