import { SmrtClassOptions } from '@happyvertical/smrt-core'; import { SqlAdapterType } from '@happyvertical/sql'; import { TenantUsageMetricCollection } from '../collections/TenantUsageMetricCollection.js'; import { BillingAdjustmentCollection, ClientCharge, ClientChargeCollection, PricingRule, PricingRuleCollection, SpendingPolicyCollection } from '../models/commercial.js'; import { RecordUsageOptions, SubscriberKind } from '../types.js'; export interface PriceUsageOptions { usageEventId: string; approved?: boolean; at?: Date; } export interface CustomPricingContext { usage: { quantity: number; dimensions: Record; }; rule: PricingRule; terms: Record; } export type CustomPricingStrategy = (context: CustomPricingContext) => number | Promise; export interface CommercialBillingStorage { adapterType: SqlAdapterType; writeStrategy?: 'immediate' | 'manual' | 'none'; } export interface CommercialUsageServiceOptions extends SmrtClassOptions { /** * Required when `db` is an already-resolved database handle, whose public * interface does not expose its adapter/write-back configuration. */ billingStorage?: CommercialBillingStorage; } export declare class UnsupportedCommercialBillingStorageError extends Error { readonly code = "UNSUPPORTED_COMMERCIAL_BILLING_STORAGE"; constructor(storage: CommercialBillingStorage); } export declare class CommercialBillingStorageConfigurationError extends Error { readonly code = "COMMERCIAL_BILLING_STORAGE_CONFIGURATION_REQUIRED"; constructor(message?: string); } export declare function assertCommercialBillingStorageSupported(storage: CommercialBillingStorage): void; export declare class CommercialUsageService { private readonly usage; private readonly rules; private readonly charges; private readonly adjustments; private readonly billingStorage; private readonly customStrategies; constructor(usage: TenantUsageMetricCollection, rules: PricingRuleCollection, charges: ClientChargeCollection, adjustments: BillingAdjustmentCollection, billingStorage: CommercialBillingStorage); static create(options?: CommercialUsageServiceOptions): Promise; registerCustomStrategy(key: string, strategy: CustomPricingStrategy): void; record(options: RecordUsageOptions): Promise; price(options: PriceUsageOptions): Promise; private approveCharge; /** * Append a signed correction to an approved charge. * * @param amount - Signed correction in **integer minor units**, same unit as * the charge (#2401). Negative is legitimate — that is a credit. A * fractional value is rejected rather than silently rounded, because it * almost always means the caller passed major units. */ adjust(chargeId: string, amount: number, reason: string, source?: string, sourceId?: string): Promise; private adjustWithinLock; /** * Price one usage event, in **integer minor units** (#2401). * * The pricing terms stay fractional on purpose — a per-token rate is * routinely a fraction of a cent, and an integer `unitPrice` would truncate * it to zero — so terms are read as *minor units per unit of usage* and only * the result is rounded. This is the single boundary in the package where a * rate meets money, which is what lets `evaluateSpending()` compare sums * against `SpendingPolicy.limitAmount` exactly. * * Replaces the old micro-unit rounding (`Math.round(amount * 1e6) / 1e6`), * which kept six sub-cent digits in a column that is now integral. */ calculateAmount(rule: PricingRule, quantity: number, dimensions?: Record): Promise; } export interface SpendingDecision { allowed: boolean; approvalRequired: boolean; state: 'ok' | 'observed' | 'warned' | 'blocked' | 'approval_required'; /** * Already-spent plus estimated, in **integer minor units** — the same unit as * `SpendingPolicy.limitAmount` it is compared against (#2401). */ projectedAmount: number; matchedPolicyId: string | null; } interface SpendingEvaluationInput { tenantId: string; subscriberKind?: SubscriberKind; subscriberExternalId?: string; projectId?: string; serviceKey?: string; metricKey: string; /** Estimated cost of the pending call, in integer minor units (#2401). */ estimatedAmount: number; currency: string; at?: Date; } export declare class SpendingPolicyEvaluator { private readonly policies; private readonly charges; private readonly adjustments; constructor(policies: SpendingPolicyCollection, charges: ClientChargeCollection, adjustments: BillingAdjustmentCollection); static create(options?: SmrtClassOptions): Promise; evaluate(input: SpendingEvaluationInput): Promise; private evaluatePolicy; } export {}; //# sourceMappingURL=commercial.d.ts.map