master-zapier-plan-draft/packages/zappier/src/ledger.ts
George Lambert 9cc0018708
Some checks are pending
offline / test (push) Waiting to run
Add customer names on the ledger, staff session login, and exclusive jobs.events.
Account-balance stores display names and looks up by name. Edge writes
names on customer create/edit; staff UIs join from edge when needed.
New verae-staff-session issues a host cookie; department HTML redirects
when STAFF_AUTH=1. JOBS_EVENTS_EXCLUSIVE lets jobs-events own the durable
consumer. Catalog index is cards; disabled fleet machines are grey.
2026-09-11 18:11:21 -04:00

65 lines
2 KiB
TypeScript

/**
* Prepaid mutations. Account-balance is the writer when NATS or HTTP books exist.
* Tests (no NATS_URL, no ACCOUNT_BALANCE_URL) keep a local cache only.
*/
import { natsAdjust, natsPublish, natsStatement } from './billing-nats';
import type { AccessPlane } from './billing-nats';
export type PrepaidRow = {
customerId: string;
veraeUserId?: string;
cents: number;
reason: string;
agent: string;
kind?: string;
prepaidCents?: number;
};
function booksUrl(): string {
return (process.env.ACCOUNT_BALANCE_URL || '').replace(/\/$/, '');
}
export function booksConfigured(): boolean {
return Boolean(process.env.NATS_URL || booksUrl());
}
export async function ledgerAdjust(row: PrepaidRow, plane: AccessPlane): Promise<PrepaidRow | null> {
const viaNats = await natsAdjust(row, plane);
if (viaNats && typeof viaNats === 'object' && viaNats !== null && 'prepaidCents' in viaNats) {
return viaNats as PrepaidRow;
}
const base = booksUrl();
if (!base) return null;
const r = await fetch(`${base}/adjust`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(row),
});
if (!r.ok) return null;
return (await r.json()) as PrepaidRow;
}
export async function ledgerPutCustomer(row: {
customerId: string;
name?: string;
veraeUserId?: string;
}): Promise<void> {
natsPublish('verae.billing.customer.put', row, 'staff');
const base = booksUrl();
if (!base) return;
await fetch(`${base}/customer`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(row),
}).catch(() => {});
}
export async function ledgerStatement(customerId: string, plane: AccessPlane, veraeUserId?: string) {
const nats = await natsStatement(customerId, plane, veraeUserId);
if (nats) return nats;
const base = booksUrl();
if (!base) return null;
const r = await fetch(`${base}/statement/${encodeURIComponent(customerId)}`);
if (!r.ok) return null;
return r.json();
}