Files
bigcapital/packages/server/src/system/models/Tenant.ts
2024-08-24 18:50:12 +02:00

237 lines
5.3 KiB
TypeScript

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 {
upgradeJobId: string;
buildJobId: string;
initializedAt!: Date | null;
seededAt!: Date | null;
/**
* Table name.
*/
static get tableName() {
return 'tenants';
}
/**
* Timestamps columns.
* @returns {string[]}
*/
get timestamps() {
return ['createdAt', 'updatedAt'];
}
/**
* Virtual attributes.
* @returns {string[]}
*/
static get virtualAttributes() {
return ['isReady', 'isBuildRunning', 'isUpgradeRunning'];
}
/**
* Tenant is ready.
* @returns {boolean}
*/
get isReady() {
return !!(this.initializedAt && this.seededAt);
}
/**
* Detarimes the tenant whether is build currently running.
* @returns {boolean}
*/
get isBuildRunning() {
return !!this.buildJobId;
}
/**
* Detarmines the tenant whether is upgrade currently running.
* @returns {boolean}
*/
get isUpgradeRunning() {
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,
join: {
from: 'tenants.id',
to: 'tenants_metadata.tenantId',
},
},
};
}
/**
* Creates a new tenant with random organization id.
*/
static createWithUniqueOrgId(uniqId) {
const organizationId = uniqid() || uniqId;
return this.query().insert({ organizationId });
}
/**
* Mark as seeded.
* @param {number} tenantId
*/
static markAsSeeded(tenantId) {
const seededAt = moment().toMySqlDateTime();
return this.query().update({ seededAt }).where({ id: tenantId });
}
/**
* Mark the the given organization as initialized.
* @param {string} organizationId
*/
static markAsInitialized(tenantId) {
const initializedAt = moment().toMySqlDateTime();
return this.query().update({ initializedAt }).where({ id: tenantId });
}
/**
* Marks the given tenant as built.
*/
static markAsBuilt(tenantId) {
const builtAt = moment().toMySqlDateTime();
return this.query().update({ builtAt }).where({ id: tenantId });
}
/**
* Marks the given tenant as built.
*/
static markAsBuilding(tenantId, buildJobId) {
return this.query().update({ buildJobId }).where({ id: tenantId });
}
/**
* Marks the given tenant as built.
*/
static markAsBuildCompleted(tenantId) {
return this.query().update({ buildJobId: null }).where({ id: tenantId });
}
/**
* Marks the given tenant as upgrading.
* @param {number} tenantId
* @param {string} upgradeJobId
* @returns
*/
static markAsUpgrading(tenantId, upgradeJobId) {
return this.query().update({ upgradeJobId }).where({ id: tenantId });
}
/**
* Markes the given tenant as upgraded.
* @param {number} tenantId
* @returns
*/
static markAsUpgraded(tenantId) {
return this.query().update({ upgradeJobId: null }).where({ id: tenantId });
}
/**
* Saves the metadata of the given tenant.
*/
static async saveMetadata(tenantId, metadata) {
const foundMetadata = await TenantMetadata.query().findOne({ tenantId });
const updateOrInsert = foundMetadata ? 'update' : 'insert';
return TenantMetadata.query()
[updateOrInsert]({
tenantId,
...metadata,
})
.where({ tenantId });
}
/**
* Saves the metadata of the tenant.
*/
saveMetadata(metadata) {
return Tenant.saveMetadata(this.id, metadata);
}
/**
*
* @param {*} planId
* @param {*} invoiceInterval
* @param {*} invoicePeriod
* @param {*} subscriptionSlug
* @returns
*/
public newSubscription(
planId,
invoiceInterval,
invoicePeriod,
subscriptionSlug,
payload?,
) {
return Tenant.newSubscription(
this.id,
planId,
invoiceInterval,
invoicePeriod,
subscriptionSlug,
payload
);
}
/**
* Records a new subscription for the associated tenant.
*/
static newSubscription(
tenantId: number,
planId: number,
invoiceInterval: 'month' | 'year',
invoicePeriod: number,
subscriptionSlug: string,
payload?: { lemonSqueezyId: string }
) {
const period = new SubscriptionPeriod(invoiceInterval, invoicePeriod);
return PlanSubscription.query().insert({
tenantId,
slug: subscriptionSlug,
planId,
startsAt: period.getStartDate(),
endsAt: period.getEndDate(),
lemonSubscriptionId: payload?.lemonSqueezyId || null,
});
}
}