Skip to content

Models ​

Every model extends MetericModel: a UUID primary key (HasUuids, non-incrementing string key) on a meteric_-prefixed table. Money columns are stored as integer minor units (*_minor); per-unit rates that go sub-cent are numeric strings. This page lists the key columns, relationships, and the helper methods you actually call.

Product ​

meteric_products: a catalog entry.

  • Columns: type, slug, name, pricing_model, is_proratable, config (array).
  • Relationships: prices(), meterDimensions(), options(), addons() (ProductAddon rows), billable() (morph).
  • Config: the keys the package reads are validated on write. config['downgrade'] must be a valid DowngradePolicy value, and config['cancel_notice_days'] and config['minimum_term_periods'] non-negative integers, or the assignment throws InvalidArgumentException. Other keys (your own host settings) pass through untouched.
  • Helpers:
    • priceFor(string $currency, PricePurpose $purpose = Recurring, ?Interval $interval = null, ?int $intervalCount = null): ?Price: latest open price for a currency and purpose, narrowed to one term when an interval is given.
    • terms(string $currency, PricePurpose $purpose = Recurring): Collection<Price>: the current recurring prices, one per term, shortest first.
    • termCatalog(string $currency, float $qty = 1, PricePurpose $purpose = Recurring): array: the terms as JSON-ready rows (Price::toDisplay). See Terms.
    • addonCatalog(Price $term, float $qty = 1): array: the bookable addons priced on $term as JSON-ready rows. See Addon catalog.
    • optionCatalog(float $qty = 1): array: the configurable-option catalog as JSON-ready rows, values priced at $qty. See Displaying options in a form.
    • isMetered(): bool: true for metered / hourly.
    • downgradePolicy(): DowngradePolicy: from config['downgrade'], defaults to Defer.
    • cancelNoticeDays(): int: notice required before a contract ends, from config['cancel_notice_days'], then the catalog default, then 0. A price may override it.
    • minimumTerm(): int: periods a new sale is committed for, from config['minimum_term_periods'], then the catalog default, then 0. A price may override it.

Price ​

meteric_prices: versioned pricing for a product.

  • Columns: currency, amount_minor, unit_rate (string), purpose, pricing_model, interval, interval_count, billing_mode, setup_fee_minor, cap_minor, min_charge_minor, included_qty, block_size, percent, tiers (array), tax_inclusive, minimum_term_periods (null = take the product's), cancel_notice_days (null = take the product's), valid_from, valid_to.
  • Casts: amount is a Money over amount_minor + currency.
  • Relationships: product().
  • Helpers:
    • amount: Money.
    • amountFor(float|int|string $qty): Money: qty × unit_rate, or the flat amount when no rate.
    • amountForQuantity(float $qty): Money: amountFor after the included_qty allowance and block_size rounding, clamped to min_charge_minor and cap_minor. Options and addons bill through this.
    • billedUnits(float $qty): float: the post-allowance, post-block unit count amountForQuantity prices.
    • isRelative(): bool: true for the relative model (a percentage of a base).
    • amountOfBase(Money $base): Money: percent of $base, for relative addons.
    • percentLabel(): string: percent without trailing zeros, e.g. "20" or "12.5".
    • recurrence(): RecurrenceRule, isRecurring(): bool.
    • hasSetupFee(): bool, setupFee(): Money, cap(): ?Money.
    • minimumTerm(): int, minimumTermEnd(CarbonImmutable $from): ?CarbonImmutable: the periods a sale on this price is committed for, and when a term starting at $from expires. The column, then the product, then the catalog default, then 0.
    • cancelNoticeDays(): int: notice a cancellation of a sale on this price needs. The column, then the product, then the catalog default, then 0.
    • toDisplay(float $qty = 1): array: JSON-ready row with the price at $qty and the raw pricing knobs.

BillingAccount ​

meteric_billing_accounts: who is billed. Owns subscriptions and invoices, and can have a parent for consolidated billing.

  • Columns: parent_id, owner_type / owner_id (morph), currency, tax_profile (array).
  • Relationships: owner() (morph), parent(), children(), subscriptions(), invoices().
  • Helpers:
    • taxContext(bool $inclusive = false): TaxContext: from the tax_profile.
    • payerScopeIds(): array: self plus children, for consolidated billing.

