# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 from odoo import fields, models class FusionBillingUsage(models.Model): """Aggregated usage rollup for a (subscription, metric, period). Aggregate-push model: apps send periodic counters (not raw events). The ``idempotency_key`` makes re-sent counters safe โ€” they never double-count. A pre-invoice cron sums these and feeds billable quantity onto the subscription. NOTE (Odoo 19, verified): the subscription is a ``sale.order`` with ``is_subscription=True`` โ€” there is no ``sale.subscription`` model. See spec ยง5.2. """ _name = "fusion.billing.usage" _description = "Fusion Billing โ€” Aggregated Usage (period rollup)" _order = "period_start desc" subscription_id = fields.Many2one( "sale.order", required=True, ondelete="cascade", index=True, string="Subscription", domain=[("is_subscription", "=", True)], ) metric_id = fields.Many2one( "fusion.billing.metric", required=True, ondelete="restrict", index=True, ) period_start = fields.Datetime(required=True) period_end = fields.Datetime(required=True) quantity = fields.Float(default=0.0) source = fields.Char(default="push") idempotency_key = fields.Char( index=True, help="Dedupe key so re-sent counters never double-count.", ) _idempotency_uniq = models.Constraint( "unique(idempotency_key)", "Usage idempotency key must be unique.", )