MCPcopy Index your code
hub / github.com/CodebuffAI/codebuff / migrateUnusedCredits

Function migrateUnusedCredits

packages/billing/src/subscription.ts:717–817  ·  view source on GitHub ↗
(params: {
  tx: DbTransaction
  userId: string
  subscriptionId: string
  expiresAt: Date
  logger: Logger
})

Source from the content-addressed store, hash-verified

715 * balance zeroed.
716 */
717export async function migrateUnusedCredits(params: {
718 tx: DbTransaction
719 userId: string
720 subscriptionId: string
721 expiresAt: Date
722 logger: Logger
723}): Promise<void> {
724 const { tx, userId, subscriptionId, expiresAt, logger } = params
725 const now = new Date()
726
727 const unusedGrants = await tx
728 .select()
729 .from(schema.creditLedger)
730 .where(
731 and(
732 eq(schema.creditLedger.user_id, userId),
733 gt(schema.creditLedger.balance, 0),
734 ne(schema.creditLedger.type, 'subscription'),
735 isNull(schema.creditLedger.org_id),
736 gt(schema.creditLedger.expires_at, now),
737 lte(schema.creditLedger.expires_at, expiresAt),
738 ),
739 )
740
741 const totalUnused = unusedGrants.reduce(
742 (sum, grant) => sum + grant.balance,
743 0,
744 )
745
746 // Deterministic ID ensures idempotency — duplicate webhook deliveries
747 // will hit onConflictDoNothing and the handleSubscribe caller checks
748 // for this operation_id before running.
749 const operationId = `subscribe-migrate-${subscriptionId}`
750
751 if (totalUnused === 0) {
752 // Still insert the marker for idempotency so handleSubscribe's check
753 // short-circuits on duplicate webhook deliveries.
754 await tx
755 .insert(schema.creditLedger)
756 .values({
757 operation_id: operationId,
758 user_id: userId,
759 type: 'free',
760 principal: 0,
761 balance: 0,
762 priority: GRANT_PRIORITIES.free,
763 expires_at: expiresAt,
764 description: 'Migrated credits from subscription transition',
765 })
766 .onConflictDoNothing({ target: schema.creditLedger.operation_id })
767 logger.debug({ userId }, 'No unused credits to migrate')
768 return
769 }
770
771 // Zero out old grants
772 for (const grant of unusedGrants) {
773 await tx
774 .update(schema.creditLedger)

Callers 2

handleSubscribeFunction · 0.85

Calls 4

trackEventFunction · 0.90
fromMethod · 0.80
insertMethod · 0.80
setMethod · 0.80

Tested by

no test coverage detected