import { WalletTransactionType } from '@repo/database'; import { prisma } from './prisma'; import { redis } from '../lib/redis'; import { logger } from '../logger'; const CACHE_KEY = (orgId: string) => `wallet:ok:${orgId}`; export interface CreditWalletParams { organizationId: string; amount: number; type: 'TOP_UP_MANUAL' | 'TOP_UP_PAYMENT' | 'ADJUSTMENT'; actorId?: string; description?: string; } export async function creditWallet(params: CreditWalletParams): Promise<{ newBalance: number }> { const { organizationId, amount, type, actorId, description } = params; const updatedOrg = await prisma.$transaction(async tx => { const org = await tx.organization.update({ where: { id: organizationId }, data: { walletBalance: { increment: amount }, isHardStopped: false, }, select: { walletBalance: true, name: true }, }); await tx.walletTransaction.create({ data: { organizationId, amount, balanceAfter: org.walletBalance, type: type as WalletTransactionType, description, actorId, byok: false, metadata: {}, }, }); await tx.auditLog.create({ data: { action: 'WALLET_CREDIT', actorId, resourceId: organizationId, details: { amount, type, description, newBalance: org.walletBalance }, }, }); return org; }); // Invalidate cache so requireCredits picks up the new balance immediately redis.del(CACHE_KEY(organizationId)).catch(() => {}); logger.info({ organizationId, amount, type, newBalance: updatedOrg.walletBalance }, '[WALLET-API] creditWallet success'); return { newBalance: updatedOrg.walletBalance }; }