f4abbb2de1
* factory and statergie * chore: use correct method of DI * feat: add onchagne * add logic to HWM stat * add webhook resolver methods to each statergy * move seat tracking + webhooks over to own statergy * Move to factory base approach * move logic to correct class * rename create -> createByTeamId * fix: remove debug `true ||` overrides from IS_STRIPE_ENABLED and IS_TEAM_BILLING_ENABLED Remove accidentally committed debug overrides that short-circuited IS_STRIPE_ENABLED and IS_TEAM_BILLING_ENABLED to always be true, bypassing Stripe credential checks. This would break self-hosted instances without Stripe configured. Identified by cubic (https://cubic.dev) Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
import { getSeatBillingStrategyFactory } from "@calcom/features/ee/billing/di/containers/Billing";
|
|
import logger from "@calcom/lib/logger";
|
|
import { z } from "zod";
|
|
|
|
import type { SWHMap } from "./__handler";
|
|
|
|
const log = logger.getSubLogger({ prefix: ["invoice-paid-team"] });
|
|
|
|
const invoicePaidSchema = z.object({
|
|
object: z.object({
|
|
customer: z.string(),
|
|
subscription: z.string(),
|
|
billing_reason: z.string().nullable(),
|
|
lines: z.object({
|
|
data: z.array(
|
|
z.object({
|
|
subscription_item: z.string(),
|
|
period: z
|
|
.object({
|
|
start: z.number(),
|
|
end: z.number(),
|
|
})
|
|
.optional(),
|
|
})
|
|
),
|
|
}),
|
|
}),
|
|
});
|
|
|
|
const handler = async (data: SWHMap["invoice.paid"]["data"]) => {
|
|
const { object: invoice } = invoicePaidSchema.parse(data);
|
|
const subscriptionId = invoice.subscription;
|
|
|
|
log.debug(`Processing invoice paid webhook for team subscription ${subscriptionId}`, {
|
|
billingReason: invoice.billing_reason,
|
|
customerId: invoice.customer,
|
|
});
|
|
|
|
if (invoice.billing_reason === "subscription_cycle") {
|
|
const periodStart = invoice.lines.data[0]?.period?.start;
|
|
if (!periodStart) {
|
|
log.warn(`Invoice has no period start for subscription ${subscriptionId}, skipping renewal handling`);
|
|
return { success: true };
|
|
}
|
|
|
|
log.info(`Processing renewal invoice for team subscription ${subscriptionId}`);
|
|
const factory = getSeatBillingStrategyFactory();
|
|
const strategy = await factory.createBySubscriptionId(subscriptionId);
|
|
await strategy.onRenewalPaid(subscriptionId, new Date(periodStart * 1000));
|
|
}
|
|
|
|
return { success: true };
|
|
};
|
|
|
|
export default handler;
|