padloc/packages/core/src/billing.ts

189 lines
4.3 KiB
TypeScript

import { AccountID } from "./account";
import { OrgID } from "./org";
import { Serializable, AsSerializable, AsDate } from "./encoding";
export enum PlanType {
Free,
Premium,
Family,
Team,
Business,
}
export class Plan extends Serializable {
id = "";
type: PlanType = PlanType.Free;
name = "Free";
description = "";
items: number = -1;
storage: number = 0;
groups: number = 0;
vaults: number = 0;
min: number = 0;
max: number = 0;
available = false;
cost: number = 0;
features: string[] = [];
default = false;
color = "";
}
export class PaymentMethod extends Serializable {
id = "";
name = "";
}
export enum SubscriptionStatus {
Trialing = "trialing",
Active = "active",
Inactive = "inactive",
Canceled = "canceled",
}
export class Subscription extends Serializable {
id = "";
account: AccountID = "";
org: OrgID = "";
status: SubscriptionStatus = SubscriptionStatus.Active;
items: number = -1;
storage: number = 0;
groups: number = 0;
vaults: number = 0;
members: number = 0;
paymentError?: string = undefined;
paymentRequiresAuth?: string = undefined;
currentInvoice: string = "";
@AsDate()
periodEnd: Date = new Date(0);
@AsDate()
trialEnd?: Date;
@AsSerializable(Plan)
plan: Plan = new Plan();
}
export class BillingAddress extends Serializable {
name = "";
street = "";
postalCode = "";
city = "";
country = "";
constructor(params?: Partial<BillingAddress>) {
super();
if (params) {
Object.assign(this, params);
}
}
}
export class Discount extends Serializable {
name = "";
coupon = "";
}
export class BillingInfo extends Serializable {
customerId: string = "";
account: AccountID = "";
org: OrgID = "";
email: string = "";
@AsSerializable(Subscription)
subscription: Subscription | null = null;
@AsSerializable(PaymentMethod)
paymentMethod: PaymentMethod | null = null;
@AsSerializable(BillingAddress)
address: BillingAddress = new BillingAddress();
@AsSerializable(Discount)
discount: Discount | null = null;
@AsDate()
firstTrialStarted?: Date;
get trialDaysLeft() {
const daysSinceFirstTrial = this.firstTrialStarted
? Math.floor((Date.now() - this.firstTrialStarted.getTime()) / 24 / 60 / 60 / 1000)
: 0;
return Math.max(0, 30 - daysSinceFirstTrial);
}
}
export class UpdateBillingParams extends Serializable {
provider: string = "";
account?: AccountID = undefined;
org?: OrgID = undefined;
email?: string = undefined;
plan?: string = undefined;
planType?: PlanType = undefined;
members?: number = undefined;
paymentMethod?: { name: string } & any = undefined;
coupon?: string = undefined;
cancel?: boolean = undefined;
@AsSerializable(BillingAddress)
address?: BillingAddress;
constructor(params?: Partial<UpdateBillingParams>) {
super();
if (params) {
Object.assign(this, params);
}
}
}
export class BillingProviderInfo extends Serializable {
type: string = "";
config: {
[param: string]: string;
} = {};
@AsSerializable(Plan)
plans: Plan[] = [];
}
export interface BillingProvider {
update(params: UpdateBillingParams): Promise<void>;
delete(billingInfo: BillingInfo): Promise<void>;
getInfo(): BillingProviderInfo;
}
//
// const stubPlans: Plan[] = [
// {
// id: "personal",
// name: "Personal",
// description: "Basic Setup For Personal Use",
// storage: -1,
// available: true,
// default: true
// },
// {
// id: "shared",
// name: "Shared",
// description: "Basic Setup For Sharing",
// storage: -1,
// vaults: -1,
// available: true,
// orgType: 1
// },
// {
// id: "advanced",
// name: "Advanced",
// description: "Advanced Setup For Sharing",
// storage: -1,
// groups: -1,
// vaults: -1,
// available: true,
// orgType: 2
// }
// ].map(p => {
// const plan = new Plan();
// Object.assign(plan, p);
// return plan;
// });