File size: 1,943 Bytes
0fd3320
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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 };
}