Billing - Fix inactivity (#17703)

- Add suspendedAt column on workspace table
- Update suspendedAt field when workspace suspended or re-activated
- Compute inactivity on suspendedAt



Tested : 
- Cancel subscription
- Cancel subscription + Subscribe again
- Cleaning command
This commit is contained in:
Etienne
2026-02-04 11:17:27 +01:00
committed by GitHub
parent aa06dab920
commit 50ef231704
4 changed files with 38 additions and 30 deletions
@@ -3,10 +3,10 @@
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { msg } from '@lingui/core/macro';
import { isDefined } from 'twenty-shared/utils';
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
import { In, Repository } from 'typeorm';
import { msg } from '@lingui/core/macro';
import type Stripe from 'stripe';
@@ -145,6 +145,7 @@ export class BillingWebhookSubscriptionService {
if (workspace.activationStatus === WorkspaceActivationStatus.ACTIVE) {
await this.workspaceRepository.update(workspaceId, {
activationStatus: WorkspaceActivationStatus.SUSPENDED,
suspendedAt: new Date(),
});
} else if (
workspace.activationStatus ===
@@ -157,6 +158,7 @@ export class BillingWebhookSubscriptionService {
) {
await this.workspaceRepository.update(workspaceId, {
activationStatus: WorkspaceActivationStatus.ACTIVE,
suspendedAt: null,
});
await this.messageQueueService.add<CleanWorkspaceDeletionWarningUserVarsJobData>(
@@ -31,7 +31,6 @@ import { PostgresCredentialsEntity } from 'src/engine/core-modules/postgres-cred
import { PublicDomainEntity } from 'src/engine/core-modules/public-domain/public-domain.entity';
import { WorkspaceSSOIdentityProviderEntity } from 'src/engine/core-modules/sso/workspace-sso-identity-provider.entity';
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { WebhookEntity } from 'src/engine/metadata-modules/webhook/entities/webhook.entity';
import { AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity';
import {
DEFAULT_FAST_MODEL,
@@ -51,6 +50,7 @@ import { ViewSortDTO } from 'src/engine/metadata-modules/view-sort/dtos/view-sor
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
import { ViewDTO } from 'src/engine/metadata-modules/view/dtos/view.dto';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { WebhookEntity } from 'src/engine/metadata-modules/webhook/entities/webhook.entity';
registerEnumType(WorkspaceActivationStatus, {
name: 'WorkspaceActivationStatus',
@@ -159,6 +159,9 @@ export class WorkspaceEntity {
@Index('IDX_WORKSPACE_ACTIVATION_STATUS')
activationStatus: WorkspaceActivationStatus;
@Column({ type: 'timestamptz', nullable: true })
suspendedAt: Date | null;
@OneToMany(
() => PostgresCredentialsEntity,
(postgresCredentials) => postgresCredentials.workspace,