Subscription ​

meteric_subscriptions: a customer's recurring billing agreement.

  • Columns: account_id, currency, state, anchor_mode, anchor_day, first_period, current_period (Period), trial_end, cancel_at, canceled_at.
  • Relationships: account(), customer() (morph), items(), charges().
  • Helpers:
    • isBillable(): bool, isOnTrial(): bool.
    • nextRenewalAt(): ?CarbonImmutable: earliest item period end.
    • scopeDueForRenewal($q, CarbonImmutable $at): subscriptions whose period has ended.

SubscriptionItem ​

meteric_subscription_items: a billed line within a subscription.

  • Columns: subscription_id, product_id, price_id, label (line title, e.g. a hostname), quantity, billing_mode (nullable override), state, current_period (Period), pending_change (array), resource_type / resource_id (morph).
  • Relationships: subscription(), product(), price(), resource() (morph), addons(), options(), usageRecords().
  • Helpers:
    • lineTitle(): string: the label if set, else the product name. Becomes the invoice line title. A configured LineLabeller overrides it per charge (../usage/extending.md).
    • billingCycle(): ?Period: the current cycle window (query your usage API for this range).
    • billingMode(): BillingMode: item override → price → InAdvance.
    • periodAmount(): Money: amount for one full period at the item's quantity.
    • hasPendingChange(): bool: a deferred plan change is queued.

Charge ​

meteric_charges: money owed. The source of truth.

  • Columns: account_id, subscription_id, state, billing_mode, kind, line_group, amount_minor, currency, covers (Period), quantity, unit_rate, deleted_at.
  • Casts: amount is Money. Soft-deletes (deleted_at).
  • Relationships: account(), subscription(). The invoice link lives on invoice_lines.charge_id, not on the charge.
  • State: pending (billable) -> invoiced (has a line on a non-void invoice) -> settled (that invoice is paid) -> void (discarded).
  • Helpers:
    • money(): Money, isCredit(): bool (negative amount).
    • markInvoiced(): void: flip to invoiced.
    • markSettled(): void: flip invoiced -> settled.
    • revertToPending(): void: return to pending (no-op on a settled or trashed charge).
    • void(): void.
    • scopePending($q): pending charges only.

Invoice ​

meteric_invoices: an immutable billing document.

  • Columns: account_id, number, driver, state, currency, subtotal_minor, tax_minor, total_minor, paid_minor, due_at, paid_at.
  • State: draft (editable) -> open -> paid / partially_paid / void.
  • Relationships: account(), lines(), creditNotes(), payments().
  • Derived: billedCharges(): Collection and billedSubscriptions(): Collection resolve through the lines (invoice_lines.charge_id). The old charges() / subscriptions() names still work but are deprecated.
  • Helpers:
    • total(): Money, outstanding(): Money.
    • isPaid(): bool, isOverdue(): bool.

InvoiceLine ​

meteric_invoice_lines: one line of an invoice, with its own service period.

  • Columns: invoice_id, charge_id (null for manual lines), parent_id (self-FK for a sub-line), kind, title, group, line_group, description, unit, quantity, unit_minor, unit_rate, amount_minor, tax_rate, tax_minor, currency, covers (Period), metadata, sort.
  • Relationships: invoice(), charge(), parent(), children() (sub-lines, ordered by sort).
  • Hierarchy: a parent line's amount_minor is its own only; child lines carry theirs. Invoice totals sum every row.
  • Helpers:
    • gross(): Money: amount + tax.
    • coversLabel(string $format = 'Y-m-d'): ?string: the service period as text, e.g. 2026-06-01 to 2026-06-30.
    • usedSummary(): ?string: for usage lines, the total consumed and unit, e.g. 1500 GB (from the rollup metadata).

Payment / PaymentAllocation ​

