Create billing customer at signup so onboarding rewards are credited (#22633)
## Problem Onboarding credit rewards (install apps, import contacts, invite team) were silently dropped. They credit the workspace balance via `billingCustomer.increment(...)`, but no `billingCustomer` row exists until the plan step (it's created lazily when the first subscription is set up, which is after those steps). So the increment affected 0 rows and the credit was lost. A user installing 3 apps saw only the trial grant, not the expected +1.5 credits. ## Fix Create the Stripe customer + `billingCustomer` row eagerly at signup via a new `BillingCreditService.ensureBillingCustomer`, called from `signUpOnNewWorkspace` after the workspace transaction commits. It is idempotent, guarded by `IS_BILLING_ENABLED`, and non-blocking (failures are logged, not thrown). The later subscription flow reuses this customer (no duplicate Stripe customer), and trial eligibility is unchanged since the customer has no subscriptions yet. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22633?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:
+3
@@ -108,6 +108,9 @@ const createSignInUpServiceForTests = () => {
|
||||
{
|
||||
creditWorkspaceBalance: jest.fn(),
|
||||
} as any,
|
||||
{
|
||||
isBillingEnabled: jest.fn(),
|
||||
} as any,
|
||||
{
|
||||
createQueryRunner: jest.fn(() => queryRunnerMock),
|
||||
} as any,
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
} from 'src/engine/core-modules/app-token/app-token.entity';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { BillingCreditService } from 'src/engine/core-modules/billing/services/billing-credit.service';
|
||||
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
||||
import {
|
||||
AuthException,
|
||||
AuthExceptionCode,
|
||||
@@ -93,6 +94,7 @@ export class SignInUpService {
|
||||
private readonly enterprisePlanService: EnterprisePlanService,
|
||||
private readonly eventLogEmitterService: EventLogEmitterService,
|
||||
private readonly billingCreditService: BillingCreditService,
|
||||
private readonly billingService: BillingService,
|
||||
@InjectDataSource()
|
||||
private readonly dataSource: DataSource,
|
||||
) {}
|
||||
@@ -708,6 +710,14 @@ export class SignInUpService {
|
||||
.createContext({ workspaceId })
|
||||
.insertWorkspaceEvent(WORKSPACE_CREATED_EVENT, {});
|
||||
|
||||
if (this.billingService.isBillingEnabled()) {
|
||||
await this.billingService.ensureBillingCustomer({
|
||||
userEmail: email,
|
||||
workspaceId: workspace.id,
|
||||
workspaceDisplayName: workspace.displayName,
|
||||
});
|
||||
}
|
||||
|
||||
return { user, workspace };
|
||||
} catch (error) {
|
||||
const isSubdomainConflict =
|
||||
|
||||
Reference in New Issue
Block a user