Add NATS account-balance SoT and statement review for customers, CS, and sales
Some checks are pending
offline / test (push) Waiting to run

Internal billing now uses verae.billing.* request-reply and pubs. zappier-account-balance tracks prepaid, credits, usage, and payments. Portal, admin, CS, and sales all review the same statement. Independent Forgejo repos stay split via push-module-repos.
This commit is contained in:
George Lambert 2026-09-11 15:35:37 -04:00
parent a1a5b957fd
commit ac38676645
135 changed files with 3078 additions and 130 deletions

View file

@ -0,0 +1,38 @@
import { CreditAdjustment } from './credits';
import { Invoice } from './invoicing';
import { UsageEntry } from './usage';
export function composeStatement(args: {
customerId: string;
prepaidCents: number;
credits: CreditAdjustment[];
usage: UsageEntry[];
invoices: Invoice[];
}) {
const payments = args.invoices
.filter((i) => i.customerId === args.customerId && (i.status === 'paid' || i.status === 'issued'))
.map((i) => ({
id: i.id,
customerId: i.customerId,
cents: i.billableCents,
kind: i.status === 'paid' ? 'invoice-paid' : 'invoice-issued',
reason: i.period,
at: new Date(i.paidAtMs || i.issuedAtMs || Date.now()).toISOString(),
}));
return {
customerId: args.customerId,
prepaidCents: args.prepaidCents,
credits: args.credits.filter((c) => c.customerId === args.customerId),
usage: args.usage
.filter((u) => u.customerId === args.customerId)
.slice(-50)
.reverse()
.map((u) => ({
customerId: u.customerId,
endpointId: u.endpointId,
cents: u.cents,
at: u.timestamp.toISOString(),
})),
payments,
};
}