meteric_payments and meteric_payment_allocations: inbound money and how it maps to invoices.

  • Payment columns: account_id, amount_minor, currency, reference, received_at.
  • Payment relationships: account(), allocations(), refunds(). Helpers: amount(): Money, refundedMinor(): int, refundable(): Money, allocatedMinor(): int, reversedMinor(): int, isReversed(): bool.
  • PaymentAllocation: payment_id, invoice_id, amount_minor, reverses_allocation_id, reason, recorded_at; relationships payment(), invoice(), reverses(), reversals(); helpers isReversal(): bool, reversedMinor(): int, scope applications(). An application is positive and a reversal of one is negative, so the column sums to what is allocated now. See Reversing a payment.
  • Refund (meteric_refunds): payment_id, credit_note_id, amount_minor, currency, reference, refunded_at, metadata; relationships payment(), creditNote(); helper amount(): Money. See Recording a refund.

MeterDimension ​

meteric_meter_dimensions: a usage axis on a product.

  • Columns: key, unit, aggregation, rate (string), block_size, currency, included_qty, cap_minor, tiers (array).
  • Relationships: product().
  • Helpers:
    • overage(float $used): float: used minus allowance.
    • billedUnits(float $used): float: overage, or block count when block_size is set.
    • amountFor(float $used): Money: billed units × rate, clamped to the cap.

UsageRecord ​

meteric_usage_records: a single reported usage event.

  • Columns: item_id, dimension_id, quantity, occurred_at, charge_id, window (Period).
  • Relationships: item(), dimension().
  • Helpers: scopeUnbilled($q): records with no charge_id.

Addon / ItemOption ​

Mid-cycle item extras.

  • Addon (meteric_addons): quantity, state, group_key, metadata; relationships item(), product(), price().
  • ItemOption (meteric_item_options): key, type (OptionType), value, quantity, min_qty, max_qty; relationships item(), price(); helpers boolValue(): bool, amount(): ?Money (per-period recurring charge), toDisplay(): array (render-ready row for a service page).

ProductAddon ​

The addon catalog: which addon products a base product may be booked with. See Addon catalog.

  • meteric_product_addons: product_id, addon_product_id, group_key, required, active, min_qty, max_qty, sort; relationships product(), addon() (the addon Product); helpers priceFor(Price $term): ?Price (the addon's price on the base term, addon purpose first, then recurring), toDisplay(Price $term, float $qty = 1, ?Money $base = null): ?array (render-ready row, null when unpriced on the term). An inactive row is not listed and cannot be booked.

ProductOption / ProductOptionValue ​

A product's declared configurable options (the catalog). See Catalog options.

  • ProductOption (meteric_product_options): product_id, key, label, type (OptionType), required, active, min_qty, max_qty, sort; relationships product(), values(); helpers activeValues(): Collection (values still on sale), toDisplay(float $qty = 1): array (option meta plus each active value priced at $qty).
  • ProductOptionValue (meteric_product_option_values): option_id, value, label, price_id, active, sort; relationships option(), price(); helpers isBookable(): bool (the value and its option are both active), amountFor(float $qty = 1): ?Money (charge at a quantity, null when free), toDisplay(float $qty = 1): array (render-ready value row with pricing knobs). See Withdrawing from sale.

BillingPeriod ​

meteric_billing_periods: the ledger of fully-billed windows. The GiST EXCLUDE constraint on this table is the database guarantee that no window is billed twice per item and dimension.

  • Columns: item_id, dimension_id, covers (Period).
  • Relationships: item().

TaxRate / TaxRegistration ​

The two tables behind the database tax driver. See Tax.

  • TaxRate (meteric_tax_rates): country, region, category, rate (fraction string), source, effective_from, effective_to. Helper: rateFraction(): float, scope activeOn($q, $date).
  • TaxRegistration (meteric_tax_registrations): country, scheme, number, valid_from, valid_to. Scope activeOn($q, $date).

CreditNote ​

  • CreditNote (meteric_credit_notes): state, number, reason, amount_minor (net), tax_minor (the invoice's blended VAT on that net, or the sum of the lines' tax), currency, metadata; relationships invoice(), lines(), refunds(); helpers amount(): Money, gross(): Money. See Credit notes and refunds.
  • CreditNoteLine (meteric_credit_note_lines): credit_note_id, invoice_line_id (null for a single-amount note), title, net_minor, tax_minor, tax_rate, gross_minor, sort; relationships creditNote(), invoiceLine(); helpers net(): Money, gross(): Money. See Credit note lines.

Released under the MIT License.