add server to monorepo.

This commit is contained in:
a.bouhuolia
2023-02-03 11:57:50 +02:00
parent 28e309981b
commit 80b97b5fdc
1303 changed files with 137049 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
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);
}
}

View File

@@ -0,0 +1,40 @@
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);
}
}

View File

@@ -0,0 +1,80 @@
import { Inject } from 'typedi';
import { Tenant, Plan } from '@/system/models';
import { IPaymentContext } from '@/interfaces';
import { NotAllowedChangeSubscriptionPlan } from '@/exceptions';
export default class Subscription<PaymentModel> {
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
);
}
}

View File

@@ -0,0 +1,41 @@
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;
}
}

View File

@@ -0,0 +1,69 @@
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;
}
}

View 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
);
}
}