Files
cal.diy/packages/features/ee/billing/service/teams/TeamBillingServiceFactory.ts
T
f4abbb2de1 feat: refactor billing to strategy implemention (#27828)
* 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>
2026-02-10 13:11:36 -03:00

57 lines
2.4 KiB
TypeScript

import type { IBillingRepository } from "../../repository/billing/IBillingRepository";
import type { ITeamBillingDataRepository } from "../../repository/teamBillingData/ITeamBillingDataRepository";
import type { IBillingProviderService } from "../billingProvider/IBillingProviderService";
import type { SeatBillingStrategyFactory } from "../seatBillingStrategy/SeatBillingStrategyFactory";
import type { ITeamBillingService, TeamBillingInput } from "./ITeamBillingService";
import { StubTeamBillingService } from "./StubTeamBillingService";
import { TeamBillingService } from "./TeamBillingService";
// Export the interface for type safety in DI modules
export interface ITeamBillingServiceFactoryDeps {
billingProviderService: IBillingProviderService;
teamBillingDataRepository: ITeamBillingDataRepository;
billingRepositoryFactory: (isOrganization: boolean) => IBillingRepository;
isTeamBillingEnabled: boolean;
seatBillingStrategyFactory: SeatBillingStrategyFactory;
}
export class TeamBillingServiceFactory {
// Store dependencies as single object (IOctopus pattern)
constructor(private readonly deps: ITeamBillingServiceFactoryDeps) {}
/** Initialize a single team billing */
init(team: TeamBillingInput): ITeamBillingService {
if (!this.deps.isTeamBillingEnabled) {
return new StubTeamBillingService(team);
}
// Call the factory function with runtime context to get the correct repository
const billingRepository = this.deps.billingRepositoryFactory(team.isOrganization);
return new TeamBillingService({
team,
billingProviderService: this.deps.billingProviderService,
teamBillingDataRepository: this.deps.teamBillingDataRepository,
billingRepository,
seatBillingStrategyFactory: this.deps.seatBillingStrategyFactory,
});
}
/** Initialize multiple team billings at once for bulk operations */
initMany(teams: TeamBillingInput[]) {
return teams.map((team) => this.init(team));
}
/** Fetch and initialize a single team billing in one go */
async findAndInit(teamId: number) {
const team = await this.deps.teamBillingDataRepository.find(teamId);
return this.init(team);
}
/** Fetch and initialize multiple team billings in one go */
async findAndInitMany(teamIds: number[]) {
const teams = await this.deps.teamBillingDataRepository.findMany(teamIds);
return this.initMany(teams);
}
}