mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
Refactor metered plan handling and add new telemetry plan
This commit is contained in:
@@ -115,7 +115,7 @@ export class BillingService extends BaseService {
|
||||
public async subscribeToMeteredPlan(data: {
|
||||
projectId: ObjectID;
|
||||
customerId: string;
|
||||
serverMeteredPlans: Array<typeof ServerMeteredPlan> ;
|
||||
serverMeteredPlans: Array<ServerMeteredPlan> ;
|
||||
trialDate: Date | null;
|
||||
defaultPaymentMethodId?: string | undefined;
|
||||
promoCode?: string | undefined;
|
||||
@@ -127,9 +127,9 @@ export class BillingService extends BaseService {
|
||||
customer: data.customerId,
|
||||
|
||||
items: data.serverMeteredPlans.map(
|
||||
(item: typeof ServerMeteredPlan) => {
|
||||
(item: ServerMeteredPlan) => {
|
||||
return {
|
||||
price: item.getMeteredPlan()?.getPriceId(),
|
||||
price: item.getPriceId(),
|
||||
};
|
||||
}
|
||||
),
|
||||
@@ -195,7 +195,7 @@ export class BillingService extends BaseService {
|
||||
public async subscribeToPlan(data: {
|
||||
projectId: ObjectID;
|
||||
customerId: string;
|
||||
serverMeteredPlans: Array<typeof ServerMeteredPlan>;
|
||||
serverMeteredPlans: Array<ServerMeteredPlan>;
|
||||
plan: SubscriptionPlan;
|
||||
quantity: number;
|
||||
isYearly: boolean;
|
||||
@@ -313,7 +313,7 @@ export class BillingService extends BaseService {
|
||||
|
||||
public async addOrUpdateMeteredPricingOnSubscription(
|
||||
subscriptionId: string,
|
||||
meteredPlan: MeteredPlan,
|
||||
serverMeteredPlan: ServerMeteredPlan,
|
||||
quantity: number
|
||||
): Promise<void> {
|
||||
if (!this.isBillingEnabled()) {
|
||||
@@ -337,7 +337,7 @@ export class BillingService extends BaseService {
|
||||
|
||||
const pricingExists: boolean = subscription.items.data.some(
|
||||
(item: SubscriptionItem) => {
|
||||
return item.price?.id === meteredPlan.getPriceId();
|
||||
return item.price?.id === serverMeteredPlan.getPriceId();
|
||||
}
|
||||
);
|
||||
|
||||
@@ -345,7 +345,7 @@ export class BillingService extends BaseService {
|
||||
// update the quantity.
|
||||
const subscriptionItemId: string | undefined =
|
||||
subscription.items.data.find((item: SubscriptionItem) => {
|
||||
return item.price?.id === meteredPlan.getPriceId();
|
||||
return item.price?.id === serverMeteredPlan.getPriceId();
|
||||
})?.id;
|
||||
|
||||
if (!subscriptionItemId) {
|
||||
@@ -366,7 +366,7 @@ export class BillingService extends BaseService {
|
||||
const subscriptionItem: SubscriptionItem =
|
||||
await this.stripe.subscriptionItems.create({
|
||||
subscription: subscriptionId,
|
||||
price: meteredPlan.getPriceId(),
|
||||
price: serverMeteredPlan.getPriceId(),
|
||||
});
|
||||
|
||||
// use stripe usage based api to update the quantity.
|
||||
@@ -470,7 +470,7 @@ export class BillingService extends BaseService {
|
||||
projectId: ObjectID;
|
||||
subscriptionId: string;
|
||||
meteredSubscriptionId: string;
|
||||
serverMeteredPlans: Array<typeof ServerMeteredPlan>;
|
||||
serverMeteredPlans: Array<ServerMeteredPlan>;
|
||||
newPlan: SubscriptionPlan;
|
||||
quantity: number;
|
||||
isYearly: boolean;
|
||||
|
||||
@@ -641,11 +641,11 @@ describe('BillingService', () => {
|
||||
it('should throw if billing is not enabled', async () => {
|
||||
const subscriptionItem: SubscriptionItem | undefined =
|
||||
mockSubscription.items.data[0];
|
||||
const meteredPlan: MeteredPlan = new MeteredPlan(
|
||||
subscriptionItem?.price?.id || '',
|
||||
100,
|
||||
'unit'
|
||||
);
|
||||
const meteredPlan: MeteredPlan = new MeteredPlan({
|
||||
priceId: subscriptionItem?.price?.id || '',
|
||||
pricePerUnitInUSD: 100,
|
||||
unitName: 'unit'
|
||||
});
|
||||
|
||||
billingService = mockIsBillingEnabled(false);
|
||||
|
||||
@@ -661,11 +661,11 @@ describe('BillingService', () => {
|
||||
it('should successfully add metered pricing to a subscription', async () => {
|
||||
const subscriptionItem: SubscriptionItem | undefined =
|
||||
mockSubscription.items.data[0];
|
||||
const meteredPlan: MeteredPlan = new MeteredPlan(
|
||||
subscriptionItem?.price?.id || '',
|
||||
100,
|
||||
'unit'
|
||||
);
|
||||
const meteredPlan: MeteredPlan = new MeteredPlan({
|
||||
priceId: subscriptionItem?.price?.id || '',
|
||||
pricePerUnitInUSD: 100,
|
||||
unitName: 'unit'
|
||||
});
|
||||
|
||||
mockSubscription.items.data = [];
|
||||
|
||||
@@ -702,11 +702,11 @@ describe('BillingService', () => {
|
||||
it('should successfully update existing metered pricing on a subscription', async () => {
|
||||
const subscriptionItem: SubscriptionItem | undefined =
|
||||
mockSubscription.items.data[0];
|
||||
const meteredPlan: MeteredPlan = new MeteredPlan(
|
||||
subscriptionItem?.price?.id || '',
|
||||
100,
|
||||
'unit'
|
||||
);
|
||||
const meteredPlan: MeteredPlan = new MeteredPlan({
|
||||
priceId: subscriptionItem?.price?.id || '',
|
||||
pricePerUnitInUSD: 100,
|
||||
unitName: 'unit'
|
||||
});
|
||||
|
||||
mockStripe.subscriptions.retrieve = jest
|
||||
.fn()
|
||||
@@ -734,11 +734,11 @@ describe('BillingService', () => {
|
||||
it('should handle non-existent subscription', async () => {
|
||||
const subscriptionItem: SubscriptionItem | undefined =
|
||||
mockSubscription.items.data[0];
|
||||
const meteredPlan: MeteredPlan = new MeteredPlan(
|
||||
subscriptionItem?.price?.id || '',
|
||||
100,
|
||||
'unit'
|
||||
);
|
||||
const meteredPlan: MeteredPlan = new MeteredPlan({
|
||||
priceId: subscriptionItem?.price?.id || '',
|
||||
pricePerUnitInUSD: 100,
|
||||
unitName: 'unit'
|
||||
});
|
||||
|
||||
const subscriptionId: string = 'sub_nonexistent';
|
||||
mockStripe.subscriptions.retrieve = jest
|
||||
|
||||
@@ -22,7 +22,7 @@ export type CouponData = {
|
||||
export type Subscription = {
|
||||
projectId: ObjectID;
|
||||
customerId: string;
|
||||
serverMeteredPlans: Array<typeof ServerMeteredPlan>;
|
||||
serverMeteredPlans: Array<ServerMeteredPlan>;
|
||||
promoCode?: string;
|
||||
defaultPaymentMethodId?: string;
|
||||
trialDate: Date;
|
||||
@@ -31,7 +31,7 @@ export type Subscription = {
|
||||
export type MeteredSubscription = {
|
||||
projectId: ObjectID;
|
||||
customerId: string;
|
||||
serverMeteredPlans: Array<typeof ServerMeteredPlan>;
|
||||
serverMeteredPlans: Array<ServerMeteredPlan>;
|
||||
plan: SubscriptionPlan;
|
||||
quantity: number;
|
||||
isYearly: boolean;
|
||||
@@ -44,7 +44,7 @@ export type ChangePlan = {
|
||||
projectId: ObjectID;
|
||||
subscriptionId: string;
|
||||
meteredSubscriptionId: string;
|
||||
serverMeteredPlans: Array<typeof ServerMeteredPlan>;
|
||||
serverMeteredPlans: Array<ServerMeteredPlan>;
|
||||
newPlan: SubscriptionPlan;
|
||||
quantity: number;
|
||||
isYearly: boolean;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import MeteredPlan from 'Common/Types/Billing/MeteredPlan';
|
||||
import MeteredPlanUtil from './MeteredPlanUtil';
|
||||
import ServerMeteredPlan from './ServerMeteredPlan';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import MonitorService from '../../../Services/MonitorService';
|
||||
@@ -7,18 +5,16 @@ import QueryHelper from '../../Database/QueryHelper';
|
||||
import MonitorType from 'Common/Types/Monitor/MonitorType';
|
||||
import PositiveNumber from 'Common/Types/PositiveNumber';
|
||||
import ProjectService from '../../../Services/ProjectService';
|
||||
import BillingService from '../../../Services/BillingService';
|
||||
import BillingService, { MeteredPlanName } from '../../../Services/BillingService';
|
||||
import Project from 'Model/Models/Project';
|
||||
|
||||
export default class ActiveMonitoringMeteredPlan extends ServerMeteredPlan {
|
||||
public static override getMeteredPlan(): MeteredPlan {
|
||||
const meteredPlan: MeteredPlan =
|
||||
MeteredPlanUtil.getMeteredPlan('ACTIVE_MONITORING');
|
||||
this.meteredPlan = meteredPlan;
|
||||
return meteredPlan;
|
||||
|
||||
public override getMeteredPlanName(): MeteredPlanName {
|
||||
return MeteredPlanName.ActiveMonitoring;
|
||||
}
|
||||
|
||||
public static override async reportQuantityToBillingProvider(
|
||||
public override async reportQuantityToBillingProvider(
|
||||
projectId: ObjectID,
|
||||
options?: {
|
||||
meteredPlanSubscriptionId?: string | undefined;
|
||||
@@ -66,7 +62,7 @@ export default class ActiveMonitoringMeteredPlan extends ServerMeteredPlan {
|
||||
await BillingService.addOrUpdateMeteredPricingOnSubscription(
|
||||
(options?.meteredPlanSubscriptionId as string) ||
|
||||
(project.paymentProviderMeteredSubscriptionId as string),
|
||||
ActiveMonitoringMeteredPlan.getMeteredPlan(),
|
||||
this,
|
||||
count.toNumber()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import ActiveMonitoringMeteredPlan from './ActiveMonitoringMeteredPlan';
|
||||
import LogsDataIngestMeteredPlan from './LogsDataIngestMeteredPlan';
|
||||
import ServerMeteredPlan from './ServerMeteredPlan';
|
||||
import TelemetryMeteredPlan from './TelemetryMeteredPlan';
|
||||
import { ProductType } from 'Model/Models/UsageBilling';
|
||||
|
||||
const AllMeteredPlans: Array<typeof ServerMeteredPlan> = [
|
||||
ActiveMonitoringMeteredPlan,
|
||||
LogsDataIngestMeteredPlan,
|
||||
const AllMeteredPlans: Array<ServerMeteredPlan> = [
|
||||
new ActiveMonitoringMeteredPlan(),
|
||||
new TelemetryMeteredPlan(ProductType.Logs),
|
||||
new TelemetryMeteredPlan(ProductType.Metrics),
|
||||
new TelemetryMeteredPlan(ProductType.Traces),
|
||||
];
|
||||
|
||||
export default AllMeteredPlans;
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import MeteredPlan from 'Common/Types/Billing/MeteredPlan';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import NotImplementedException from 'Common/Types/Exception/NotImplementedException';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import BillingService, { MeteredPlanName } from '../../../Services/BillingService';
|
||||
import MeteredPlan from 'Common/Types/Billing/MeteredPlan';
|
||||
|
||||
export default class ServerMeteredPlan {
|
||||
public static meteredPlan: MeteredPlan | undefined = undefined;
|
||||
|
||||
public static getMeteredPlan(): MeteredPlan {
|
||||
if (!this.meteredPlan) {
|
||||
throw new BadDataException('Metered plan not found');
|
||||
}
|
||||
|
||||
return this.meteredPlan;
|
||||
|
||||
public getMeteredPlanName(): MeteredPlanName {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static async reportQuantityToBillingProvider(
|
||||
public getMeteredPlan(projectId: ObjectID): MeteredPlan {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async reportQuantityToBillingProvider(
|
||||
_projectId: ObjectID,
|
||||
_options: {
|
||||
meteredPlanSubscriptionId?: string | undefined;
|
||||
@@ -22,4 +21,8 @@ export default class ServerMeteredPlan {
|
||||
): Promise<void> {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public getPriceId(): string {
|
||||
return BillingService.getMeteredPlanPriceId(this.getMeteredPlanName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,36 @@
|
||||
import MeteredPlan from 'Common/Types/Billing/MeteredPlan';
|
||||
import MeteredPlanUtil from './MeteredPlanUtil';
|
||||
import ServerMeteredPlan from './ServerMeteredPlan';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import ProjectService from '../../../Services/ProjectService';
|
||||
import BillingService from '../../../Services/BillingService';
|
||||
import BillingService, { MeteredPlanName } from '../../../Services/BillingService';
|
||||
import Project from 'Model/Models/Project';
|
||||
import UsageBilling, { ProductType } from 'Model/Models/UsageBilling';
|
||||
import UsageBillingService from '../../../Services/UsageBillingService';
|
||||
import OneUptimeDate from 'Common/Types/Date';
|
||||
|
||||
export default class LogsDataIngestMeteredPlan extends ServerMeteredPlan {
|
||||
public static override getMeteredPlan(): MeteredPlan {
|
||||
const meteredPlan: MeteredPlan =
|
||||
MeteredPlanUtil.getMeteredPlan('LOGS_DATA_INGEST');
|
||||
this.meteredPlan = meteredPlan;
|
||||
return meteredPlan;
|
||||
export default class TelemetryMeteredPlan extends ServerMeteredPlan {
|
||||
|
||||
|
||||
|
||||
private _prodyctType!: ProductType;
|
||||
public get prodyctType() : ProductType {
|
||||
return this._prodyctType;
|
||||
}
|
||||
public set prodyctType(v : ProductType) {
|
||||
this._prodyctType = v;
|
||||
}
|
||||
|
||||
|
||||
public constructor(productType: ProductType) {
|
||||
super();
|
||||
this.prodyctType = productType;
|
||||
}
|
||||
|
||||
public static override async reportQuantityToBillingProvider(
|
||||
|
||||
public override getMeteredPlanName(): MeteredPlanName {
|
||||
return MeteredPlanName.LogsDataIngestion;
|
||||
}
|
||||
|
||||
public override async reportQuantityToBillingProvider(
|
||||
projectId: ObjectID,
|
||||
options?: {
|
||||
meteredPlanSubscriptionId?: string | undefined;
|
||||
@@ -62,7 +75,7 @@ export default class LogsDataIngestMeteredPlan extends ServerMeteredPlan {
|
||||
await BillingService.addOrUpdateMeteredPricingOnSubscription(
|
||||
(options?.meteredPlanSubscriptionId as string) ||
|
||||
(project.paymentProviderMeteredSubscriptionId as string),
|
||||
LogsDataIngestMeteredPlan.getMeteredPlan(),
|
||||
this,
|
||||
usageBilling.usageCount
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user