@@ -21,6 +21,10 @@ import type { GrantType } from '@codebuff/internal/db/schema'
2121
2222import type { CodebuffTransaction } from '@codebuff/internal/db'
2323
24+ const getBillingDbClient = (
25+ dbOverride ?: BillingDbConnection ,
26+ ) : BillingDbConnection => ( dbOverride ?? db ) as BillingDbConnection
27+
2428/**
2529 * Dependencies for getPreviousFreeGrantAmount (for testing)
2630 */
@@ -38,12 +42,11 @@ export async function getPreviousFreeGrantAmount(params: {
3842 deps ?: GetPreviousFreeGrantAmountDeps
3943} ) : Promise < number > {
4044 const { userId, logger, deps = { } } = params
41- // Cast to BillingDbConnection to allow either real db or mock to be used
42- const dbClient = ( deps . db ?? db ) as BillingDbConnection
45+ const dbClient = getBillingDbClient ( deps . db )
4346
4447 const now = new Date ( )
4548 const lastExpiredFreeGrant = await dbClient
46- . select ( {
49+ . select < { principal : number } > ( {
4750 principal : schema . creditLedger . principal ,
4851 } )
4952 . from ( schema . creditLedger )
@@ -55,7 +58,7 @@ export async function getPreviousFreeGrantAmount(params: {
5558 ) ,
5659 )
5760 . orderBy ( desc ( schema . creditLedger . expires_at ) ) // Most recent expiry first
58- . limit ( 1 ) as { principal : number } [ ]
61+ . limit ( 1 )
5962
6063 if ( lastExpiredFreeGrant . length > 0 ) {
6164 // TODO: remove this once it's past May 22nd, after all users have been migrated over
@@ -93,12 +96,11 @@ export async function calculateTotalReferralBonus(params: {
9396 deps ?: CalculateTotalReferralBonusDeps
9497} ) : Promise < number > {
9598 const { userId, logger, deps = { } } = params
96- // Cast to BillingDbConnection to allow either real db or mock to be used
97- const dbClient = ( deps . db ?? db ) as BillingDbConnection
99+ const dbClient = getBillingDbClient ( deps . db )
98100
99101 try {
100102 const result = await dbClient
101- . select ( {
103+ . select < { totalCredits : string } > ( {
102104 totalCredits : sql < string > `COALESCE(SUM(${ schema . referral . credits } ), 0)` ,
103105 } )
104106 . from ( schema . referral )
@@ -107,7 +109,7 @@ export async function calculateTotalReferralBonus(params: {
107109 eq ( schema . referral . referrer_id , userId ) ,
108110 eq ( schema . referral . referred_id , userId ) ,
109111 ) ,
110- ) as { totalCredits : string } [ ]
112+ )
111113
112114 const totalBonus = parseInt ( result [ 0 ] ?. totalCredits ?? '0' )
113115 logger . debug ( { userId, totalBonus } , 'Calculated total referral bonus.' )
@@ -428,10 +430,10 @@ export async function triggerMonthlyResetAndGrant(params: {
428430 // Calculate new reset date
429431 const newResetDate = getNextQuotaReset ( currentResetDate )
430432
431- // Calculate grant amounts separately
433+ // Calculate grant amounts separately - pass tx to maintain transaction consistency
432434 const [ freeGrantAmount , referralBonus ] = await Promise . all ( [
433- getPreviousFreeGrantAmount ( { userId, logger } ) ,
434- calculateTotalReferralBonus ( { userId, logger } ) ,
435+ getPreviousFreeGrantAmount ( { userId, logger, deps : { db : tx as BillingDbConnection } } ) ,
436+ calculateTotalReferralBonus ( { userId, logger, deps : { db : tx as BillingDbConnection } } ) ,
435437 ] )
436438
437439 // Generate a deterministic operation ID based on userId and reset date to minute precision
0 commit comments