Enhance ledger operations and referral lifecycle
Add traceable ledger filtering and permanent referral codes so operators can investigate credit activity without weakening immutable accounting guarantees.
This commit is contained in:
@@ -160,6 +160,11 @@ function cursorQuery<T extends CursorQuery>(value?: string | T): CursorQuery | T
|
||||
|
||||
type CursorQuery = { cursor?: string };
|
||||
|
||||
function ledgerQuery(value?: string | LedgerQuery): CursorQuery | LedgerQuery {
|
||||
if (typeof value === "string") return { cursor: value };
|
||||
return value ? { ...value, referenceId: value.referenceId?.trim() } : {};
|
||||
}
|
||||
|
||||
export const adminApi = {
|
||||
session: () => request<SessionResponse>("/auth/session"),
|
||||
|
||||
@@ -195,12 +200,12 @@ export const adminApi = {
|
||||
|
||||
latestLedger: (value?: string | LedgerQuery) =>
|
||||
request<PageResult<LedgerEntry>>(
|
||||
`/credits/ledger${encodeQuery(cursorQuery(value))}`,
|
||||
`/credits/ledger${encodeQuery(ledgerQuery(value))}`,
|
||||
),
|
||||
|
||||
ledger: (userId: string, value?: string | LedgerQuery) =>
|
||||
request<PageResult<LedgerEntry>>(
|
||||
`/users/${encodeURIComponent(userId)}/ledger${encodeQuery(cursorQuery(value))}`,
|
||||
`/users/${encodeURIComponent(userId)}/ledger${encodeQuery(ledgerQuery(value))}`,
|
||||
),
|
||||
|
||||
grantCredits: (payload: CreditGrantRequest) =>
|
||||
|
||||
@@ -27,8 +27,12 @@ export interface UsersQuery extends CursorPageQuery {
|
||||
status?: UserSummary["status"];
|
||||
}
|
||||
|
||||
export interface LedgerQuery extends CursorPageQuery {
|
||||
type?: LedgerEntryType;
|
||||
export interface LedgerQuery extends Omit<CursorPageQuery, "sort"> {
|
||||
type?: LedgerAction;
|
||||
entryType?: LedgerEntryType;
|
||||
usageType?: UsageType;
|
||||
referenceId?: string;
|
||||
sort?: "createdAt" | "amount";
|
||||
}
|
||||
|
||||
export interface AuditQuery extends CursorPageQuery {
|
||||
@@ -219,23 +223,61 @@ export interface PageResult<T> {
|
||||
nextCursor?: string;
|
||||
}
|
||||
|
||||
export type LedgerEntryType =
|
||||
export type LedgerAction =
|
||||
| "grant"
|
||||
| "reserve"
|
||||
| "settle"
|
||||
| "refund"
|
||||
| "adjustment";
|
||||
| "refund";
|
||||
|
||||
export type LedgerEntryType =
|
||||
| "SIGNUP_TRIAL"
|
||||
| "MANUAL_GRANT"
|
||||
| "USAGE_RESERVE"
|
||||
| "USAGE_SETTLE"
|
||||
| "USAGE_RELEASE"
|
||||
| "USAGE_REFUND"
|
||||
| "REFERRAL_INVITER"
|
||||
| "REFERRAL_INVITEE"
|
||||
| "STOREKIT_PURCHASE"
|
||||
| "SUBSCRIPTION_GRANT";
|
||||
|
||||
export type UsageType = "polish" | "asr" | "ai" | "agent" | "hotword";
|
||||
|
||||
export type LedgerEntryDetails =
|
||||
| {
|
||||
kind: "manualGrant";
|
||||
reason?: string;
|
||||
operatorName?: string;
|
||||
}
|
||||
| {
|
||||
kind: "storeKit";
|
||||
productId?: string;
|
||||
transactionId?: string;
|
||||
originalTransactionId?: string;
|
||||
environment?: string;
|
||||
purchasedAt?: string;
|
||||
}
|
||||
| {
|
||||
kind: "referral";
|
||||
role?: string;
|
||||
relatedUserId?: string;
|
||||
}
|
||||
| {
|
||||
kind: "usage";
|
||||
reservationId?: string;
|
||||
};
|
||||
|
||||
export interface LedgerEntry {
|
||||
entryId: string;
|
||||
userId: string;
|
||||
type: LedgerEntryType;
|
||||
type: LedgerAction;
|
||||
entryType: LedgerEntryType;
|
||||
amount: number;
|
||||
balanceAfter: number;
|
||||
reasonCode: string;
|
||||
usageType?: UsageType;
|
||||
referenceId?: string;
|
||||
details?: LedgerEntryDetails;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user