feat(billing) - facilitate top up in ai chat (#21645)
Today, when a trialing user hits their AI usage cap inside the Ask AI chat, ending the trial bounces them to the Stripe billing portal (and, for card-less users, loses their place in the conversation). This PR makes activating a paid plan / topping up credits feel seamless from within the chat: Trial users with a card on file activate their subscription in place, without leaving the app. Trial users without a card are sent to the Stripe payment-method portal and, on return, the trial is ended automatically and they're dropped back into the exact Ask AI thread they came from. Credit-exhaustion and trial banners now reflect whether a payment method exists (Add Credit Card vs Subscribe Now / End Trial Period) and upgrade inline via a confirmation modal instead of redirecting to Settings. Uploading Screen Recording 2026-06-16 at 07.51.12.mov… https://github.com/user-attachments/assets/4ea77273-da63-4b32-b6f1-5ac9e9560651 <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/21645?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+37
@@ -0,0 +1,37 @@
|
||||
import { QueryRunner } from 'typeorm';
|
||||
|
||||
import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-instance-command.decorator';
|
||||
import { FastInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/fast-instance-command.interface';
|
||||
|
||||
@RegisteredInstanceCommand('2.15.0', 1781280240009)
|
||||
export class AddHasPaymentMethodToBillingCustomerFastInstanceCommand
|
||||
implements FastInstanceCommand
|
||||
{
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
const tableExists = await queryRunner.query(
|
||||
`SELECT 1 FROM pg_tables WHERE schemaname = 'core' AND tablename = 'billingCustomer'`,
|
||||
);
|
||||
|
||||
if (tableExists.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."billingCustomer" ADD COLUMN IF NOT EXISTS "hasPaymentMethod" boolean`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
const tableExists = await queryRunner.query(
|
||||
`SELECT 1 FROM pg_tables WHERE schemaname = 'core' AND tablename = 'billingCustomer'`,
|
||||
);
|
||||
|
||||
if (tableExists.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."billingCustomer" DROP COLUMN IF EXISTS "hasPaymentMethod"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
+2
@@ -72,6 +72,7 @@ import { EmailingDomainTenantStatusAndGlobalUniquenessFastInstanceCommand } from
|
||||
import { AddLogicFunctionExecutionModeFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-9/2-9-instance-command-fast-1799000030000-add-logic-function-execution-mode';
|
||||
import { EncryptNonSecretApplicationVariableSlowInstanceCommand } from 'src/database/commands/upgrade-version-command/2-9/2-9-instance-command-slow-1798400000000-encrypt-non-secret-application-variable';
|
||||
import { MigrateAiModelPreferencesSlowInstanceCommand } from 'src/database/commands/upgrade-version-command/2-9/2-9-instance-command-slow-1799000010000-migrate-ai-model-preferences';
|
||||
import { AddHasPaymentMethodToBillingCustomerFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-15/2-15-instance-command-fast-1781280240009-add-has-payment-method-to-billing-customer';
|
||||
|
||||
export const INSTANCE_COMMANDS = [
|
||||
AddViewFieldGroupIdIndexOnViewFieldFastInstanceCommand,
|
||||
@@ -135,6 +136,7 @@ export const INSTANCE_COMMANDS = [
|
||||
EncryptNonSecretApplicationVariableSlowInstanceCommand,
|
||||
DropIsCustomFromObjectAndFieldMetadataFastInstanceCommand,
|
||||
DropEmailingDomainDriverColumnFastInstanceCommand,
|
||||
AddHasPaymentMethodToBillingCustomerFastInstanceCommand,
|
||||
AddEmailingDomainUnsubscribeHostFastInstanceCommand,
|
||||
ViewOverridableEntityFastInstanceCommand,
|
||||
CreateMessageSuppressionCoreTableFastInstanceCommand,
|
||||
|
||||
Reference in New Issue
Block a user