From 6682d4eb02c6c2cde27db4dc33742dea185d6b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 18 Dec 2025 08:38:15 +0100 Subject: [PATCH] fix: bill all events in BillingUsageService.billUsage() instead of only the first one (#16650) ## Summary Fixes a bug where `BillingUsageService.billUsage()` only sent the first event from the `billingEvents` array to Stripe, silently ignoring all subsequent events. ## Bug Description The `billUsage()` method accepts an array of `BillingUsageEvent[]` but was only processing `billingEvents[0]`, causing: - Customers to be undercharged for their usage - Revenue loss due to unbilled events - Incorrect usage tracking ## Fix Changed the implementation to use `Promise.all()` to send all events in the array concurrently to Stripe. ## Before ```typescript await this.stripeBillingMeterEventService.sendBillingMeterEvent({ eventName: billingEvents[0].eventName, // Only first event value: billingEvents[0].value, stripeCustomerId: workspaceStripeCustomer.stripeCustomerId, dimensions: billingEvents[0].dimensions, }); ``` ## After ```typescript await Promise.all( billingEvents.map((event) => this.stripeBillingMeterEventService.sendBillingMeterEvent({ eventName: event.eventName, value: event.value, stripeCustomerId: workspaceStripeCustomer.stripeCustomerId, dimensions: event.dimensions, }), ), ); ``` --- .../billing/services/billing-usage.service.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts b/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts index ffd79cea6f..4b78de2a15 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/services/billing-usage.service.ts @@ -67,12 +67,16 @@ export class BillingUsageService { } try { - await this.stripeBillingMeterEventService.sendBillingMeterEvent({ - eventName: billingEvents[0].eventName, - value: billingEvents[0].value, - stripeCustomerId: workspaceStripeCustomer.stripeCustomerId, - dimensions: billingEvents[0].dimensions, - }); + await Promise.all( + billingEvents.map((event) => + this.stripeBillingMeterEventService.sendBillingMeterEvent({ + eventName: event.eventName, + value: event.value, + stripeCustomerId: workspaceStripeCustomer.stripeCustomerId, + dimensions: event.dimensions, + }), + ), + ); } catch (error) { throw new BillingException( `Failed to send billing meter events to Stripe: ${error}`,