* Disable auto-top-up for an entity (user or organization).
(entity: AutoTopUpEntity, reason: string)
| 390 | * Disable auto-top-up for an entity (user or organization). |
| 391 | */ |
| 392 | async function disableAutoTopUpForEntity(entity: AutoTopUpEntity, reason: string): Promise<void> { |
| 393 | const message = |
| 394 | failureReasonMessages[reason as KnownFailureReason] ?? failureReasonMessages.unknown_error; |
| 395 | const isUnmappedCode = !(reason in failureReasonMessages); |
| 396 | const entityLabel = |
| 397 | entity.type === 'user' ? `user ${entity.user.id}` : `organization ${entity.organization.id}`; |
| 398 | |
| 399 | sentryLogger('auto-topup', 'info')(`Disabling auto-top-up for ${entityLabel}: ${reason}`, { |
| 400 | ...(isUnmappedCode && { unmapped_code: reason }), |
| 401 | }); |
| 402 | |
| 403 | const ownerColumn = |
| 404 | entity.type === 'user' |
| 405 | ? auto_top_up_configs.owned_by_user_id |
| 406 | : auto_top_up_configs.owned_by_organization_id; |
| 407 | const ownerId = entity.type === 'user' ? entity.user.id : entity.organization.id; |
| 408 | |
| 409 | // Update auto_top_up_configs (shared for both entity types) |
| 410 | await db |
| 411 | .update(auto_top_up_configs) |
| 412 | .set({ disabled_reason: reason }) |
| 413 | .where(eq(ownerColumn, ownerId)); |
| 414 | |
| 415 | if (entity.type === 'user') { |
| 416 | await db |
| 417 | .update(kilocode_users) |
| 418 | .set({ auto_top_up_enabled: false }) |
| 419 | .where(eq(kilocode_users.id, entity.user.id)); |
| 420 | |
| 421 | // Send email notification for users |
| 422 | const user = await findUserById(entity.user.id); |
| 423 | if (user?.google_user_email) { |
| 424 | await sendAutoTopUpFailedEmail(user.google_user_email, { reason: message }); |
| 425 | } |
| 426 | } else { |
| 427 | await db |
| 428 | .update(organizations) |
| 429 | .set({ auto_top_up_enabled: false }) |
| 430 | .where(eq(organizations.id, entity.organization.id)); |
| 431 | |
| 432 | // Send email notification to org owners and billing managers |
| 433 | const members = await getOrganizationMembers(entity.organization.id); |
| 434 | const ownerEmails = members |
| 435 | .filter(m => (m.role === 'owner' || m.role === 'billing_manager') && m.status === 'active') |
| 436 | .map(m => m.email); |
| 437 | for (const email of ownerEmails) { |
| 438 | await sendAutoTopUpFailedEmail(email, { |
| 439 | reason: message, |
| 440 | organizationId: entity.organization.id, |
| 441 | }); |
| 442 | } |
| 443 | } |
| 444 | } |
no test coverage detected