Count billable phone extensions

Featurekamo-shared-library
Shipped
August 27, 2026 at 2:56 AM UTC
Author
Kamo
Commit
a601630

Adds the phone twin of the per-mailbox aggregator: PbxBillingClass with an exhaustive VoipProviderType switch and no default arm, OrgPbxBillingAggregator (no Spring stereotype - BillingService declares the bean), and the daily audit snapshot. One structural difference runs through everything downstream. org_email_providers is unique on org_id, so exactly one mail add-on could ever bill non-zero. VOIP_PROVIDER_INSTANCE is many rows per org, so an org can run KamoPBX and RingCentral at once and both add-ons bill in the same month. The breakdown is therefore one flat list carrying a class per extension, and countByClass() drives the unused code to zero through the ordinary path rather than a special case. VoipProviderType is EnumType.ORDINAL, so nothing is appended to it; the coverage test pins the order as well as the classification. FREE_PBX classifies as third party - the picker offers it as an on-premise PBX, which is the customer's own Asterisk. KAMO_PBX is therefore the only hosted type and, since no KAMO_PBX instance exists and KamoPBXProvider still throws from every method, PBX_HOSTING correctly bills nothing at all today. Both assignment records are read - **************** and MEMBER_VOIP_CONFIG - because the member phone-settings screen writes both, so their union is exactly what an administrator set. A number that decides money should not rest on one column a background sweep can zero, which is precisely what InstanceSyncService was doing to it. ExtensionBillingDay is keyed on the subscription as well as the day and code, so an org with two billing groups keeps two audit rows instead of one overwriting the other.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing