mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 13:20:31 +00:00
feat: sweep up the Lemon Squeezy integration
This commit is contained in:
@@ -29,7 +29,7 @@ export class Webhooks extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens to LemonSqueezy webhooks events.
|
* Listens to Lemon Squeezy webhooks events.
|
||||||
* @param {Request} req
|
* @param {Request} req
|
||||||
* @param {Response} res
|
* @param {Response} res
|
||||||
* @returns {Response}
|
* @returns {Response}
|
||||||
|
|||||||
@@ -1,41 +1,29 @@
|
|||||||
import { Request, Response, NextFunction } from 'express';
|
|
||||||
import { Container } from 'typedi';
|
import { Container } from 'typedi';
|
||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
|
||||||
export default (subscriptionSlug = 'main') => async (
|
export default (subscriptionSlug = 'main') =>
|
||||||
req: Request,
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
res: Response,
|
const { tenant, tenantId } = req;
|
||||||
next: NextFunction
|
const { subscriptionRepository } = Container.get('repositories');
|
||||||
) => {
|
|
||||||
const { tenant, tenantId } = req;
|
|
||||||
const Logger = Container.get('logger');
|
|
||||||
const { subscriptionRepository } = Container.get('repositories');
|
|
||||||
|
|
||||||
if (!tenant) {
|
if (!tenant) {
|
||||||
throw new Error('Should load `TenancyMiddlware` before this middleware.');
|
throw new Error('Should load `TenancyMiddlware` before this middleware.');
|
||||||
}
|
}
|
||||||
Logger.info('[subscription_middleware] trying get tenant main subscription.');
|
const subscription = await subscriptionRepository.getBySlugInTenant(
|
||||||
const subscription = await subscriptionRepository.getBySlugInTenant(
|
subscriptionSlug,
|
||||||
subscriptionSlug,
|
tenantId
|
||||||
tenantId
|
|
||||||
);
|
|
||||||
// Validate in case there is no any already subscription.
|
|
||||||
if (!subscription) {
|
|
||||||
Logger.info('[subscription_middleware] tenant has no subscription.', {
|
|
||||||
tenantId,
|
|
||||||
});
|
|
||||||
return res.boom.badRequest('Tenant has no subscription.', {
|
|
||||||
errors: [{ type: 'TENANT.HAS.NO.SUBSCRIPTION' }],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Validate in case the subscription is inactive.
|
|
||||||
else if (subscription.inactive()) {
|
|
||||||
Logger.info(
|
|
||||||
'[subscription_middleware] tenant main subscription is expired.',
|
|
||||||
{ tenantId }
|
|
||||||
);
|
);
|
||||||
return res.boom.badRequest(null, {
|
// Validate in case there is no any already subscription.
|
||||||
errors: [{ type: 'ORGANIZATION.SUBSCRIPTION.INACTIVE' }],
|
if (!subscription) {
|
||||||
});
|
return res.boom.badRequest('Tenant has no subscription.', {
|
||||||
}
|
errors: [{ type: 'TENANT.HAS.NO.SUBSCRIPTION' }],
|
||||||
next();
|
});
|
||||||
};
|
}
|
||||||
|
// Validate in case the subscription is inactive.
|
||||||
|
else if (subscription.inactive()) {
|
||||||
|
return res.boom.badRequest(null, {
|
||||||
|
errors: [{ type: 'ORGANIZATION.SUBSCRIPTION.INACTIVE' }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|||||||
@@ -190,6 +190,15 @@ module.exports = {
|
|||||||
secretSandbox: process.env.PLAID_SECRET_SANDBOX,
|
secretSandbox: process.env.PLAID_SECRET_SANDBOX,
|
||||||
redirectSandBox: process.env.PLAID_SANDBOX_REDIRECT_URI,
|
redirectSandBox: process.env.PLAID_SANDBOX_REDIRECT_URI,
|
||||||
redirectDevelopment: process.env.PLAID_DEVELOPMENT_REDIRECT_URI,
|
redirectDevelopment: process.env.PLAID_DEVELOPMENT_REDIRECT_URI,
|
||||||
linkWebhook: process.env.PLAID_LINK_WEBHOOK
|
linkWebhook: process.env.PLAID_LINK_WEBHOOK,
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lemon Squeezy.
|
||||||
|
*/
|
||||||
|
lemonSqueezy: {
|
||||||
|
key: process.env.LEMONSQUEEZY_API_KEY,
|
||||||
|
storeId: process.env.LEMONSQUEEZY_STORE_ID,
|
||||||
|
webhookSecret: process.env.LEMONSQUEEZY_WEBHOOK_SECRET,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
export default class NoPaymentModelWithPricedPlan {
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
export default class PaymentAmountInvalidWithPlan{
|
|
||||||
constructor() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export default class PaymentInputInvalid {
|
|
||||||
constructor() {}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export default class VoucherCodeRequired {
|
|
||||||
constructor() {
|
|
||||||
this.name = 'VoucherCodeRequired';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +1,17 @@
|
|||||||
import NotAllowedChangeSubscriptionPlan from './NotAllowedChangeSubscriptionPlan';
|
import NotAllowedChangeSubscriptionPlan from './NotAllowedChangeSubscriptionPlan';
|
||||||
import ServiceError from './ServiceError';
|
import ServiceError from './ServiceError';
|
||||||
import ServiceErrors from './ServiceErrors';
|
import ServiceErrors from './ServiceErrors';
|
||||||
import NoPaymentModelWithPricedPlan from './NoPaymentModelWithPricedPlan';
|
|
||||||
import PaymentInputInvalid from './PaymentInputInvalid';
|
|
||||||
import PaymentAmountInvalidWithPlan from './PaymentAmountInvalidWithPlan';
|
|
||||||
import TenantAlreadyInitialized from './TenantAlreadyInitialized';
|
import TenantAlreadyInitialized from './TenantAlreadyInitialized';
|
||||||
import TenantAlreadySeeded from './TenantAlreadySeeded';
|
import TenantAlreadySeeded from './TenantAlreadySeeded';
|
||||||
import TenantDBAlreadyExists from './TenantDBAlreadyExists';
|
import TenantDBAlreadyExists from './TenantDBAlreadyExists';
|
||||||
import TenantDatabaseNotBuilt from './TenantDatabaseNotBuilt';
|
import TenantDatabaseNotBuilt from './TenantDatabaseNotBuilt';
|
||||||
import VoucherCodeRequired from './VoucherCodeRequired';
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
NotAllowedChangeSubscriptionPlan,
|
NotAllowedChangeSubscriptionPlan,
|
||||||
NoPaymentModelWithPricedPlan,
|
|
||||||
PaymentAmountInvalidWithPlan,
|
|
||||||
ServiceError,
|
ServiceError,
|
||||||
ServiceErrors,
|
ServiceErrors,
|
||||||
PaymentInputInvalid,
|
|
||||||
TenantAlreadyInitialized,
|
TenantAlreadyInitialized,
|
||||||
TenantAlreadySeeded,
|
TenantAlreadySeeded,
|
||||||
TenantDBAlreadyExists,
|
TenantDBAlreadyExists,
|
||||||
TenantDatabaseNotBuilt,
|
TenantDatabaseNotBuilt,
|
||||||
VoucherCodeRequired,
|
};
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
import Container from 'typedi';
|
|
||||||
import SubscriptionService from '@/services/Subscription/Subscription';
|
|
||||||
|
|
||||||
export default class MailNotificationSubscribeEnd {
|
|
||||||
/**
|
|
||||||
* Job handler.
|
|
||||||
* @param {Job} job -
|
|
||||||
*/
|
|
||||||
handler(job) {
|
|
||||||
const { tenantId, phoneNumber, remainingDays } = job.attrs.data;
|
|
||||||
|
|
||||||
const subscriptionService = Container.get(SubscriptionService);
|
|
||||||
const Logger = Container.get('logger');
|
|
||||||
|
|
||||||
Logger.info(
|
|
||||||
`Send mail notification subscription end soon - started: ${job.attrs.data}`
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
subscriptionService.mailMessages.sendRemainingTrialPeriod(
|
|
||||||
phoneNumber,
|
|
||||||
remainingDays
|
|
||||||
);
|
|
||||||
Logger.info(
|
|
||||||
`Send mail notification subscription end soon - finished: ${job.attrs.data}`
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
Logger.info(
|
|
||||||
`Send mail notification subscription end soon - failed: ${job.attrs.data}, error: ${e}`
|
|
||||||
);
|
|
||||||
done(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import Container from 'typedi';
|
|
||||||
import SubscriptionService from '@/services/Subscription/Subscription';
|
|
||||||
|
|
||||||
export default class MailNotificationTrialEnd {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {Job} job -
|
|
||||||
*/
|
|
||||||
handler(job) {
|
|
||||||
const { tenantId, phoneNumber, remainingDays } = job.attrs.data;
|
|
||||||
|
|
||||||
const subscriptionService = Container.get(SubscriptionService);
|
|
||||||
const Logger = Container.get('logger');
|
|
||||||
|
|
||||||
Logger.info(
|
|
||||||
`Send mail notification subscription end soon - started: ${job.attrs.data}`
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
subscriptionService.mailMessages.sendRemainingTrialPeriod(
|
|
||||||
phoneNumber,
|
|
||||||
remainingDays
|
|
||||||
);
|
|
||||||
Logger.info(
|
|
||||||
`Send mail notification subscription end soon - finished: ${job.attrs.data}`
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
Logger.info(
|
|
||||||
`Send mail notification subscription end soon - failed: ${job.attrs.data}, error: ${e}`
|
|
||||||
);
|
|
||||||
done(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import Container from 'typedi';
|
|
||||||
import SubscriptionService from '@/services/Subscription/Subscription';
|
|
||||||
|
|
||||||
export default class SMSNotificationSubscribeEnd {
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {Job}job
|
|
||||||
*/
|
|
||||||
handler(job) {
|
|
||||||
const { tenantId, phoneNumber, remainingDays } = job.attrs.data;
|
|
||||||
|
|
||||||
const subscriptionService = Container.get(SubscriptionService);
|
|
||||||
const Logger = Container.get('logger');
|
|
||||||
|
|
||||||
Logger.info(`Send SMS notification subscription end soon - started: ${job.attrs.data}`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
subscriptionService.smsMessages.sendRemainingSubscriptionPeriod(
|
|
||||||
phoneNumber, remainingDays,
|
|
||||||
);
|
|
||||||
Logger.info(`Send SMS notification subscription end soon - finished: ${job.attrs.data}`);
|
|
||||||
} catch(error) {
|
|
||||||
Logger.info(`Send SMS notification subscription end soon - failed: ${job.attrs.data}, error: ${e}`);
|
|
||||||
done(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import Container from 'typedi';
|
|
||||||
import SubscriptionService from '@/services/Subscription/Subscription';
|
|
||||||
|
|
||||||
export default class SMSNotificationTrialEnd {
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {Job}job
|
|
||||||
*/
|
|
||||||
handler(job) {
|
|
||||||
const { tenantId, phoneNumber, remainingDays } = job.attrs.data;
|
|
||||||
|
|
||||||
const subscriptionService = Container.get(SubscriptionService);
|
|
||||||
const Logger = Container.get('logger');
|
|
||||||
|
|
||||||
Logger.info(`Send notification subscription end soon - started: ${job.attrs.data}`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
subscriptionService.smsMessages.sendRemainingTrialPeriod(
|
|
||||||
phoneNumber, remainingDays,
|
|
||||||
);
|
|
||||||
Logger.info(`Send notification subscription end soon - finished: ${job.attrs.data}`);
|
|
||||||
} catch(error) {
|
|
||||||
Logger.info(`Send notification subscription end soon - failed: ${job.attrs.data}, error: ${e}`);
|
|
||||||
done(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,10 +2,6 @@ import Agenda from 'agenda';
|
|||||||
import ResetPasswordMailJob from 'jobs/ResetPasswordMail';
|
import ResetPasswordMailJob from 'jobs/ResetPasswordMail';
|
||||||
import ComputeItemCost from 'jobs/ComputeItemCost';
|
import ComputeItemCost from 'jobs/ComputeItemCost';
|
||||||
import RewriteInvoicesJournalEntries from 'jobs/WriteInvoicesJEntries';
|
import RewriteInvoicesJournalEntries from 'jobs/WriteInvoicesJEntries';
|
||||||
import SendSMSNotificationSubscribeEnd from 'jobs/SMSNotificationSubscribeEnd';
|
|
||||||
import SendSMSNotificationTrialEnd from 'jobs/SMSNotificationTrialEnd';
|
|
||||||
import SendMailNotificationSubscribeEnd from 'jobs/MailNotificationSubscribeEnd';
|
|
||||||
import SendMailNotificationTrialEnd from 'jobs/MailNotificationTrialEnd';
|
|
||||||
import UserInviteMailJob from 'jobs/UserInviteMail';
|
import UserInviteMailJob from 'jobs/UserInviteMail';
|
||||||
import OrganizationSetupJob from 'jobs/OrganizationSetup';
|
import OrganizationSetupJob from 'jobs/OrganizationSetup';
|
||||||
import OrganizationUpgrade from 'jobs/OrganizationUpgrade';
|
import OrganizationUpgrade from 'jobs/OrganizationUpgrade';
|
||||||
@@ -35,25 +31,5 @@ export default ({ agenda }: { agenda: Agenda }) => {
|
|||||||
agenda.start().then(() => {
|
agenda.start().then(() => {
|
||||||
agenda.every('1 hours', 'delete-expired-imported-files', {});
|
agenda.every('1 hours', 'delete-expired-imported-files', {});
|
||||||
});
|
});
|
||||||
// agenda.define(
|
|
||||||
// 'send-sms-notification-subscribe-end',
|
|
||||||
// { priority: 'nromal', concurrency: 1, },
|
|
||||||
// new SendSMSNotificationSubscribeEnd().handler,
|
|
||||||
// );
|
|
||||||
// agenda.define(
|
|
||||||
// 'send-sms-notification-trial-end',
|
|
||||||
// { priority: 'normal', concurrency: 1, },
|
|
||||||
// new SendSMSNotificationTrialEnd().handler,
|
|
||||||
// );
|
|
||||||
// agenda.define(
|
|
||||||
// 'send-mail-notification-subscribe-end',
|
|
||||||
// { priority: 'high', concurrency: 1, },
|
|
||||||
// new SendMailNotificationSubscribeEnd().handler
|
|
||||||
// );
|
|
||||||
// agenda.define(
|
|
||||||
// 'send-mail-notification-trial-end',
|
|
||||||
// { priority: 'high', concurrency: 1, },
|
|
||||||
// new SendMailNotificationTrialEnd().handler
|
|
||||||
// );
|
|
||||||
agenda.start();
|
agenda.start();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
import { Service } from "typedi";
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export default class SubscriptionMailMessages {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param phoneNumber
|
|
||||||
* @param remainingDays
|
|
||||||
*/
|
|
||||||
public async sendRemainingSubscriptionPeriod(phoneNumber: string, remainingDays: number) {
|
|
||||||
const message: string = `
|
|
||||||
Your remaining subscription is ${remainingDays} days,
|
|
||||||
please renew your subscription before expire.
|
|
||||||
`;
|
|
||||||
this.smsClient.sendMessage(phoneNumber, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param phoneNumber
|
|
||||||
* @param remainingDays
|
|
||||||
*/
|
|
||||||
public async sendRemainingTrialPeriod(phoneNumber: string, remainingDays: number) {
|
|
||||||
const message: string = `
|
|
||||||
Your remaining free trial is ${remainingDays} days,
|
|
||||||
please subscription before ends, if you have any quation to contact us.`;
|
|
||||||
|
|
||||||
this.smsClient.sendMessage(phoneNumber, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
import { Service, Inject } from 'typedi';
|
|
||||||
import SMSClient from '@/services/SMSClient';
|
|
||||||
|
|
||||||
@Service()
|
|
||||||
export default class SubscriptionSMSMessages {
|
|
||||||
@Inject('SMSClient')
|
|
||||||
smsClient: SMSClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send remaining subscription period SMS message.
|
|
||||||
* @param {string} phoneNumber -
|
|
||||||
* @param {number} remainingDays -
|
|
||||||
*/
|
|
||||||
public async sendRemainingSubscriptionPeriod(
|
|
||||||
phoneNumber: string,
|
|
||||||
remainingDays: number
|
|
||||||
): Promise<void> {
|
|
||||||
const message: string = `
|
|
||||||
Your remaining subscription is ${remainingDays} days,
|
|
||||||
please renew your subscription before expire.
|
|
||||||
`;
|
|
||||||
this.smsClient.sendMessage(phoneNumber, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send remaining trial period SMS message.
|
|
||||||
* @param {string} phoneNumber -
|
|
||||||
* @param {number} remainingDays -
|
|
||||||
*/
|
|
||||||
public async sendRemainingTrialPeriod(
|
|
||||||
phoneNumber: string,
|
|
||||||
remainingDays: number
|
|
||||||
): Promise<void> {
|
|
||||||
const message: string = `
|
|
||||||
Your remaining free trial is ${remainingDays} days,
|
|
||||||
please subscription before ends, if you have any quation to contact us.`;
|
|
||||||
|
|
||||||
this.smsClient.sendMessage(phoneNumber, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,11 +23,9 @@ export function configureLemonSqueezy() {
|
|||||||
lemonSqueezySetup({
|
lemonSqueezySetup({
|
||||||
apiKey: process.env.LEMONSQUEEZY_API_KEY,
|
apiKey: process.env.LEMONSQUEEZY_API_KEY,
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.log(error);
|
|
||||||
// console.log('LL', error.message);
|
|
||||||
// eslint-disable-next-line no-console -- allow logging
|
// eslint-disable-next-line no-console -- allow logging
|
||||||
// console.error(error);
|
console.error(error);
|
||||||
// throw new Error(`Lemon Squeezy API error: ${error.message}`);
|
throw new Error(`Lemon Squeezy API error: ${error.message}`);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,129 +0,0 @@
|
|||||||
import { Model, mixin } from 'objection';
|
|
||||||
import moment from 'moment';
|
|
||||||
import SystemModel from '@/system/models/SystemModel';
|
|
||||||
|
|
||||||
export default class License extends SystemModel {
|
|
||||||
/**
|
|
||||||
* Table name.
|
|
||||||
*/
|
|
||||||
static get tableName() {
|
|
||||||
return 'subscription_licenses';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timestamps columns.
|
|
||||||
*/
|
|
||||||
get timestamps() {
|
|
||||||
return ['createdAt', 'updatedAt'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Model modifiers.
|
|
||||||
*/
|
|
||||||
static get modifiers() {
|
|
||||||
return {
|
|
||||||
// Filters active licenses.
|
|
||||||
filterActiveLicense(query) {
|
|
||||||
query.where('disabled_at', null);
|
|
||||||
query.where('used_at', null);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Find license by its code or id.
|
|
||||||
findByCodeOrId(query, id, code) {
|
|
||||||
if (id) {
|
|
||||||
query.where('id', id);
|
|
||||||
}
|
|
||||||
if (code) {
|
|
||||||
query.where('license_code', code);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Filters licenses list.
|
|
||||||
filter(builder, licensesFilter) {
|
|
||||||
if (licensesFilter.active) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Relationship mapping.
|
|
||||||
*/
|
|
||||||
static get relationMappings() {
|
|
||||||
const Plan = require('system/models/Subscriptions/Plan');
|
|
||||||
|
|
||||||
return {
|
|
||||||
plan: {
|
|
||||||
relation: Model.BelongsToOneRelation,
|
|
||||||
modelClass: Plan.default,
|
|
||||||
join: {
|
|
||||||
from: 'subscription_licenses.planId',
|
|
||||||
to: 'subscriptions_plans.id',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the given license code from the storage.
|
|
||||||
* @param {string} licenseCode
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
static deleteLicense(licenseCode, viaAttribute = 'license_code') {
|
|
||||||
return this.query().where(viaAttribute, licenseCode).delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks the given license code as disabled on the storage.
|
|
||||||
* @param {string} licenseCode
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
static markLicenseAsDisabled(licenseCode, viaAttribute = 'license_code') {
|
|
||||||
return this.query().where(viaAttribute, licenseCode).patch({
|
|
||||||
disabled_at: moment().toMySqlDateTime(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks the given license code as sent on the storage.
|
|
||||||
* @param {string} licenseCode
|
|
||||||
*/
|
|
||||||
static markLicenseAsSent(licenseCode, viaAttribute = 'license_code') {
|
|
||||||
return this.query().where(viaAttribute, licenseCode).patch({
|
|
||||||
sent_at: moment().toMySqlDateTime(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks the given license code as used on the storage.
|
|
||||||
* @param {string} licenseCode
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
static markLicenseAsUsed(licenseCode, viaAttribute = 'license_code') {
|
|
||||||
return this.query().where(viaAttribute, licenseCode).patch({
|
|
||||||
used_at: moment().toMySqlDateTime(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {IIPlan} plan
|
|
||||||
* @return {boolean}
|
|
||||||
*/
|
|
||||||
isEqualPlanPeriod(plan) {
|
|
||||||
return (
|
|
||||||
this.invoicePeriod === plan.invoiceInterval &&
|
|
||||||
license.licensePeriod === license.periodInterval
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user