mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 05:10:31 +00:00
feat: subscription period based on the license code.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { NextFunction, Router, Request, Response } from 'express';
|
||||
import { check } from 'express-validator';
|
||||
import asyncMiddleware from 'api/middleware/asyncMiddleware';
|
||||
import PaymentMethodController from 'api/controllers/Subscription/PaymentMethod';
|
||||
@@ -8,13 +8,13 @@ import {
|
||||
NoPaymentModelWithPricedPlan,
|
||||
PaymentAmountInvalidWithPlan,
|
||||
PaymentInputInvalid,
|
||||
VoucherCodeRequired
|
||||
VoucherCodeRequired,
|
||||
} from 'exceptions';
|
||||
import { ILicensePaymentModel } from 'interfaces';
|
||||
import instance from 'tsyringe/dist/typings/dependency-container';
|
||||
|
||||
@Service()
|
||||
export default class PaymentViaLicenseController extends PaymentMethodController {
|
||||
export default class PaymentViaLicenseController extends PaymentMethodController {
|
||||
@Inject('logger')
|
||||
logger: any;
|
||||
|
||||
@@ -30,6 +30,7 @@ export default class PaymentViaLicenseController extends PaymentMethodController
|
||||
this.validationResult,
|
||||
asyncMiddleware(this.validatePlanSlugExistance.bind(this)),
|
||||
asyncMiddleware(this.paymentViaLicense.bind(this)),
|
||||
this.handleErrors,
|
||||
);
|
||||
return router;
|
||||
}
|
||||
@@ -40,14 +41,14 @@ export default class PaymentViaLicenseController extends PaymentMethodController
|
||||
get paymentViaLicenseSchema() {
|
||||
return [
|
||||
check('plan_slug').exists().trim().escape(),
|
||||
check('license_code').optional().trim().escape(),
|
||||
check('license_code').exists().trim().escape(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the subscription payment via license code.
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @return {Response}
|
||||
*/
|
||||
async paymentViaLicense(req: Request, res: Response, next: Function) {
|
||||
@@ -55,11 +56,13 @@ export default class PaymentViaLicenseController extends PaymentMethodController
|
||||
const { tenant } = req;
|
||||
|
||||
try {
|
||||
const licenseModel: ILicensePaymentModel|null = licenseCode
|
||||
? { licenseCode } : null;
|
||||
const licenseModel: ILicensePaymentModel = { licenseCode };
|
||||
|
||||
await this.subscriptionService
|
||||
.subscriptionViaLicense(tenant.id, planSlug, licenseModel);
|
||||
await this.subscriptionService.subscriptionViaLicense(
|
||||
tenant.id,
|
||||
planSlug,
|
||||
licenseModel
|
||||
);
|
||||
|
||||
return res.status(200).send({
|
||||
type: 'success',
|
||||
@@ -67,39 +70,56 @@ export default class PaymentViaLicenseController extends PaymentMethodController
|
||||
message: 'Payment via license has been made successfully.',
|
||||
});
|
||||
} catch (exception) {
|
||||
const errorReasons = [];
|
||||
|
||||
if (exception instanceof VoucherCodeRequired) {
|
||||
errorReasons.push({
|
||||
type: 'VOUCHER_CODE_REQUIRED', code: 100,
|
||||
});
|
||||
}
|
||||
if (exception instanceof NoPaymentModelWithPricedPlan) {
|
||||
errorReasons.push({
|
||||
type: 'NO_PAYMENT_WITH_PRICED_PLAN',
|
||||
code: 140,
|
||||
});
|
||||
}
|
||||
if (exception instanceof NotAllowedChangeSubscriptionPlan) {
|
||||
errorReasons.push({
|
||||
type: 'NOT.ALLOWED.RENEW.SUBSCRIPTION.WHILE.ACTIVE',
|
||||
code: 120,
|
||||
});
|
||||
}
|
||||
if (errorReasons.length > 0) {
|
||||
return res.status(400).send({ errors: errorReasons });
|
||||
}
|
||||
if (exception instanceof PaymentInputInvalid) {
|
||||
return res.status(400).send({
|
||||
errors: [{ type: 'LICENSE.CODE.IS.INVALID', code: 120 }],
|
||||
});
|
||||
}
|
||||
if (exception instanceof PaymentAmountInvalidWithPlan) {
|
||||
return res.status(400).send({
|
||||
errors: [{ type: 'LICENSE.NOT.FOR.GIVEN.PLAN' }],
|
||||
});
|
||||
}
|
||||
next(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle service errors.
|
||||
* @param {Error} error
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {NextFunction} next
|
||||
*/
|
||||
private handleErrors(
|
||||
exception: Error,
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
const errorReasons = [];
|
||||
|
||||
if (exception instanceof VoucherCodeRequired) {
|
||||
errorReasons.push({
|
||||
type: 'VOUCHER_CODE_REQUIRED',
|
||||
code: 100,
|
||||
});
|
||||
}
|
||||
if (exception instanceof NoPaymentModelWithPricedPlan) {
|
||||
errorReasons.push({
|
||||
type: 'NO_PAYMENT_WITH_PRICED_PLAN',
|
||||
code: 140,
|
||||
});
|
||||
}
|
||||
if (exception instanceof NotAllowedChangeSubscriptionPlan) {
|
||||
errorReasons.push({
|
||||
type: 'NOT.ALLOWED.RENEW.SUBSCRIPTION.WHILE.ACTIVE',
|
||||
code: 120,
|
||||
});
|
||||
}
|
||||
if (errorReasons.length > 0) {
|
||||
return res.status(400).send({ errors: errorReasons });
|
||||
}
|
||||
if (exception instanceof PaymentInputInvalid) {
|
||||
return res.status(400).send({
|
||||
errors: [{ type: 'LICENSE.CODE.IS.INVALID', code: 120 }],
|
||||
});
|
||||
}
|
||||
if (exception instanceof PaymentAmountInvalidWithPlan) {
|
||||
return res.status(400).send({
|
||||
errors: [{ type: 'LICENSE.NOT.FOR.GIVEN.PLAN' }],
|
||||
});
|
||||
}
|
||||
next(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
export default class NotAllowedChangeSubscriptionPlan {
|
||||
|
||||
constructor(message: string) {
|
||||
constructor() {
|
||||
this.name = "NotAllowedChangeSubscriptionPlan";
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
EventDispatcher,
|
||||
EventDispatcherInterface,
|
||||
} from 'decorators/eventDispatcher';
|
||||
import { PasswordReset } from 'system/models';
|
||||
import { PasswordReset, Tenant } from 'system/models';
|
||||
import {
|
||||
IRegisterDTO,
|
||||
ITenant,
|
||||
@@ -117,7 +117,7 @@ export default class AuthenticationService implements IAuthenticationService {
|
||||
password,
|
||||
user,
|
||||
});
|
||||
const tenant = await user.$relatedQuery('tenant');
|
||||
const tenant = await Tenant.query().findById(user.tenantId).withGraphFetched('metadata');
|
||||
|
||||
// Keep the user object immutable.
|
||||
const outputUser = cloneDeep(user);
|
||||
|
||||
@@ -2,7 +2,6 @@ import { License } from 'system/models';
|
||||
import PaymentMethod from 'services/Payment/PaymentMethod';
|
||||
import { Plan } from 'system/models';
|
||||
import { IPaymentMethod, ILicensePaymentModel } from 'interfaces';
|
||||
import { ILicensePaymentModel } from 'interfaces';
|
||||
import {
|
||||
PaymentInputInvalid,
|
||||
PaymentAmountInvalidWithPlan,
|
||||
@@ -11,12 +10,13 @@ import {
|
||||
|
||||
export default class LicensePaymentMethod
|
||||
extends PaymentMethod
|
||||
implements IPaymentMethod {
|
||||
implements IPaymentMethod
|
||||
{
|
||||
/**
|
||||
* Payment subscription of organization via license code.
|
||||
* @param {ILicensePaymentModel} licensePaymentModel -
|
||||
*/
|
||||
async payment(licensePaymentModel: ILicensePaymentModel, plan: Plan) {
|
||||
public async payment(licensePaymentModel: ILicensePaymentModel, plan: Plan) {
|
||||
this.validateLicensePaymentModel(licensePaymentModel);
|
||||
|
||||
const license = await this.getLicenseOrThrowInvalid(licensePaymentModel);
|
||||
@@ -30,7 +30,9 @@ export default class LicensePaymentMethod
|
||||
* Validates the license code activation on the storage.
|
||||
* @param {ILicensePaymentModel} licensePaymentModel -
|
||||
*/
|
||||
async getLicenseOrThrowInvalid(licensePaymentModel: ILicensePaymentModel) {
|
||||
private async getLicenseOrThrowInvalid(
|
||||
licensePaymentModel: ILicensePaymentModel
|
||||
) {
|
||||
const foundLicense = await License.query()
|
||||
.modify('filterActiveLicense')
|
||||
.where('license_code', licensePaymentModel.licenseCode)
|
||||
@@ -47,7 +49,7 @@ export default class LicensePaymentMethod
|
||||
* @param {License} license
|
||||
* @param {Plan} plan
|
||||
*/
|
||||
validatePaymentAmountWithPlan(license: License, plan: Plan) {
|
||||
private validatePaymentAmountWithPlan(license: License, plan: Plan) {
|
||||
if (license.planId !== plan.id) {
|
||||
throw new PaymentAmountInvalidWithPlan();
|
||||
}
|
||||
@@ -57,7 +59,7 @@ export default class LicensePaymentMethod
|
||||
* Validate voucher payload.
|
||||
* @param {ILicensePaymentModel} licenseModel -
|
||||
*/
|
||||
validateLicensePaymentModel(licenseModel: ILicensePaymentModel) {
|
||||
private validateLicensePaymentModel(licenseModel: ILicensePaymentModel) {
|
||||
if (!licenseModel || !licenseModel.licenseCode) {
|
||||
throw new VoucherCodeRequired();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { Inject } from 'typedi';
|
||||
import { Tenant, Plan } from 'system/models';
|
||||
import { IPaymentContext } from 'interfaces';
|
||||
import { NotAllowedChangeSubscriptionPlan } from 'exceptions';
|
||||
import { NoPaymentModelWithPricedPlan } from 'exceptions';
|
||||
|
||||
export default class Subscription<PaymentModel> {
|
||||
paymentContext: IPaymentContext|null;
|
||||
paymentContext: IPaymentContext | null;
|
||||
|
||||
@Inject('logger')
|
||||
logger: any;
|
||||
@@ -19,46 +18,63 @@ export default class Subscription<PaymentModel> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscripe to the given plan.
|
||||
* @param {Plan} plan
|
||||
* @throws {NotAllowedChangeSubscriptionPlan}
|
||||
* Give the tenant a new subscription.
|
||||
* @param {Tenant} tenant
|
||||
* @param {Plan} plan
|
||||
* @param {string} invoiceInterval
|
||||
* @param {number} invoicePeriod
|
||||
* @param {string} subscriptionSlug
|
||||
*/
|
||||
async subscribe(
|
||||
tenant: Tenant,
|
||||
plan: Plan,
|
||||
paymentModel?: PaymentModel,
|
||||
subscriptionSlug: string = 'main',
|
||||
protected async newSubscribtion(
|
||||
tenant,
|
||||
plan,
|
||||
invoiceInterval: string,
|
||||
invoicePeriod: number,
|
||||
subscriptionSlug: string = 'main'
|
||||
) {
|
||||
this.validateIfPlanHasPriceNoPayment(plan, paymentModel);
|
||||
|
||||
await this.paymentContext.makePayment(paymentModel, plan);
|
||||
|
||||
const subscription = await tenant.$relatedQuery('subscriptions')
|
||||
const subscription = await tenant
|
||||
.$relatedQuery('subscriptions')
|
||||
.modify('subscriptionBySlug', subscriptionSlug)
|
||||
.first();
|
||||
|
||||
// No allowed to re-new the the subscription while the subscription is active.
|
||||
if (subscription && subscription.active()) {
|
||||
throw new NotAllowedChangeSubscriptionPlan;
|
||||
throw new NotAllowedChangeSubscriptionPlan();
|
||||
|
||||
// In case there is already subscription associated to the given tenant renew it.
|
||||
} else if(subscription && subscription.inactive()) {
|
||||
await subscription.renew(plan);
|
||||
// In case there is already subscription associated to the given tenant renew it.
|
||||
} else if (subscription && subscription.inactive()) {
|
||||
await subscription.renew(invoiceInterval, invoicePeriod);
|
||||
|
||||
// No stored past tenant subscriptions create new one.
|
||||
// No stored past tenant subscriptions create new one.
|
||||
} else {
|
||||
await tenant.newSubscription(subscriptionSlug, plan);
|
||||
}
|
||||
await tenant.newSubscription(
|
||||
plan.id,
|
||||
invoiceInterval,
|
||||
invoicePeriod,
|
||||
subscriptionSlug
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw error in plan has price and no payment model.
|
||||
* @param {Plan} plan -
|
||||
* @param {PaymentModel} paymentModel - payment input.
|
||||
* Subscripe to the given plan.
|
||||
* @param {Plan} plan
|
||||
* @throws {NotAllowedChangeSubscriptionPlan}
|
||||
*/
|
||||
validateIfPlanHasPriceNoPayment(plan: Plan, paymentModel: PaymentMode) {
|
||||
if (plan.price > 0 && !paymentModel) {
|
||||
throw new NoPaymentModelWithPricedPlan();
|
||||
}
|
||||
public async subscribe(
|
||||
tenant: Tenant,
|
||||
plan: Plan,
|
||||
paymentModel?: PaymentModel,
|
||||
subscriptionSlug: string = 'main'
|
||||
) {
|
||||
await this.paymentContext.makePayment(paymentModel, plan);
|
||||
|
||||
return this.newSubscribtion(
|
||||
tenant,
|
||||
plan,
|
||||
plan.invoiceInterval,
|
||||
plan.invoicePeriod,
|
||||
subscriptionSlug
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Service, Inject } from 'typedi';
|
||||
import { Plan, PlanSubscription } from 'system/models';
|
||||
import { Plan, PlanSubscription, Tenant } from 'system/models';
|
||||
import Subscription from 'services/Subscription/Subscription';
|
||||
import LicensePaymentMethod from 'services/Payment/LicensePaymentMethod';
|
||||
import PaymentContext from 'services/Payment';
|
||||
import SubscriptionSMSMessages from 'services/Subscription/SMSMessages';
|
||||
import SubscriptionMailMessages from 'services/Subscription/MailMessages';
|
||||
import { ILicensePaymentModel } from 'interfaces';
|
||||
import SubscriptionViaLicense from './SubscriptionViaLicense';
|
||||
|
||||
@Service()
|
||||
export default class SubscriptionService {
|
||||
@@ -22,46 +23,47 @@ export default class SubscriptionService {
|
||||
sysRepositories: any;
|
||||
|
||||
/**
|
||||
* Handles the payment process via license code and than subscribe to
|
||||
* Handles the payment process via license code and than subscribe to
|
||||
* the given tenant.
|
||||
* @param {number} tenantId
|
||||
* @param {String} planSlug
|
||||
* @param {string} licenseCode
|
||||
* @param {number} tenantId
|
||||
* @param {String} planSlug
|
||||
* @param {string} licenseCode
|
||||
* @return {Promise}
|
||||
*/
|
||||
public async subscriptionViaLicense(
|
||||
tenantId: number,
|
||||
planSlug: string,
|
||||
paymentModel?: ILicensePaymentModel,
|
||||
subscriptionSlug: string = 'main',
|
||||
paymentModel: ILicensePaymentModel,
|
||||
subscriptionSlug: string = 'main'
|
||||
) {
|
||||
this.logger.info('[subscription_via_license] try to subscribe via given license.', {
|
||||
tenantId, paymentModel
|
||||
});
|
||||
const { tenantRepository } = this.sysRepositories;
|
||||
|
||||
// Retrieve plan details.
|
||||
const plan = await Plan.query().findOne('slug', planSlug);
|
||||
const tenant = await tenantRepository.findOneById(tenantId);
|
||||
|
||||
// Retrieve tenant details.
|
||||
const tenant = await Tenant.query().findById(tenantId);
|
||||
|
||||
// License payment method.
|
||||
const paymentViaLicense = new LicensePaymentMethod();
|
||||
|
||||
// Payment context.
|
||||
const paymentContext = new PaymentContext(paymentViaLicense);
|
||||
|
||||
const subscription = new Subscription(paymentContext);
|
||||
// Subscription.
|
||||
const subscription = new SubscriptionViaLicense(paymentContext);
|
||||
|
||||
// Subscribe.
|
||||
await subscription.subscribe(tenant, plan, paymentModel, subscriptionSlug);
|
||||
this.logger.info('[subscription_via_license] payment via license done successfully.', {
|
||||
tenantId, paymentModel
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all subscription of the given tenant.
|
||||
* @param {number} tenantId
|
||||
* @param {number} tenantId
|
||||
*/
|
||||
public async getSubscriptions(tenantId: number) {
|
||||
this.logger.info('[subscription] trying to get tenant subscriptions.', { tenantId });
|
||||
const subscriptions = await PlanSubscription.query().where('tenant_id', tenantId);
|
||||
|
||||
const subscriptions = await PlanSubscription.query().where(
|
||||
'tenant_id',
|
||||
tenantId
|
||||
);
|
||||
return subscriptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
54
server/src/services/Subscription/SubscriptionViaLicense.ts
Normal file
54
server/src/services/Subscription/SubscriptionViaLicense.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { License, Tenant, Plan } from 'system/models';
|
||||
import Subscription from './Subscription';
|
||||
import { PaymentModel } from 'interfaces';
|
||||
|
||||
export default class SubscriptionViaLicense extends Subscription<PaymentModel> {
|
||||
/**
|
||||
* Subscripe to the given plan.
|
||||
* @param {Plan} plan
|
||||
* @throws {NotAllowedChangeSubscriptionPlan}
|
||||
*/
|
||||
public async subscribe(
|
||||
tenant: Tenant,
|
||||
plan: Plan,
|
||||
paymentModel?: PaymentModel,
|
||||
subscriptionSlug: string = 'main'
|
||||
): Promise<void> {
|
||||
await this.paymentContext.makePayment(paymentModel, plan);
|
||||
|
||||
return this.newSubscriptionFromLicense(
|
||||
tenant,
|
||||
plan,
|
||||
paymentModel.licenseCode,
|
||||
subscriptionSlug
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* New subscription from the given license.
|
||||
* @param {Tanant} tenant
|
||||
* @param {Plab} plan
|
||||
* @param {string} licenseCode
|
||||
* @param {string} subscriptionSlug
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
private async newSubscriptionFromLicense(
|
||||
tenant,
|
||||
plan,
|
||||
licenseCode: string,
|
||||
subscriptionSlug: string = 'main'
|
||||
): Promise<void> {
|
||||
// License information.
|
||||
const licenseInfo = await License.query().findOne(
|
||||
'licenseCode',
|
||||
licenseCode
|
||||
);
|
||||
return this.newSubscribtion(
|
||||
tenant,
|
||||
plan,
|
||||
licenseInfo.periodInterval,
|
||||
licenseInfo.licensePeriod,
|
||||
subscriptionSlug
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,6 @@ const ERRORS = {
|
||||
|
||||
@Service()
|
||||
export default class UsersService {
|
||||
@Inject()
|
||||
tenancy: TenancyService;
|
||||
|
||||
@Inject('logger')
|
||||
logger: any;
|
||||
|
||||
|
||||
@@ -41,18 +41,18 @@ export default class License extends SystemModel {
|
||||
// Filters licenses list.
|
||||
filter(builder, licensesFilter) {
|
||||
if (licensesFilter.active) {
|
||||
builder.modify('filterActiveLicense')
|
||||
builder.modify('filterActiveLicense');
|
||||
}
|
||||
if (licensesFilter.disabled) {
|
||||
builder.whereNot('disabled_at', null);
|
||||
}
|
||||
if (licensesFilter.used) {
|
||||
builder.whereNot('used_at', null);
|
||||
}
|
||||
}
|
||||
if (licensesFilter.sent) {
|
||||
builder.whereNot('sent_at', null);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -76,38 +76,32 @@ export default class License extends SystemModel {
|
||||
|
||||
/**
|
||||
* Deletes the given license code from the storage.
|
||||
* @param {string} licenseCode
|
||||
* @param {string} licenseCode
|
||||
* @return {Promise}
|
||||
*/
|
||||
static deleteLicense(licenseCode, viaAttribute = 'license_code') {
|
||||
return this.query()
|
||||
.where(viaAttribute, licenseCode)
|
||||
.delete();
|
||||
return this.query().where(viaAttribute, licenseCode).delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the given license code as disabled on the storage.
|
||||
* @param {string} licenseCode
|
||||
* @param {string} licenseCode
|
||||
* @return {Promise}
|
||||
*/
|
||||
static markLicenseAsDisabled(licenseCode, viaAttribute = 'license_code') {
|
||||
return this.query()
|
||||
.where(viaAttribute, licenseCode)
|
||||
.patch({
|
||||
disabled_at: moment().toMySqlDateTime(),
|
||||
});
|
||||
return this.query().where(viaAttribute, licenseCode).patch({
|
||||
disabled_at: moment().toMySqlDateTime(),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the given license code as sent on the storage.
|
||||
* @param {string} licenseCode
|
||||
* @param {string} licenseCode
|
||||
*/
|
||||
static markLicenseAsSent(licenseCode, viaAttribute = 'license_code') {
|
||||
return this.query()
|
||||
.where(viaAttribute, licenseCode)
|
||||
.patch({
|
||||
sent_at: moment().toMySqlDateTime(),
|
||||
});
|
||||
return this.query().where(viaAttribute, licenseCode).patch({
|
||||
sent_at: moment().toMySqlDateTime(),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,20 +110,20 @@ export default class License extends SystemModel {
|
||||
* @return {Promise}
|
||||
*/
|
||||
static markLicenseAsUsed(licenseCode, viaAttribute = 'license_code') {
|
||||
return this.query()
|
||||
.where(viaAttribute, licenseCode)
|
||||
.patch({
|
||||
used_at: moment().toMySqlDateTime()
|
||||
});
|
||||
return this.query().where(viaAttribute, licenseCode).patch({
|
||||
used_at: moment().toMySqlDateTime(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {IIPlan} plan
|
||||
*
|
||||
* @param {IIPlan} plan
|
||||
* @return {boolean}
|
||||
*/
|
||||
isEqualPlanPeriod(plan) {
|
||||
return (this.invoicePeriod === plan.invoiceInterval &&
|
||||
license.licensePeriod === license.periodInterval);
|
||||
return (
|
||||
this.invoicePeriod === plan.invoiceInterval &&
|
||||
license.licensePeriod === license.periodInterval
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import uniqid from 'uniqid';
|
||||
import SubscriptionPeriod from 'services/Subscription/SubscriptionPeriod';
|
||||
import BaseModel from 'models/Model';
|
||||
import TenantMetadata from './TenantMetadata';
|
||||
import PlanSubscription from './Subscriptions/PlanSubscription';
|
||||
|
||||
export default class Tenant extends BaseModel {
|
||||
/**
|
||||
@@ -88,20 +89,40 @@ export default class Tenant extends BaseModel {
|
||||
return chain(subscriptions).map('planId').unq();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} planId
|
||||
* @param {*} invoiceInterval
|
||||
* @param {*} invoicePeriod
|
||||
* @param {*} subscriptionSlug
|
||||
* @returns
|
||||
*/
|
||||
newSubscription(planId, invoiceInterval, invoicePeriod, subscriptionSlug) {
|
||||
return Tenant.newSubscription(
|
||||
this.id,
|
||||
planId,
|
||||
invoiceInterval,
|
||||
invoicePeriod,
|
||||
subscriptionSlug,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Records a new subscription for the associated tenant.
|
||||
*/
|
||||
newSubscription(subscriptionSlug, plan) {
|
||||
const trial = new SubscriptionPeriod(plan.trialInterval, plan.trialPeriod);
|
||||
const period = new SubscriptionPeriod(
|
||||
plan.invoiceInterval,
|
||||
plan.invoicePeriod,
|
||||
trial.getEndDate()
|
||||
);
|
||||
static newSubscription(
|
||||
tenantId,
|
||||
planId,
|
||||
invoiceInterval,
|
||||
invoicePeriod,
|
||||
subscriptionSlug
|
||||
) {
|
||||
const period = new SubscriptionPeriod(invoiceInterval, invoicePeriod);
|
||||
|
||||
return this.$relatedQuery('subscriptions').insert({
|
||||
return PlanSubscription.query().insert({
|
||||
tenantId,
|
||||
slug: subscriptionSlug,
|
||||
planId: plan.id,
|
||||
planId,
|
||||
startsAt: period.getStartDate(),
|
||||
endsAt: period.getEndDate(),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user