From 3b79ac66ae52cc596b7ee56dbfeea5cf010df1ad Mon Sep 17 00:00:00 2001 From: "a.bouhuolia" Date: Thu, 2 Mar 2023 22:44:14 +0200 Subject: [PATCH] feat(server): deprecated the subscription module. --- .../NoPaymentModelWithPricedPlan.ts | 8 - .../NotAllowedChangeSubscriptionPlan.ts | 8 - .../PaymentAmountInvalidWithPlan.ts | 7 - .../src/exceptions/PaymentInputInvalid.ts | 3 - .../src/exceptions/VoucherCodeRequired.ts | 5 - packages/server/src/exceptions/index.ts | 12 +- .../src/jobs/MailNotificationSubscribeEnd.ts | 34 ---- .../src/jobs/MailNotificationTrialEnd.ts | 34 ---- .../src/jobs/SMSNotificationSubscribeEnd.ts | 28 --- .../src/jobs/SMSNotificationTrialEnd.ts | 28 --- packages/server/src/jobs/SendLicenseEmail.ts | 33 ---- packages/server/src/jobs/SendLicensePhone.ts | 33 ---- packages/server/src/loaders/jobs.ts | 28 --- .../server/src/loaders/systemRepositories.ts | 2 - .../Organization/OrganizationService.ts | 1 - .../server/src/services/Payment/License.ts | 185 ------------------ .../services/Payment/LicenseMailMessages.ts | 26 --- .../services/Payment/LicensePaymentMethod.ts | 67 ------- .../services/Payment/LicenseSMSMessages.ts | 17 -- .../src/services/Payment/PaymentMethod.ts | 6 - packages/server/src/services/Payment/index.ts | 22 --- .../src/services/Subscription/MailMessages.ts | 30 --- .../src/services/Subscription/SMSMessages.ts | 40 ---- .../src/services/Subscription/Subscription.ts | 80 -------- .../Subscription/SubscriptionPeriod.ts | 41 ---- .../Subscription/SubscriptionService.ts | 69 ------- .../Subscription/SubscriptionViaLicense.ts | 54 ----- .../system/models/Subscriptions/License.ts | 129 ------------ .../src/system/models/Subscriptions/Plan.ts | 82 -------- .../models/Subscriptions/PlanFeature.ts | 36 ---- .../models/Subscriptions/PlanSubscription.ts | 164 ---------------- packages/server/src/system/models/Tenant.ts | 81 +------- packages/server/src/system/models/index.ts | 17 +- .../repositories/SubscriptionRepository.ts | 26 --- .../server/src/system/repositories/index.ts | 7 +- packages/server/src/system/seeds/.gitkeep | 0 .../system/seeds/seed_subscriptions_plans.js | 66 ------- 37 files changed, 8 insertions(+), 1501 deletions(-) delete mode 100644 packages/server/src/exceptions/NoPaymentModelWithPricedPlan.ts delete mode 100644 packages/server/src/exceptions/NotAllowedChangeSubscriptionPlan.ts delete mode 100644 packages/server/src/exceptions/PaymentAmountInvalidWithPlan.ts delete mode 100644 packages/server/src/exceptions/PaymentInputInvalid.ts delete mode 100644 packages/server/src/exceptions/VoucherCodeRequired.ts delete mode 100644 packages/server/src/jobs/MailNotificationSubscribeEnd.ts delete mode 100644 packages/server/src/jobs/MailNotificationTrialEnd.ts delete mode 100644 packages/server/src/jobs/SMSNotificationSubscribeEnd.ts delete mode 100644 packages/server/src/jobs/SMSNotificationTrialEnd.ts delete mode 100644 packages/server/src/jobs/SendLicenseEmail.ts delete mode 100644 packages/server/src/jobs/SendLicensePhone.ts delete mode 100644 packages/server/src/services/Payment/License.ts delete mode 100644 packages/server/src/services/Payment/LicenseMailMessages.ts delete mode 100644 packages/server/src/services/Payment/LicensePaymentMethod.ts delete mode 100644 packages/server/src/services/Payment/LicenseSMSMessages.ts delete mode 100644 packages/server/src/services/Payment/PaymentMethod.ts delete mode 100644 packages/server/src/services/Payment/index.ts delete mode 100644 packages/server/src/services/Subscription/MailMessages.ts delete mode 100644 packages/server/src/services/Subscription/SMSMessages.ts delete mode 100644 packages/server/src/services/Subscription/Subscription.ts delete mode 100644 packages/server/src/services/Subscription/SubscriptionPeriod.ts delete mode 100644 packages/server/src/services/Subscription/SubscriptionService.ts delete mode 100644 packages/server/src/services/Subscription/SubscriptionViaLicense.ts delete mode 100644 packages/server/src/system/models/Subscriptions/License.ts delete mode 100644 packages/server/src/system/models/Subscriptions/Plan.ts delete mode 100644 packages/server/src/system/models/Subscriptions/PlanFeature.ts delete mode 100644 packages/server/src/system/models/Subscriptions/PlanSubscription.ts delete mode 100644 packages/server/src/system/repositories/SubscriptionRepository.ts create mode 100644 packages/server/src/system/seeds/.gitkeep delete mode 100644 packages/server/src/system/seeds/seed_subscriptions_plans.js diff --git a/packages/server/src/exceptions/NoPaymentModelWithPricedPlan.ts b/packages/server/src/exceptions/NoPaymentModelWithPricedPlan.ts deleted file mode 100644 index 938ec8b4a..000000000 --- a/packages/server/src/exceptions/NoPaymentModelWithPricedPlan.ts +++ /dev/null @@ -1,8 +0,0 @@ - - -export default class NoPaymentModelWithPricedPlan { - - constructor() { - - } -} \ No newline at end of file diff --git a/packages/server/src/exceptions/NotAllowedChangeSubscriptionPlan.ts b/packages/server/src/exceptions/NotAllowedChangeSubscriptionPlan.ts deleted file mode 100644 index 3c5380259..000000000 --- a/packages/server/src/exceptions/NotAllowedChangeSubscriptionPlan.ts +++ /dev/null @@ -1,8 +0,0 @@ - - -export default class NotAllowedChangeSubscriptionPlan { - - constructor() { - this.name = "NotAllowedChangeSubscriptionPlan"; - } -} \ No newline at end of file diff --git a/packages/server/src/exceptions/PaymentAmountInvalidWithPlan.ts b/packages/server/src/exceptions/PaymentAmountInvalidWithPlan.ts deleted file mode 100644 index 834e8cbe1..000000000 --- a/packages/server/src/exceptions/PaymentAmountInvalidWithPlan.ts +++ /dev/null @@ -1,7 +0,0 @@ - - -export default class PaymentAmountInvalidWithPlan{ - constructor() { - - } -} \ No newline at end of file diff --git a/packages/server/src/exceptions/PaymentInputInvalid.ts b/packages/server/src/exceptions/PaymentInputInvalid.ts deleted file mode 100644 index 2a024ff05..000000000 --- a/packages/server/src/exceptions/PaymentInputInvalid.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default class PaymentInputInvalid { - constructor() {} -} diff --git a/packages/server/src/exceptions/VoucherCodeRequired.ts b/packages/server/src/exceptions/VoucherCodeRequired.ts deleted file mode 100644 index a3bef6ff2..000000000 --- a/packages/server/src/exceptions/VoucherCodeRequired.ts +++ /dev/null @@ -1,5 +0,0 @@ -export default class VoucherCodeRequired { - constructor() { - this.name = 'VoucherCodeRequired'; - } -} diff --git a/packages/server/src/exceptions/index.ts b/packages/server/src/exceptions/index.ts index a18746d02..53bb38897 100644 --- a/packages/server/src/exceptions/index.ts +++ b/packages/server/src/exceptions/index.ts @@ -1,25 +1,15 @@ -import NotAllowedChangeSubscriptionPlan from './NotAllowedChangeSubscriptionPlan'; import ServiceError from './ServiceError'; import ServiceErrors from './ServiceErrors'; -import NoPaymentModelWithPricedPlan from './NoPaymentModelWithPricedPlan'; -import PaymentInputInvalid from './PaymentInputInvalid'; -import PaymentAmountInvalidWithPlan from './PaymentAmountInvalidWithPlan'; import TenantAlreadyInitialized from './TenantAlreadyInitialized'; import TenantAlreadySeeded from './TenantAlreadySeeded'; import TenantDBAlreadyExists from './TenantDBAlreadyExists'; import TenantDatabaseNotBuilt from './TenantDatabaseNotBuilt'; -import VoucherCodeRequired from './VoucherCodeRequired'; export { - NotAllowedChangeSubscriptionPlan, - NoPaymentModelWithPricedPlan, - PaymentAmountInvalidWithPlan, ServiceError, ServiceErrors, - PaymentInputInvalid, TenantAlreadyInitialized, TenantAlreadySeeded, TenantDBAlreadyExists, TenantDatabaseNotBuilt, - VoucherCodeRequired, -}; \ No newline at end of file +}; diff --git a/packages/server/src/jobs/MailNotificationSubscribeEnd.ts b/packages/server/src/jobs/MailNotificationSubscribeEnd.ts deleted file mode 100644 index a2b54778b..000000000 --- a/packages/server/src/jobs/MailNotificationSubscribeEnd.ts +++ /dev/null @@ -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); - } - } -} diff --git a/packages/server/src/jobs/MailNotificationTrialEnd.ts b/packages/server/src/jobs/MailNotificationTrialEnd.ts deleted file mode 100644 index 82d8bd53c..000000000 --- a/packages/server/src/jobs/MailNotificationTrialEnd.ts +++ /dev/null @@ -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); - } - } -} diff --git a/packages/server/src/jobs/SMSNotificationSubscribeEnd.ts b/packages/server/src/jobs/SMSNotificationSubscribeEnd.ts deleted file mode 100644 index d203c1d6b..000000000 --- a/packages/server/src/jobs/SMSNotificationSubscribeEnd.ts +++ /dev/null @@ -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); - } - } -} \ No newline at end of file diff --git a/packages/server/src/jobs/SMSNotificationTrialEnd.ts b/packages/server/src/jobs/SMSNotificationTrialEnd.ts deleted file mode 100644 index a3e5c5420..000000000 --- a/packages/server/src/jobs/SMSNotificationTrialEnd.ts +++ /dev/null @@ -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); - } - } -} \ No newline at end of file diff --git a/packages/server/src/jobs/SendLicenseEmail.ts b/packages/server/src/jobs/SendLicenseEmail.ts deleted file mode 100644 index d28c07afe..000000000 --- a/packages/server/src/jobs/SendLicenseEmail.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Container } from 'typedi'; -import LicenseService from '@/services/Payment/License'; - -export default class SendLicenseViaEmailJob { - /** - * Constructor method. - * @param agenda - */ - constructor(agenda) { - agenda.define( - 'send-license-via-email', - { priority: 'high', concurrency: 1, }, - this.handler, - ); - } - - public async handler(job, done: Function): Promise { - const Logger = Container.get('logger'); - const licenseService = Container.get(LicenseService); - const { email, licenseCode } = job.attrs.data; - - Logger.info(`[send_license_via_mail] started: ${job.attrs.data}`); - - try { - await licenseService.mailMessages.sendMailLicense(licenseCode, email); - Logger.info(`[send_license_via_mail] completed: ${job.attrs.data}`); - done(); - } catch(e) { - Logger.error(`[send_license_via_mail] ${job.attrs.data}, error: ${e}`); - done(e); - } - } -} diff --git a/packages/server/src/jobs/SendLicensePhone.ts b/packages/server/src/jobs/SendLicensePhone.ts deleted file mode 100644 index adc5429fb..000000000 --- a/packages/server/src/jobs/SendLicensePhone.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Container } from 'typedi'; -import LicenseService from '@/services/Payment/License'; - -export default class SendLicenseViaPhoneJob { - /** - * Constructor method. - */ - constructor(agenda) { - agenda.define( - 'send-license-via-phone', - { priority: 'high', concurrency: 1, }, - this.handler, - ); - } - - public async handler(job, done: Function): Promise { - const { phoneNumber, licenseCode } = job.attrs.data; - - const Logger = Container.get('logger'); - const licenseService = Container.get(LicenseService); - - Logger.debug(`Send license via phone number - started: ${job.attrs.data}`); - - try { - await licenseService.smsMessages.sendLicenseSMSMessage(phoneNumber, licenseCode); - Logger.debug(`Send license via phone number - completed: ${job.attrs.data}`); - done(); - } catch(e) { - Logger.error(`Send license via phone number: ${job.attrs.data}, error: ${e}`); - done(e); - } - } -} diff --git a/packages/server/src/loaders/jobs.ts b/packages/server/src/loaders/jobs.ts index 448df7ec4..49acd77c2 100644 --- a/packages/server/src/loaders/jobs.ts +++ b/packages/server/src/loaders/jobs.ts @@ -4,12 +4,6 @@ import WelcomeSMSJob from 'jobs/WelcomeSMS'; import ResetPasswordMailJob from 'jobs/ResetPasswordMail'; import ComputeItemCost from 'jobs/ComputeItemCost'; import RewriteInvoicesJournalEntries from 'jobs/writeInvoicesJEntries'; -import SendLicenseViaPhoneJob from 'jobs/SendLicensePhone'; -import SendLicenseViaEmailJob from 'jobs/SendLicenseEmail'; -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 OrganizationSetupJob from 'jobs/OrganizationSetup'; import OrganizationUpgrade from 'jobs/OrganizationUpgrade'; @@ -20,33 +14,11 @@ export default ({ agenda }: { agenda: Agenda }) => { new ResetPasswordMailJob(agenda); new WelcomeSMSJob(agenda); new UserInviteMailJob(agenda); - new SendLicenseViaEmailJob(agenda); - new SendLicenseViaPhoneJob(agenda); new ComputeItemCost(agenda); new RewriteInvoicesJournalEntries(agenda); new OrganizationSetupJob(agenda); new OrganizationUpgrade(agenda); new SmsNotification(agenda); - 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(); }; diff --git a/packages/server/src/loaders/systemRepositories.ts b/packages/server/src/loaders/systemRepositories.ts index 4d84583ca..f162df8f3 100644 --- a/packages/server/src/loaders/systemRepositories.ts +++ b/packages/server/src/loaders/systemRepositories.ts @@ -1,7 +1,6 @@ import Container from 'typedi'; import { SystemUserRepository, - SubscriptionRepository, TenantRepository, } from '@/system/repositories'; @@ -11,7 +10,6 @@ export default () => { return { systemUserRepository: new SystemUserRepository(knex, cache), - subscriptionRepository: new SubscriptionRepository(knex, cache), tenantRepository: new TenantRepository(knex, cache), }; } \ No newline at end of file diff --git a/packages/server/src/services/Organization/OrganizationService.ts b/packages/server/src/services/Organization/OrganizationService.ts index b4886b4af..32431a066 100644 --- a/packages/server/src/services/Organization/OrganizationService.ts +++ b/packages/server/src/services/Organization/OrganizationService.ts @@ -150,7 +150,6 @@ export default class OrganizationService { public async currentOrganization(tenantId: number): Promise { const tenant = await Tenant.query() .findById(tenantId) - .withGraphFetched('subscriptions') .withGraphFetched('metadata'); this.throwIfTenantNotExists(tenant); diff --git a/packages/server/src/services/Payment/License.ts b/packages/server/src/services/Payment/License.ts deleted file mode 100644 index 8e0fbc675..000000000 --- a/packages/server/src/services/Payment/License.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { Service, Container, Inject } from 'typedi'; -import cryptoRandomString from 'crypto-random-string'; -import { times } from 'lodash'; -import { License, Plan } from '@/system/models'; -import { ILicense, ISendLicenseDTO } from '@/interfaces'; -import LicenseMailMessages from '@/services/Payment/LicenseMailMessages'; -import LicenseSMSMessages from '@/services/Payment/LicenseSMSMessages'; -import { ServiceError } from '@/exceptions'; - -const ERRORS = { - PLAN_NOT_FOUND: 'PLAN_NOT_FOUND', - LICENSE_NOT_FOUND: 'LICENSE_NOT_FOUND', - LICENSE_ALREADY_DISABLED: 'LICENSE_ALREADY_DISABLED', - NO_AVALIABLE_LICENSE_CODE: 'NO_AVALIABLE_LICENSE_CODE', -}; - -@Service() -export default class LicenseService { - @Inject() - smsMessages: LicenseSMSMessages; - - @Inject() - mailMessages: LicenseMailMessages; - - /** - * Validate the plan existance on the storage. - * @param {number} tenantId - - * @param {string} planSlug - Plan slug. - */ - private async getPlanOrThrowError(planSlug: string) { - const foundPlan = await Plan.query().where('slug', planSlug).first(); - - if (!foundPlan) { - throw new ServiceError(ERRORS.PLAN_NOT_FOUND); - } - return foundPlan; - } - - /** - * Valdiate the license existance on the storage. - * @param {number} licenseId - License id. - */ - private async getLicenseOrThrowError(licenseId: number) { - const foundLicense = await License.query().findById(licenseId); - - if (!foundLicense) { - throw new ServiceError(ERRORS.LICENSE_NOT_FOUND); - } - return foundLicense; - } - - /** - * Validates whether the license id is disabled. - * @param {ILicense} license - */ - private validateNotDisabledLicense(license: ILicense) { - if (license.disabledAt) { - throw new ServiceError(ERRORS.LICENSE_ALREADY_DISABLED); - } - } - - /** - * Generates the license code in the given period. - * @param {number} licensePeriod - * @return {Promise} - */ - public async generateLicense( - licensePeriod: number, - periodInterval: string = 'days', - planSlug: string - ): ILicense { - let licenseCode: string; - let repeat: boolean = true; - - // Retrieve plan or throw not found error. - const plan = await this.getPlanOrThrowError(planSlug); - - while (repeat) { - licenseCode = cryptoRandomString({ length: 10, type: 'numeric' }); - const foundLicenses = await License.query().where( - 'license_code', - licenseCode - ); - - if (foundLicenses.length === 0) { - repeat = false; - } - } - return License.query().insert({ - licenseCode, - licensePeriod, - periodInterval, - planId: plan.id, - }); - } - - /** - * Generates licenses. - * @param {number} loop - * @param {number} licensePeriod - * @param {string} periodInterval - * @param {number} planId - */ - public async generateLicenses( - loop = 1, - licensePeriod: number, - periodInterval: string = 'days', - planSlug: string - ) { - const asyncOpers: Promise[] = []; - - times(loop, () => { - const generateOper = this.generateLicense( - licensePeriod, - periodInterval, - planSlug - ); - asyncOpers.push(generateOper); - }); - return Promise.all(asyncOpers); - } - - /** - * Disables the given license id on the storage. - * @param {string} licenseSlug - License slug. - * @return {Promise} - */ - public async disableLicense(licenseId: number) { - const license = await this.getLicenseOrThrowError(licenseId); - - this.validateNotDisabledLicense(license); - - return License.markLicenseAsDisabled(license.id, 'id'); - } - - /** - * Deletes the given license id from the storage. - * @param licenseSlug {string} - License slug. - */ - public async deleteLicense(licenseSlug: string) { - const license = await this.getPlanOrThrowError(licenseSlug); - - return License.query().where('id', license.id).delete(); - } - - /** - * Sends license code to the given customer via SMS or mail message. - * @param {string} licenseCode - License code. - * @param {string} phoneNumber - Phone number. - * @param {string} email - Email address. - */ - public async sendLicenseToCustomer(sendLicense: ISendLicenseDTO) { - const agenda = Container.get('agenda'); - const { phoneNumber, email, period, periodInterval } = sendLicense; - - // Retreive plan details byt the given plan slug. - const plan = await this.getPlanOrThrowError(sendLicense.planSlug); - - const license = await License.query() - .modify('filterActiveLicense') - .where('license_period', period) - .where('period_interval', periodInterval) - .where('plan_id', plan.id) - .first(); - - if (!license) { - throw new ServiceError(ERRORS.NO_AVALIABLE_LICENSE_CODE) - } - // Mark the license as used. - await License.markLicenseAsSent(license.licenseCode); - - if (sendLicense.email) { - await agenda.schedule('1 second', 'send-license-via-email', { - licenseCode: license.licenseCode, - email, - }); - } - if (phoneNumber) { - await agenda.schedule('1 second', 'send-license-via-phone', { - licenseCode: license.licenseCode, - phoneNumber, - }); - } - } -} diff --git a/packages/server/src/services/Payment/LicenseMailMessages.ts b/packages/server/src/services/Payment/LicenseMailMessages.ts deleted file mode 100644 index a9b144629..000000000 --- a/packages/server/src/services/Payment/LicenseMailMessages.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Container } from 'typedi'; -import Mail from '@/lib/Mail'; -import config from '@/config'; -export default class SubscriptionMailMessages { - /** - * Send license code to the given mail address. - * @param {string} licenseCode - * @param {email} email - */ - public async sendMailLicense(licenseCode: string, email: string) { - const Logger = Container.get('logger'); - - const mail = new Mail() - .setView('mail/LicenseReceive.html') - .setSubject('Bigcapital - License code') - .setTo(email) - .setData({ - licenseCode, - successEmail: config.customerSuccess.email, - successPhoneNumber: config.customerSuccess.phoneNumber, - }); - - await mail.send(); - Logger.info('[license_mail] sent successfully.'); - } -} \ No newline at end of file diff --git a/packages/server/src/services/Payment/LicensePaymentMethod.ts b/packages/server/src/services/Payment/LicensePaymentMethod.ts deleted file mode 100644 index a8dbdf4ec..000000000 --- a/packages/server/src/services/Payment/LicensePaymentMethod.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { License } from '@/system/models'; -import PaymentMethod from '@/services/Payment/PaymentMethod'; -import { Plan } from '@/system/models'; -import { IPaymentMethod, ILicensePaymentModel } from '@/interfaces'; -import { - PaymentInputInvalid, - PaymentAmountInvalidWithPlan, - VoucherCodeRequired, -} from '@/exceptions'; - -export default class LicensePaymentMethod - extends PaymentMethod - implements IPaymentMethod -{ - /** - * Payment subscription of organization via license code. - * @param {ILicensePaymentModel} licensePaymentModel - - */ - public async payment(licensePaymentModel: ILicensePaymentModel, plan: Plan) { - this.validateLicensePaymentModel(licensePaymentModel); - - const license = await this.getLicenseOrThrowInvalid(licensePaymentModel); - this.validatePaymentAmountWithPlan(license, plan); - - // Mark the license code as used. - return License.markLicenseAsUsed(licensePaymentModel.licenseCode); - } - - /** - * Validates the license code activation on the storage. - * @param {ILicensePaymentModel} licensePaymentModel - - */ - private async getLicenseOrThrowInvalid( - licensePaymentModel: ILicensePaymentModel - ) { - const foundLicense = await License.query() - .modify('filterActiveLicense') - .where('license_code', licensePaymentModel.licenseCode) - .first(); - - if (!foundLicense) { - throw new PaymentInputInvalid(); - } - return foundLicense; - } - - /** - * Validates the payment amount with given plan price. - * @param {License} license - * @param {Plan} plan - */ - private validatePaymentAmountWithPlan(license: License, plan: Plan) { - if (license.planId !== plan.id) { - throw new PaymentAmountInvalidWithPlan(); - } - } - - /** - * Validate voucher payload. - * @param {ILicensePaymentModel} licenseModel - - */ - private validateLicensePaymentModel(licenseModel: ILicensePaymentModel) { - if (!licenseModel || !licenseModel.licenseCode) { - throw new VoucherCodeRequired(); - } - } -} diff --git a/packages/server/src/services/Payment/LicenseSMSMessages.ts b/packages/server/src/services/Payment/LicenseSMSMessages.ts deleted file mode 100644 index aa884ccdf..000000000 --- a/packages/server/src/services/Payment/LicenseSMSMessages.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Container, Inject } from 'typedi'; -import SMSClient from '@/services/SMSClient'; - -export default class SubscriptionSMSMessages { - @Inject('SMSClient') - smsClient: SMSClient; - - /** - * Sends license code to the given phone number via SMS message. - * @param {string} phoneNumber - * @param {string} licenseCode - */ - public async sendLicenseSMSMessage(phoneNumber: string, licenseCode: string) { - const message: string = `Your license card number: ${licenseCode}. If you need any help please contact us. Bigcapital.`; - return this.smsClient.sendMessage(phoneNumber, message); - } -} \ No newline at end of file diff --git a/packages/server/src/services/Payment/PaymentMethod.ts b/packages/server/src/services/Payment/PaymentMethod.ts deleted file mode 100644 index a0c1072f0..000000000 --- a/packages/server/src/services/Payment/PaymentMethod.ts +++ /dev/null @@ -1,6 +0,0 @@ -import moment from 'moment'; -import { IPaymentModel } from '@/interfaces'; - -export default class PaymentMethod implements IPaymentModel { - -} \ No newline at end of file diff --git a/packages/server/src/services/Payment/index.ts b/packages/server/src/services/Payment/index.ts deleted file mode 100644 index bec52feaf..000000000 --- a/packages/server/src/services/Payment/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { IPaymentMethod, IPaymentContext } from "interfaces"; -import { Plan } from '@/system/models'; - -export default class PaymentContext implements IPaymentContext{ - paymentMethod: IPaymentMethod; - - /** - * Constructor method. - * @param {IPaymentMethod} paymentMethod - */ - constructor(paymentMethod: IPaymentMethod) { - this.paymentMethod = paymentMethod; - } - - /** - * - * @param {} paymentModel - */ - makePayment(paymentModel: PaymentModel, plan: Plan) { - return this.paymentMethod.payment(paymentModel, plan); - } -} \ No newline at end of file diff --git a/packages/server/src/services/Subscription/MailMessages.ts b/packages/server/src/services/Subscription/MailMessages.ts deleted file mode 100644 index 4c50a5243..000000000 --- a/packages/server/src/services/Subscription/MailMessages.ts +++ /dev/null @@ -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); - } -} \ No newline at end of file diff --git a/packages/server/src/services/Subscription/SMSMessages.ts b/packages/server/src/services/Subscription/SMSMessages.ts deleted file mode 100644 index 9cb7de273..000000000 --- a/packages/server/src/services/Subscription/SMSMessages.ts +++ /dev/null @@ -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 { - 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 { - 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); - } -} diff --git a/packages/server/src/services/Subscription/Subscription.ts b/packages/server/src/services/Subscription/Subscription.ts deleted file mode 100644 index 4592a781f..000000000 --- a/packages/server/src/services/Subscription/Subscription.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Inject } from 'typedi'; -import { Tenant, Plan } from '@/system/models'; -import { IPaymentContext } from '@/interfaces'; -import { NotAllowedChangeSubscriptionPlan } from '@/exceptions'; - -export default class Subscription { - paymentContext: IPaymentContext | null; - - @Inject('logger') - logger: any; - - /** - * Constructor method. - * @param {IPaymentContext} - */ - constructor(payment?: IPaymentContext) { - this.paymentContext = payment; - } - - /** - * Give the tenant a new subscription. - * @param {Tenant} tenant - * @param {Plan} plan - * @param {string} invoiceInterval - * @param {number} invoicePeriod - * @param {string} subscriptionSlug - */ - protected async newSubscribtion( - tenant, - plan, - invoiceInterval: string, - invoicePeriod: number, - subscriptionSlug: string = 'main' - ) { - 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(); - - // 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. - } else { - await tenant.newSubscription( - plan.id, - invoiceInterval, - invoicePeriod, - subscriptionSlug - ); - } - } - - /** - * Subscripe to the given plan. - * @param {Plan} plan - * @throws {NotAllowedChangeSubscriptionPlan} - */ - 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 - ); - } -} diff --git a/packages/server/src/services/Subscription/SubscriptionPeriod.ts b/packages/server/src/services/Subscription/SubscriptionPeriod.ts deleted file mode 100644 index c1d2e4a8b..000000000 --- a/packages/server/src/services/Subscription/SubscriptionPeriod.ts +++ /dev/null @@ -1,41 +0,0 @@ -import moment from 'moment'; - -export default class SubscriptionPeriod { - start: Date; - end: Date; - interval: string; - count: number; - - /** - * Constructor method. - * @param {string} interval - - * @param {number} count - - * @param {Date} start - - */ - constructor(interval: string = 'month', count: number, start?: Date) { - this.interval = interval; - this.count = count; - this.start = start; - - if (!start) { - this.start = moment().toDate(); - } - this.end = moment(start).add(count, interval).toDate(); - } - - getStartDate() { - return this.start; - } - - getEndDate() { - return this.end; - } - - getInterval() { - return this.interval; - } - - getIntervalCount() { - return this.interval; - } -} \ No newline at end of file diff --git a/packages/server/src/services/Subscription/SubscriptionService.ts b/packages/server/src/services/Subscription/SubscriptionService.ts deleted file mode 100644 index 0e254066b..000000000 --- a/packages/server/src/services/Subscription/SubscriptionService.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Service, Inject } from 'typedi'; -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 { - @Inject() - smsMessages: SubscriptionSMSMessages; - - @Inject() - mailMessages: SubscriptionMailMessages; - - @Inject('logger') - logger: any; - - @Inject('repositories') - sysRepositories: any; - - /** - * Handles the payment process via license code and than subscribe to - * the given tenant. - * @param {number} tenantId - * @param {String} planSlug - * @param {string} licenseCode - * @return {Promise} - */ - public async subscriptionViaLicense( - tenantId: number, - planSlug: string, - paymentModel: ILicensePaymentModel, - subscriptionSlug: string = 'main' - ) { - // Retrieve plan details. - const plan = await Plan.query().findOne('slug', planSlug); - - // Retrieve tenant details. - const tenant = await Tenant.query().findById(tenantId); - - // License payment method. - const paymentViaLicense = new LicensePaymentMethod(); - - // Payment context. - const paymentContext = new PaymentContext(paymentViaLicense); - - // Subscription. - const subscription = new SubscriptionViaLicense(paymentContext); - - // Subscribe. - await subscription.subscribe(tenant, plan, paymentModel, subscriptionSlug); - } - - /** - * Retrieve all subscription of the given tenant. - * @param {number} tenantId - */ - public async getSubscriptions(tenantId: number) { - const subscriptions = await PlanSubscription.query().where( - 'tenant_id', - tenantId - ); - return subscriptions; - } -} diff --git a/packages/server/src/services/Subscription/SubscriptionViaLicense.ts b/packages/server/src/services/Subscription/SubscriptionViaLicense.ts deleted file mode 100644 index 629f30143..000000000 --- a/packages/server/src/services/Subscription/SubscriptionViaLicense.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { License, Tenant, Plan } from '@/system/models'; -import Subscription from './Subscription'; -import { PaymentModel } from '@/interfaces'; - -export default class SubscriptionViaLicense extends Subscription { - /** - * Subscripe to the given plan. - * @param {Plan} plan - * @throws {NotAllowedChangeSubscriptionPlan} - */ - public async subscribe( - tenant: Tenant, - plan: Plan, - paymentModel?: PaymentModel, - subscriptionSlug: string = 'main' - ): Promise { - 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} - */ - private async newSubscriptionFromLicense( - tenant, - plan, - licenseCode: string, - subscriptionSlug: string = 'main' - ): Promise { - // License information. - const licenseInfo = await License.query().findOne( - 'licenseCode', - licenseCode - ); - return this.newSubscribtion( - tenant, - plan, - licenseInfo.periodInterval, - licenseInfo.licensePeriod, - subscriptionSlug - ); - } -} diff --git a/packages/server/src/system/models/Subscriptions/License.ts b/packages/server/src/system/models/Subscriptions/License.ts deleted file mode 100644 index 97bbc87a7..000000000 --- a/packages/server/src/system/models/Subscriptions/License.ts +++ /dev/null @@ -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 - ); - } -} diff --git a/packages/server/src/system/models/Subscriptions/Plan.ts b/packages/server/src/system/models/Subscriptions/Plan.ts deleted file mode 100644 index 2b3f6b057..000000000 --- a/packages/server/src/system/models/Subscriptions/Plan.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { Model, mixin } from 'objection'; -import SystemModel from '@/system/models/SystemModel'; -import { PlanSubscription } from '..'; - -export default class Plan extends mixin(SystemModel) { - /** - * Table name. - */ - static get tableName() { - return 'subscription_plans'; - } - - /** - * Timestamps columns. - */ - get timestamps() { - return ['createdAt', 'updatedAt']; - } - - /** - * Defined virtual attributes. - */ - static get virtualAttributes() { - return ['isFree', 'hasTrial']; - } - - /** - * Model modifiers. - */ - static get modifiers() { - return { - getFeatureBySlug(builder, featureSlug) { - builder.where('slug', featureSlug); - }, - }; - } - - /** - * Relationship mapping. - */ - static get relationMappings() { - const PlanSubscription = require('system/models/Subscriptions/PlanSubscription'); - - return { - /** - * The plan may have many subscriptions. - */ - subscriptions: { - relation: Model.HasManyRelation, - modelClass: PlanSubscription.default, - join: { - from: 'subscription_plans.id', - to: 'subscription_plan_subscriptions.planId', - }, - } - }; - } - - /** - * Check if plan is free. - * @return {boolean} - */ - isFree() { - return this.price <= 0; - } - - /** - * Check if plan is paid. - * @return {boolean} - */ - isPaid() { - return !this.isFree(); - } - - /** - * Check if plan has trial. - * @return {boolean} - */ - hasTrial() { - return this.trialPeriod && this.trialInterval; - } -} diff --git a/packages/server/src/system/models/Subscriptions/PlanFeature.ts b/packages/server/src/system/models/Subscriptions/PlanFeature.ts deleted file mode 100644 index 178fe818e..000000000 --- a/packages/server/src/system/models/Subscriptions/PlanFeature.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Model, mixin } from 'objection'; -import SystemModel from '@/system/models/SystemModel'; - -export default class PlanFeature extends mixin(SystemModel) { - /** - * Table name. - */ - static get tableName() { - return 'subscriptions.plan_features'; - } - - /** - * Timestamps columns. - */ - static get timestamps() { - return ['createdAt', 'updatedAt']; - } - - /** - * Relationship mapping. - */ - static get relationMappings() { - const Plan = require('system/models/Subscriptions/Plan'); - - return { - plan: { - relation: Model.BelongsToOneRelation, - modelClass: Plan.default, - join: { - from: 'subscriptions.plan_features.planId', - to: 'subscriptions.plans.id', - }, - }, - }; - } -} diff --git a/packages/server/src/system/models/Subscriptions/PlanSubscription.ts b/packages/server/src/system/models/Subscriptions/PlanSubscription.ts deleted file mode 100644 index d77ee6418..000000000 --- a/packages/server/src/system/models/Subscriptions/PlanSubscription.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { Model, mixin } from 'objection'; -import SystemModel from '@/system/models/SystemModel'; -import moment from 'moment'; -import SubscriptionPeriod from '@/services/Subscription/SubscriptionPeriod'; - -export default class PlanSubscription extends mixin(SystemModel) { - /** - * Table name. - */ - static get tableName() { - return 'subscription_plan_subscriptions'; - } - - /** - * Timestamps columns. - */ - get timestamps() { - return ['createdAt', 'updatedAt']; - } - - /** - * Defined virtual attributes. - */ - static get virtualAttributes() { - return ['active', 'inactive', 'ended', 'onTrial']; - } - - /** - * Modifiers queries. - */ - static get modifiers() { - return { - activeSubscriptions(builder) { - const dateFormat = 'YYYY-MM-DD HH:mm:ss'; - const now = moment().format(dateFormat); - - builder.where('ends_at', '>', now); - builder.where('trial_ends_at', '>', now); - }, - - inactiveSubscriptions() { - builder.modify('endedTrial'); - builder.modify('endedPeriod'); - }, - - subscriptionBySlug(builder, subscriptionSlug) { - builder.where('slug', subscriptionSlug); - }, - - endedTrial(builder) { - const dateFormat = 'YYYY-MM-DD HH:mm:ss'; - const endDate = moment().format(dateFormat); - - builder.where('ends_at', '<=', endDate); - }, - - endedPeriod(builder) { - const dateFormat = 'YYYY-MM-DD HH:mm:ss'; - const endDate = moment().format(dateFormat); - - builder.where('trial_ends_at', '<=', endDate); - }, - }; - } - - /** - * Relations mappings. - */ - static get relationMappings() { - const Tenant = require('system/models/Tenant'); - const Plan = require('system/models/Subscriptions/Plan'); - - return { - /** - * Plan subscription belongs to tenant. - */ - tenant: { - relation: Model.BelongsToOneRelation, - modelClass: Tenant.default, - join: { - from: 'subscription_plan_subscriptions.tenantId', - to: 'tenants.id', - }, - }, - - /** - * Plan description belongs to plan. - */ - plan: { - relation: Model.BelongsToOneRelation, - modelClass: Plan.default, - join: { - from: 'subscription_plan_subscriptions.planId', - to: 'subscription_plans.id', - }, - }, - }; - } - - /** - * Check if subscription is active. - * @return {Boolean} - */ - active() { - return !this.ended() || this.onTrial(); - } - - /** - * Check if subscription is inactive. - * @return {Boolean} - */ - inactive() { - return !this.active(); - } - - /** - * Check if subscription period has ended. - * @return {Boolean} - */ - ended() { - return this.endsAt ? moment().isAfter(this.endsAt) : false; - } - - /** - * Check if subscription is currently on trial. - * @return {Boolean} - */ - onTrial() { - return this.trailEndsAt ? moment().isAfter(this.trailEndsAt) : false; - } - - /** - * Set new period from the given details. - * @param {string} invoiceInterval - * @param {number} invoicePeriod - * @param {string} start - * - * @return {Object} - */ - static setNewPeriod(invoiceInterval, invoicePeriod, start) { - const period = new SubscriptionPeriod( - invoiceInterval, - invoicePeriod, - start, - ); - - const startsAt = period.getStartDate(); - const endsAt = period.getEndDate(); - - return { startsAt, endsAt }; - } - - /** - * Renews subscription period. - * @Promise - */ - renew(invoiceInterval, invoicePeriod) { - const { startsAt, endsAt } = PlanSubscription.setNewPeriod( - invoiceInterval, - invoicePeriod, - ); - return this.$query().update({ startsAt, endsAt }); - } -} diff --git a/packages/server/src/system/models/Tenant.ts b/packages/server/src/system/models/Tenant.ts index 82cb0d112..53436cd17 100644 --- a/packages/server/src/system/models/Tenant.ts +++ b/packages/server/src/system/models/Tenant.ts @@ -1,10 +1,8 @@ import moment from 'moment'; import { Model } from 'objection'; 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 { /** @@ -49,33 +47,13 @@ export default class Tenant extends BaseModel { return !!this.upgradeJobId; } - /** - * Query modifiers. - */ - static modifiers() { - return { - subscriptions(builder) { - builder.withGraphFetched('subscriptions'); - }, - }; - } - /** * Relations mappings. */ static get relationMappings() { - const PlanSubscription = require('./Subscriptions/PlanSubscription'); const TenantMetadata = require('./TenantMetadata'); return { - subscriptions: { - relation: Model.HasManyRelation, - modelClass: PlanSubscription.default, - join: { - from: 'tenants.id', - to: 'subscription_plan_subscriptions.tenantId', - }, - }, metadata: { relation: Model.HasOneRelation, modelClass: TenantMetadata.default, @@ -86,55 +64,6 @@ export default class Tenant extends BaseModel { }, }; } - - /** - * Retrieve the subscribed plans ids. - * @return {number[]} - */ - async subscribedPlansIds() { - const { subscriptions } = this; - 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. - */ - static newSubscription( - tenantId, - planId, - invoiceInterval, - invoicePeriod, - subscriptionSlug - ) { - const period = new SubscriptionPeriod(invoiceInterval, invoicePeriod); - - return PlanSubscription.query().insert({ - tenantId, - slug: subscriptionSlug, - planId, - startsAt: period.getStartDate(), - endsAt: period.getEndDate(), - }); - } - /** * Creates a new tenant with random organization id. */ @@ -185,9 +114,9 @@ export default class Tenant extends BaseModel { /** * Marks the given tenant as upgrading. - * @param {number} tenantId - * @param {string} upgradeJobId - * @returns + * @param {number} tenantId + * @param {string} upgradeJobId + * @returns */ static markAsUpgrading(tenantId, upgradeJobId) { return this.query().update({ upgradeJobId }).where({ id: tenantId }); @@ -195,8 +124,8 @@ export default class Tenant extends BaseModel { /** * Markes the given tenant as upgraded. - * @param {number} tenantId - * @returns + * @param {number} tenantId + * @returns */ static markAsUpgraded(tenantId) { return this.query().update({ upgradeJobId: null }).where({ id: tenantId }); diff --git a/packages/server/src/system/models/index.ts b/packages/server/src/system/models/index.ts index 6e5ee2d80..44a92ea27 100644 --- a/packages/server/src/system/models/index.ts +++ b/packages/server/src/system/models/index.ts @@ -1,22 +1,7 @@ - -import Plan from './Subscriptions/Plan'; -import PlanFeature from './Subscriptions/PlanFeature'; -import PlanSubscription from './Subscriptions/PlanSubscription'; -import License from './Subscriptions/License'; import Tenant from './Tenant'; import TenantMetadata from './TenantMetadata'; import SystemUser from './SystemUser'; import PasswordReset from './PasswordReset'; import Invite from './Invite'; -export { - Plan, - PlanFeature, - PlanSubscription, - License, - Tenant, - TenantMetadata, - SystemUser, - PasswordReset, - Invite, -} \ No newline at end of file +export { Tenant, TenantMetadata, SystemUser, PasswordReset, Invite }; diff --git a/packages/server/src/system/repositories/SubscriptionRepository.ts b/packages/server/src/system/repositories/SubscriptionRepository.ts deleted file mode 100644 index 44962b0b8..000000000 --- a/packages/server/src/system/repositories/SubscriptionRepository.ts +++ /dev/null @@ -1,26 +0,0 @@ -import SystemRepository from '@/system/repositories/SystemRepository'; -import { PlanSubscription } from '@/system/models'; - -export default class SubscriptionRepository extends SystemRepository { - /** - * Gets the repository's model. - */ - get model() { - return PlanSubscription.bindKnex(this.knex); - } - - /** - * Retrieve subscription from a given slug in specific tenant. - * @param {string} slug - * @param {number} tenantId - */ - getBySlugInTenant(slug: string, tenantId: number) { - const cacheKey = this.getCacheKey('getBySlugInTenant', slug, tenantId); - - return this.cache.get(cacheKey, () => { - return PlanSubscription.query() - .findOne('slug', slug) - .where('tenant_id', tenantId); - }); - } -} diff --git a/packages/server/src/system/repositories/index.ts b/packages/server/src/system/repositories/index.ts index 9fb001718..472f9867d 100644 --- a/packages/server/src/system/repositories/index.ts +++ b/packages/server/src/system/repositories/index.ts @@ -1,9 +1,4 @@ import SystemUserRepository from '@/system/repositories/SystemUserRepository'; -import SubscriptionRepository from '@/system/repositories/SubscriptionRepository'; import TenantRepository from '@/system/repositories/TenantRepository'; -export { - SystemUserRepository, - SubscriptionRepository, - TenantRepository, -}; \ No newline at end of file +export { SystemUserRepository, TenantRepository }; diff --git a/packages/server/src/system/seeds/.gitkeep b/packages/server/src/system/seeds/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/server/src/system/seeds/seed_subscriptions_plans.js b/packages/server/src/system/seeds/seed_subscriptions_plans.js deleted file mode 100644 index 0e69b94db..000000000 --- a/packages/server/src/system/seeds/seed_subscriptions_plans.js +++ /dev/null @@ -1,66 +0,0 @@ - -exports.seed = (knex) => { - // Deletes ALL existing entries - return knex('subscription_plans').del() - .then(() => { - // Inserts seed entries - return knex('subscription_plans').insert([ - { - name: 'Essentials', - slug: 'essentials-monthly', - price: 100, - active: true, - currency: 'LYD', - trial_period: 7, - trial_interval: 'days', - }, - { - name: 'Essentials', - slug: 'essentials-yearly', - price: 1200, - active: true, - currency: 'LYD', - trial_period: 12, - trial_interval: 'months', - }, - { - name: 'Pro', - slug: 'pro-monthly', - price: 200, - active: true, - currency: 'LYD', - trial_period: 1, - trial_interval: 'months', - }, - { - name: 'Pro', - slug: 'pro-yearly', - price: 500, - active: true, - currency: 'LYD', - invoice_period: 12, - invoice_interval: 'month', - index: 2, - }, - { - name: 'Plus', - slug: 'plus-monthly', - price: 200, - active: true, - currency: 'LYD', - trial_period: 1, - trial_interval: 'months', - }, - { - name: 'Plus', - slug: 'plus-yearly', - price: 500, - active: true, - currency: 'LYD', - invoice_period: 12, - invoice_interval: 'month', - index: 2, - }, - ]); - }); -};