refactor: improve invoice.upcoming logging and add strategyName to billing strategies (#28143)
- Add strategyName property to ISeatBillingStrategy interface and all implementations - Log which strategy handled the invoice.upcoming webhook (not just whether it applied) - Always log strategy result (not just when applied=true) for better observability - Rename highWaterMarkApplied to strategyApplied since applied covers multiple strategies Co-Authored-By: unknown <> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
6 files changed
+21
-13
No files matched your search
@@ -1,6 +1,5 @@
|
||||
import { getSeatBillingStrategyFactory } from "@calcom/features/ee/billing/di/containers/Billing";
|
||||
import logger from "@calcom/lib/logger";
|
||||
|
||||
import type { SWHMap } from "./__handler";
|
||||
|
||||
type Data = SWHMap["invoice.upcoming"]["data"];
|
||||
@@ -29,11 +28,13 @@ const handler = async (data: Data) => {
|
||||
const strategy = await factory.createBySubscriptionId(subscriptionId);
|
||||
const { applied } = await strategy.onInvoiceUpcoming(subscriptionId);
|
||||
|
||||
if (applied) {
|
||||
log.info("Strategy applied invoice.upcoming handling", { subscriptionId });
|
||||
}
|
||||
log.info("invoice.upcoming handled", {
|
||||
subscriptionId,
|
||||
strategy: strategy.strategyName,
|
||||
applied,
|
||||
});
|
||||
|
||||
return { success: true, highWaterMarkApplied: applied };
|
||||
return { success: true, strategyApplied: applied };
|
||||
} catch (error) {
|
||||
log.error("Failed to process invoice.upcoming", { subscriptionId, error });
|
||||
return { success: false, error: String(error) };
|
||||
|
||||
+3
-2
@@ -1,10 +1,9 @@
|
||||
import logger from "@calcom/lib/logger";
|
||||
|
||||
import type { ActiveUserBillingService } from "../../active-user/services/ActiveUserBillingService";
|
||||
import type { ITeamBillingDataRepository } from "../../repository/teamBillingData/ITeamBillingDataRepository";
|
||||
import type { IBillingProviderService } from "../billingProvider/IBillingProviderService";
|
||||
import { BaseSeatBillingStrategy } from "./ISeatBillingStrategy";
|
||||
import type { SeatChangeContext } from "./ISeatBillingStrategy";
|
||||
import { BaseSeatBillingStrategy } from "./ISeatBillingStrategy";
|
||||
|
||||
const log = logger.getSubLogger({ prefix: ["ActiveUserBillingStrategy"] });
|
||||
|
||||
@@ -15,6 +14,8 @@ export interface IActiveUserBillingStrategyDeps {
|
||||
}
|
||||
|
||||
export class ActiveUserBillingStrategy extends BaseSeatBillingStrategy {
|
||||
readonly strategyName = "ActiveUserBilling";
|
||||
|
||||
constructor(private readonly deps: IActiveUserBillingStrategyDeps) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import logger from "@calcom/lib/logger";
|
||||
|
||||
import type { HighWaterMarkService } from "../highWaterMark/HighWaterMarkService";
|
||||
import type { HighWaterMarkRepository } from "../../repository/highWaterMark/HighWaterMarkRepository";
|
||||
import { BaseSeatBillingStrategy } from "./ISeatBillingStrategy";
|
||||
import type { HighWaterMarkService } from "../highWaterMark/HighWaterMarkService";
|
||||
import type { SeatChangeContext } from "./ISeatBillingStrategy";
|
||||
import { BaseSeatBillingStrategy } from "./ISeatBillingStrategy";
|
||||
|
||||
const log = logger.getSubLogger({ prefix: ["HighWaterMarkStrategy"] });
|
||||
|
||||
@@ -13,6 +12,8 @@ export interface IHighWaterMarkStrategyDeps {
|
||||
}
|
||||
|
||||
export class HighWaterMarkStrategy extends BaseSeatBillingStrategy {
|
||||
readonly strategyName = "HighWaterMark";
|
||||
|
||||
constructor(private readonly deps: IHighWaterMarkStrategyDeps) {
|
||||
super();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ export interface StripeInvoiceData {
|
||||
}
|
||||
|
||||
export interface ISeatBillingStrategy {
|
||||
readonly strategyName: string;
|
||||
onSeatChange(context: SeatChangeContext): Promise<void>;
|
||||
onInvoiceUpcoming(subscriptionId: string): Promise<{ applied: boolean }>;
|
||||
onRenewalPaid(subscriptionId: string, periodStart: Date): Promise<{ reset: boolean }>;
|
||||
@@ -25,6 +26,7 @@ export interface ISeatBillingStrategy {
|
||||
}
|
||||
|
||||
export abstract class BaseSeatBillingStrategy implements ISeatBillingStrategy {
|
||||
abstract readonly strategyName: string;
|
||||
abstract onSeatChange(context: SeatChangeContext): Promise<void>;
|
||||
|
||||
async onInvoiceUpcoming(_subscriptionId: string): Promise<{ applied: boolean }> {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import type { IBillingProviderService } from "../billingProvider/IBillingProviderService";
|
||||
import { BaseSeatBillingStrategy } from "./ISeatBillingStrategy";
|
||||
import type { SeatChangeContext } from "./ISeatBillingStrategy";
|
||||
import { BaseSeatBillingStrategy } from "./ISeatBillingStrategy";
|
||||
|
||||
export class ImmediateUpdateStrategy extends BaseSeatBillingStrategy {
|
||||
readonly strategyName = "ImmediateUpdate";
|
||||
|
||||
constructor(private readonly billingProviderService: IBillingProviderService) {
|
||||
super();
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,9 +1,8 @@
|
||||
import logger from "@calcom/lib/logger";
|
||||
|
||||
import { findMonthlyProrationLineItem } from "../../lib/proration-utils";
|
||||
import type { MonthlyProrationService } from "../proration/MonthlyProrationService";
|
||||
import { BaseSeatBillingStrategy } from "./ISeatBillingStrategy";
|
||||
import type { SeatChangeContext, StripeInvoiceData } from "./ISeatBillingStrategy";
|
||||
import { BaseSeatBillingStrategy } from "./ISeatBillingStrategy";
|
||||
|
||||
const log = logger.getSubLogger({ prefix: ["MonthlyProrationStrategy"] });
|
||||
|
||||
@@ -12,6 +11,8 @@ export interface IMonthlyProrationStrategyDeps {
|
||||
}
|
||||
|
||||
export class MonthlyProrationStrategy extends BaseSeatBillingStrategy {
|
||||
readonly strategyName = "MonthlyProration";
|
||||
|
||||
constructor(private readonly deps: IMonthlyProrationStrategyDeps) {
|
||||
super();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user