From 5e03dcb150d2669b0efaf7ffefac4a4678395fe9 Mon Sep 17 00:00:00 2001 From: Shubham P Date: Thu, 22 Aug 2024 10:35:57 +0530 Subject: [PATCH] =?UTF-8?q?feat(ci-cd):=20add=20apis=20to=20manage=20plan?= =?UTF-8?q?=20size=20configuration=20and=20features=20=E2=80=A6=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR adds the API endspoints to manage plan size configuration and features mapping with the plans to be created by SaaS Admin and consumed by both application plane and control plane. --- services/orchestrator-service/README.md | 16 +- .../src/__tests__/unit/component.unit.ts | 3 + .../unit/orchestrator-service.unit.ts | 20 +- .../orchestrator-service/src/component.ts | 3 + .../src/services/index.ts | 1 + .../src/services/orchestrator.service.ts | 17 +- .../tenant-deployment-handler.service.ts | 23 + .../src/services/types.ts | 13 +- .../20240805112128-remove-plan-items.js | 59 + .../20240805112316-add-plan-sizes-table.js | 59 + .../20240805112817-add-plan-size-column.js | 59 + ...0208115049-add-tier-column-to-plans-up.sql | 2 +- .../sqls/20240209122448-seed-data-up.sql | 4 +- .../20240805112128-remove-plan-items-down.sql | 16 + .../20240805112128-remove-plan-items-up.sql | 1 + ...240805112316-add-plan-sizes-table-down.sql | 1 + ...20240805112316-add-plan-sizes-table-up.sql | 15 + ...240805112817-add-plan-size-column-down.sql | 1 + ...20240805112817-add-plan-size-column-up.sql | 2 + .../src/__tests__/acceptance/mock-data.ts | 14 +- .../plan-item.controller.acceptance.ts | 143 - .../subscription-service/src/component.ts | 16 +- .../src/controllers/index.ts | 3 +- .../controllers/plan-features.controller.ts | 215 + ...controller.ts => plan-sizes.controller.ts} | 105 +- .../subscription-service/src/enums/index.ts | 1 - .../src/enums/plans-tier.enum.ts | 4 - .../subscription-service/src/models/index.ts | 2 +- .../src/models/plan-item.model.ts | 53 - .../src/models/plan-sizes.model.ts | 33 + .../src/models/plan.model.ts | 30 +- .../subscription-service/src/openapi.json | 4386 +++++++++++++---- .../subscription-service/src/permissions.ts | 11 +- .../src/repositories/index.ts | 2 +- .../src/repositories/plan-item.repository.ts | 31 - .../src/repositories/plan-sizes.repository.ts | 24 + .../src/repositories/plan.repository.ts | 26 +- .../src/__tests__/acceptance/mock-data.ts | 10 +- .../src/enums/index.ts | 1 - .../src/enums/plans-tier.enum.ts | 4 - .../src/models/dtos/plan-item-dto.model.ts | 40 - .../src/types/i-subscription.interface.ts | 27 +- .../src/types/index.ts | 1 + 43 files changed, 3994 insertions(+), 1503 deletions(-) create mode 100644 services/orchestrator-service/src/services/tenant-deployment-handler.service.ts create mode 100644 services/subscription-service/migrations/pg/migrations/20240805112128-remove-plan-items.js create mode 100644 services/subscription-service/migrations/pg/migrations/20240805112316-add-plan-sizes-table.js create mode 100644 services/subscription-service/migrations/pg/migrations/20240805112817-add-plan-size-column.js create mode 100644 services/subscription-service/migrations/pg/migrations/sqls/20240805112128-remove-plan-items-down.sql create mode 100644 services/subscription-service/migrations/pg/migrations/sqls/20240805112128-remove-plan-items-up.sql create mode 100644 services/subscription-service/migrations/pg/migrations/sqls/20240805112316-add-plan-sizes-table-down.sql create mode 100644 services/subscription-service/migrations/pg/migrations/sqls/20240805112316-add-plan-sizes-table-up.sql create mode 100644 services/subscription-service/migrations/pg/migrations/sqls/20240805112817-add-plan-size-column-down.sql create mode 100644 services/subscription-service/migrations/pg/migrations/sqls/20240805112817-add-plan-size-column-up.sql delete mode 100644 services/subscription-service/src/__tests__/acceptance/plan-item.controller.acceptance.ts create mode 100644 services/subscription-service/src/controllers/plan-features.controller.ts rename services/subscription-service/src/controllers/{plan-item.controller.ts => plan-sizes.controller.ts} (57%) delete mode 100644 services/subscription-service/src/enums/plans-tier.enum.ts delete mode 100644 services/subscription-service/src/models/plan-item.model.ts create mode 100644 services/subscription-service/src/models/plan-sizes.model.ts delete mode 100644 services/subscription-service/src/repositories/plan-item.repository.ts create mode 100644 services/subscription-service/src/repositories/plan-sizes.repository.ts delete mode 100644 services/tenant-management-service/src/enums/plans-tier.enum.ts delete mode 100644 services/tenant-management-service/src/models/dtos/plan-item-dto.model.ts diff --git a/services/orchestrator-service/README.md b/services/orchestrator-service/README.md index 57ead03..0b1e17f 100644 --- a/services/orchestrator-service/README.md +++ b/services/orchestrator-service/README.md @@ -73,6 +73,7 @@ This microservice provides following loopback services and providers which can b 5. [Tenant Deprovisioning Provider](#5-tenant-deprovisioning-provider) 6. [Tenant Provisioning Success Handler](#6-tenant-provisioning-success-provider) 7. [Tenant Provisioning Failure Handler](#7-tenant-provisioning-failure-provider) +8. [Tenant Deployment Handler](#8-tenant-deployment-handler) Here's the invocation flow for quick understanding on how and when above artifacts are called, more details are provided in their own sections: @@ -135,6 +136,7 @@ import { TenantProvisioningFailureHandler, TenantProvisioningHandler, TenantProvisioningSuccessHandler, + TenantDeploymentHandler, } from '@arc-saas/orchestrator-service'; export interface AWSEventBridgeInterface { @@ -160,6 +162,8 @@ export class OrchestratorService implements OrchestratorServiceInterface { private handleTenantProvisioningSuccess: TenantProvisioningSuccessHandler, @inject(OrchestratorServiceBindings.TENANT_PROVISIONING_FAILURE_HANDLER) private handleTenantProvisioningFailure: TenantProvisioningFailureHandler, + @inject(OrchestratorServiceBindings.TENANT_DEPLOYMENT_HANDLER) + private handleTenantDeployment: TenantDeploymentHandler, ) {} handleEvent( @@ -173,8 +177,10 @@ export class OrchestratorService implements OrchestratorServiceInterface { return this.handleTenantDeprovisioning(eventBody.detail); case EventTypes.TENANT_PROVISIONING_SUCCESS: return this.handleTenantProvisioningSuccess(eventBody.detail); - case EventTypes.TENANT_PROVISIONING_FAILED: + case EventTypes.TENANT_PROVISIONING_FAILURE: return this.handleTenantProvisioningFailure(eventBody.detail); + case DefaultEventTypes.TENANT_DEPLOYMENT: + return this.handleTenantDeployment(eventBody); default: throw new Error(`Unsupported event type: ${eventType}`); } @@ -519,6 +525,14 @@ For example, In this provider you can implement any cleanup or notification need The way of binding this provider is similar to other provider, just the binding key is `OrchestratorServiceBindings.TENANT_PROVISIONING_FAILURE_HANDLER`. +#### 8. Tenant Deployment Provider + +This provider is intended to be the handler of the tenant deployment, which means any work after the provisioning that is required to make the tenant's application up and running, should be implemented here. + +For example, this can be adding some initial users. Populating some seed data in the application service etc. + +The way of binding this provider is similar to other provider, just the binding key is `OrchestratorServiceBindings.TENANT_DEPLOYMENT_HANDLER`. + ## Deployment The @arc-saas/orchestrator-service can be deployed in various ways, including as a serverless application. Here's how you can set it up for serverless deployment, specifically for AWS Lambda. diff --git a/services/orchestrator-service/src/__tests__/unit/component.unit.ts b/services/orchestrator-service/src/__tests__/unit/component.unit.ts index 16a8886..94d0bd8 100644 --- a/services/orchestrator-service/src/__tests__/unit/component.unit.ts +++ b/services/orchestrator-service/src/__tests__/unit/component.unit.ts @@ -11,6 +11,7 @@ import { OrchestratorService, BuilderService, TierDetailsFn, + TenantDeploymentHandlerProvider, } from './../../'; import {OrchestratorServiceComponent} from '../../component'; import {Provider} from '@loopback/context'; @@ -85,6 +86,8 @@ describe('OrchestratorServiceComponent', () => { TenantProvisioningSuccessHandlerProvider, [OrchestratorServiceBindings.TENANT_PROVISIONING_FAILURE_HANDLER.key]: TenantProvisioningFailureHandlerProvider, + [OrchestratorServiceBindings.TENANT_DEPLOYMENT_HANDLER.key]: + TenantDeploymentHandlerProvider, }; for (const [key] of Object.entries(providerMap)) { diff --git a/services/orchestrator-service/src/__tests__/unit/orchestrator-service.unit.ts b/services/orchestrator-service/src/__tests__/unit/orchestrator-service.unit.ts index fcd6bab..8fef3b1 100644 --- a/services/orchestrator-service/src/__tests__/unit/orchestrator-service.unit.ts +++ b/services/orchestrator-service/src/__tests__/unit/orchestrator-service.unit.ts @@ -6,6 +6,7 @@ import { TenantDeprovisioningHandler, TenantProvisioningSuccessHandler, TenantProvisioningFailureHandler, + TenantDeploymentHandler, } from '../..'; describe('OrchestratorService', () => { @@ -14,6 +15,7 @@ describe('OrchestratorService', () => { let tenantDeprovisioningHandlerStub: sinon.SinonStub; let tenantProvisioningSuccessHandlerStub: sinon.SinonStub; let tenantProvisioningFailureHandlerStub: sinon.SinonStub; + let tenantDeploymentHandlerStub: sinon.SinonStub; beforeEach(givenOrchestratorService); @@ -50,10 +52,10 @@ describe('OrchestratorService', () => { ).to.be.true(); }); - it('handles TENANT_PROVISIONING_FAILED event', async () => { + it('handles TENANT_PROVISIONING_FAILURE event', async () => { const eventBody = {tenantId: '123', error: 'Some error'}; await orchestratorService.handleEvent( - DefaultEventTypes.TENANT_PROVISIONING_FAILED, + DefaultEventTypes.TENANT_PROVISIONING_FAILURE, eventBody, ); expect( @@ -61,6 +63,18 @@ describe('OrchestratorService', () => { ).to.be.true(); }); + it('handles TENANT_DEPLOYMENT event', async () => { + const eventBody = { + tenantId: '123', + plan: {features: [{key: 'FEAT', value: 'FOO'}]}, + }; + await orchestratorService.handleEvent( + DefaultEventTypes.TENANT_DEPLOYMENT, + eventBody, + ); + expect(tenantDeploymentHandlerStub.calledOnceWith(eventBody)).to.be.true(); + }); + it('throws error for unsupported event type', async () => { const eventBody = {}; await expect( @@ -76,12 +90,14 @@ describe('OrchestratorService', () => { tenantDeprovisioningHandlerStub = sinon.stub(); tenantProvisioningSuccessHandlerStub = sinon.stub(); tenantProvisioningFailureHandlerStub = sinon.stub(); + tenantDeploymentHandlerStub = sinon.stub(); orchestratorService = new OrchestratorService( tenantProvisioningHandlerStub as unknown as TenantProvisioningHandler, tenantDeprovisioningHandlerStub as unknown as TenantDeprovisioningHandler, tenantProvisioningSuccessHandlerStub as unknown as TenantProvisioningSuccessHandler, tenantProvisioningFailureHandlerStub as unknown as TenantProvisioningFailureHandler, + tenantDeploymentHandlerStub as unknown as TenantDeploymentHandler, ); } }); diff --git a/services/orchestrator-service/src/component.ts b/services/orchestrator-service/src/component.ts index a88733a..f2e9a8e 100644 --- a/services/orchestrator-service/src/component.ts +++ b/services/orchestrator-service/src/component.ts @@ -19,6 +19,7 @@ import { TierDetailsProvider, TenantProvisioningSuccessHandlerProvider, TenantDeprovisioningHandlerProvider, + TenantDeploymentHandlerProvider, } from './services'; import {EventController} from './controllers'; import {RestApplication} from '@loopback/rest'; @@ -52,6 +53,8 @@ export class OrchestratorServiceComponent implements Component { TenantProvisioningSuccessHandlerProvider, [OrchestratorServiceBindings.TENANT_PROVISIONING_FAILURE_HANDLER.key]: TenantProvisioningFailureHandlerProvider, + [OrchestratorServiceBindings.TENANT_DEPLOYMENT_HANDLER.key]: + TenantDeploymentHandlerProvider, }); // Bind Service Classes if not provided by consumer of the component diff --git a/services/orchestrator-service/src/services/index.ts b/services/orchestrator-service/src/services/index.ts index d5790ba..b8ad43e 100644 --- a/services/orchestrator-service/src/services/index.ts +++ b/services/orchestrator-service/src/services/index.ts @@ -3,6 +3,7 @@ export * from './tenant-provisioning-handler.service'; export * from './tenant-provisioning-success-handler.service'; export * from './tenant-provisioning-failure-handler.service'; export * from './tenant-deprovisioning-handler.service'; +export * from './tenant-deployment-handler.service'; export * from './tier-details.service'; export * from './orchestrator.service'; export * from './types'; diff --git a/services/orchestrator-service/src/services/orchestrator.service.ts b/services/orchestrator-service/src/services/orchestrator.service.ts index 435d120..5583565 100644 --- a/services/orchestrator-service/src/services/orchestrator.service.ts +++ b/services/orchestrator-service/src/services/orchestrator.service.ts @@ -4,11 +4,14 @@ import { OrchestratorServiceBindings, OrchestratorServiceInterface, } from './types'; -import {TenantProvisioningHandler} from './tenant-provisioning-handler.service'; import {AnyObject} from '@loopback/repository'; -import {TenantDeprovisioningHandler} from './tenant-deprovisioning-handler.service'; -import {TenantProvisioningSuccessHandler} from './tenant-provisioning-success-handler.service'; -import {TenantProvisioningFailureHandler} from './tenant-provisioning-failure-handler.service'; +import { + TenantProvisioningHandler, + TenantDeprovisioningHandler, + TenantProvisioningSuccessHandler, + TenantProvisioningFailureHandler, + TenantDeploymentHandler, +} from './'; @injectable({scope: BindingScope.TRANSIENT}) export class OrchestratorService implements OrchestratorServiceInterface { @@ -21,6 +24,8 @@ export class OrchestratorService implements OrchestratorServiceInterface { private handleTenantProvisioningSuccess: TenantProvisioningSuccessHandler, @inject(OrchestratorServiceBindings.TENANT_PROVISIONING_FAILURE_HANDLER) private handleTenantProvisioningFailure: TenantProvisioningFailureHandler, + @inject(OrchestratorServiceBindings.TENANT_DEPLOYMENT_HANDLER) + private handleTenantDeployment: TenantDeploymentHandler, ) {} async handleEvent( @@ -34,8 +39,10 @@ export class OrchestratorService implements OrchestratorServiceInterface { return this.handleTenantDeprovisioning(eventBody); case DefaultEventTypes.TENANT_PROVISIONING_SUCCESS: return this.handleTenantProvisioningSuccess(eventBody); - case DefaultEventTypes.TENANT_PROVISIONING_FAILED: + case DefaultEventTypes.TENANT_PROVISIONING_FAILURE: return this.handleTenantProvisioningFailure(eventBody); + case DefaultEventTypes.TENANT_DEPLOYMENT: + return this.handleTenantDeployment(eventBody); default: throw new Error(`Unsupported event type: ${eventType}`); } diff --git a/services/orchestrator-service/src/services/tenant-deployment-handler.service.ts b/services/orchestrator-service/src/services/tenant-deployment-handler.service.ts new file mode 100644 index 0000000..428995c --- /dev/null +++ b/services/orchestrator-service/src/services/tenant-deployment-handler.service.ts @@ -0,0 +1,23 @@ +import {injectable, BindingScope, Provider} from '@loopback/core'; +import {AnyObject} from '@loopback/repository'; + +export type TenantDeploymentHandler = ( + body: T, +) => Promise; + +@injectable({scope: BindingScope.TRANSIENT}) +export class TenantDeploymentHandlerProvider + implements Provider +{ + constructor() {} + + value() { + return async (body: AnyObject) => this.handler(body); + } + + private async handler(body: AnyObject): Promise { + throw Error( + `${TenantDeploymentHandlerProvider.name} is not implemented. Follow the README for more details.`, + ); + } +} diff --git a/services/orchestrator-service/src/services/types.ts b/services/orchestrator-service/src/services/types.ts index 6fc3b41..caf7ada 100644 --- a/services/orchestrator-service/src/services/types.ts +++ b/services/orchestrator-service/src/services/types.ts @@ -5,6 +5,7 @@ import {TenantDeprovisioningHandler} from './tenant-deprovisioning-handler.servi import {AnyObject} from '@loopback/repository'; import {TenantProvisioningSuccessHandler} from './tenant-provisioning-success-handler.service'; import {TenantProvisioningFailureHandler} from './tenant-provisioning-failure-handler.service'; +import {TenantDeploymentHandler} from './tenant-deployment-handler.service'; const BINDING_PREFIX = `arc-saas`; @@ -26,7 +27,11 @@ export namespace OrchestratorServiceBindings { ); export const TENANT_PROVISIONING_FAILURE_HANDLER = BindingKey.create( - `${BINDING_PREFIX}.providers.tenant-provisioning-success-handler`, + `${BINDING_PREFIX}.providers.tenant-provisioning-failure-handler`, + ); + export const TENANT_DEPLOYMENT_HANDLER = + BindingKey.create( + `${BINDING_PREFIX}.providers.tenant-deployment-handler`, ); export const BUILDER_SERVICE = BindingKey.create( `${BINDING_PREFIX}.services.builder-service`, @@ -52,5 +57,9 @@ export enum DefaultEventTypes { TENANT_PROVISIONING = 'TENANT_PROVISIONING', TENANT_DEPROVISIONING = 'TENANT_DEPROVISIONING', TENANT_PROVISIONING_SUCCESS = 'TENANT_PROVISIONING_SUCCESS', - TENANT_PROVISIONING_FAILED = 'TENANT_PROVISIONING_FAILED', + TENANT_PROVISIONING_FAILURE = 'TENANT_PROVISIONING_FAILURE', + + TENANT_DEPLOYMENT = 'TENANT_DEPLOYMENT', + TENANT_DEPLOYMENT_SUCCESS = 'TENANT_DEPLOYMENT_SUCCESS', + TENANT_DEPLOYMENT_FAILURE = 'TENANT_DEPLOYMENT_FAILURE', } diff --git a/services/subscription-service/migrations/pg/migrations/20240805112128-remove-plan-items.js b/services/subscription-service/migrations/pg/migrations/20240805112128-remove-plan-items.js new file mode 100644 index 0000000..96581f3 --- /dev/null +++ b/services/subscription-service/migrations/pg/migrations/20240805112128-remove-plan-items.js @@ -0,0 +1,59 @@ +'use strict'; + +var dbm; +var type; +var seed; +var fs = require('fs'); +var path = require('path'); +var Promise; + +/** + * We receive the dbmigrate dependency from dbmigrate initially. + * This enables us to not have to rely on NODE_PATH. + */ +exports.setup = function (options, seedLink) { + dbm = options.dbmigrate; + type = dbm.dataType; + seed = seedLink; + Promise = options.Promise; +}; + +exports.up = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20240805112128-remove-plan-items-up.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports.down = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20240805112128-remove-plan-items-down.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports._meta = { + version: 1, +}; diff --git a/services/subscription-service/migrations/pg/migrations/20240805112316-add-plan-sizes-table.js b/services/subscription-service/migrations/pg/migrations/20240805112316-add-plan-sizes-table.js new file mode 100644 index 0000000..c9be0cc --- /dev/null +++ b/services/subscription-service/migrations/pg/migrations/20240805112316-add-plan-sizes-table.js @@ -0,0 +1,59 @@ +'use strict'; + +var dbm; +var type; +var seed; +var fs = require('fs'); +var path = require('path'); +var Promise; + +/** + * We receive the dbmigrate dependency from dbmigrate initially. + * This enables us to not have to rely on NODE_PATH. + */ +exports.setup = function (options, seedLink) { + dbm = options.dbmigrate; + type = dbm.dataType; + seed = seedLink; + Promise = options.Promise; +}; + +exports.up = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20240805112316-add-plan-sizes-table-up.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports.down = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20240805112316-add-plan-sizes-table-down.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports._meta = { + version: 1, +}; diff --git a/services/subscription-service/migrations/pg/migrations/20240805112817-add-plan-size-column.js b/services/subscription-service/migrations/pg/migrations/20240805112817-add-plan-size-column.js new file mode 100644 index 0000000..7de5b51 --- /dev/null +++ b/services/subscription-service/migrations/pg/migrations/20240805112817-add-plan-size-column.js @@ -0,0 +1,59 @@ +'use strict'; + +var dbm; +var type; +var seed; +var fs = require('fs'); +var path = require('path'); +var Promise; + +/** + * We receive the dbmigrate dependency from dbmigrate initially. + * This enables us to not have to rely on NODE_PATH. + */ +exports.setup = function (options, seedLink) { + dbm = options.dbmigrate; + type = dbm.dataType; + seed = seedLink; + Promise = options.Promise; +}; + +exports.up = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20240805112817-add-plan-size-column-up.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports.down = function (db) { + var filePath = path.join( + __dirname, + 'sqls', + '20240805112817-add-plan-size-column-down.sql', + ); + return new Promise(function (resolve, reject) { + fs.readFile(filePath, {encoding: 'utf-8'}, function (err, data) { + if (err) return reject(err); + console.log('received data: ' + data); + + resolve(data); + }); + }).then(function (data) { + return db.runSql(data); + }); +}; + +exports._meta = { + version: 1, +}; diff --git a/services/subscription-service/migrations/pg/migrations/sqls/20240208115049-add-tier-column-to-plans-up.sql b/services/subscription-service/migrations/pg/migrations/sqls/20240208115049-add-tier-column-to-plans-up.sql index 085f7c4..137b87a 100644 --- a/services/subscription-service/migrations/pg/migrations/sqls/20240208115049-add-tier-column-to-plans-up.sql +++ b/services/subscription-service/migrations/pg/migrations/sqls/20240208115049-add-tier-column-to-plans-up.sql @@ -1,2 +1,2 @@ -- add tier column to plans table -ALTER TABLE main.plans ADD COLUMN tier smallint DEFAULT 0 NOT NULL ; \ No newline at end of file +ALTER TABLE main.plans ADD COLUMN tier text NOT NULL; \ No newline at end of file diff --git a/services/subscription-service/migrations/pg/migrations/sqls/20240209122448-seed-data-up.sql b/services/subscription-service/migrations/pg/migrations/sqls/20240209122448-seed-data-up.sql index c58d713..c63126f 100644 --- a/services/subscription-service/migrations/pg/migrations/sqls/20240209122448-seed-data-up.sql +++ b/services/subscription-service/migrations/pg/migrations/sqls/20240209122448-seed-data-up.sql @@ -10,7 +10,7 @@ INSERT INTO main."plans"("name", created_on, created_by, description, price, cur FROM main.billing_cycles bb WHERE - cycle_name = 'MONTHLY'), 0); + cycle_name = 'MONTHLY'), "STANDARD"); INSERT INTO main."plans"("name", created_on, created_by, description, price, currency_id, meta_data, billing_cycle_id, tier) VALUES ('Premium', CURRENT_TIMESTAMP, '123e4567-e89b-12d3-a456-426614174002', 'Premium plan', 150,( @@ -24,7 +24,7 @@ INSERT INTO main."plans"("name", created_on, created_by, description, price, cur FROM main.billing_cycles bb WHERE - cycle_name = 'MONTHLY'), 1); + cycle_name = 'MONTHLY'), "PREMIUM"); INSERT INTO main.plan_items(created_on, created_by, "name", plan_item_type, plan_id, value) VALUES (CURRENT_TIMESTAMP, '123e4567-e89b-12d3-a456-426614174002', 'Database', 'database',( diff --git a/services/subscription-service/migrations/pg/migrations/sqls/20240805112128-remove-plan-items-down.sql b/services/subscription-service/migrations/pg/migrations/sqls/20240805112128-remove-plan-items-down.sql new file mode 100644 index 0000000..5ba84f3 --- /dev/null +++ b/services/subscription-service/migrations/pg/migrations/sqls/20240805112128-remove-plan-items-down.sql @@ -0,0 +1,16 @@ +CREATE TABLE plan_items ( + id uuid DEFAULT (md5(((random())::text || (clock_timestamp())::text)))::uuid NOT NULL , + created_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , + modified_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL , + deleted boolean DEFAULT false NOT NULL , + deleted_on timestamptz , + deleted_by uuid , + created_by uuid NOT NULL , + modified_by uuid , + name varchar(100) NOT NULL , + plan_item_type varchar(30) NOT NULL , + plan_id uuid NOT NULL , + value jsonb NOT NULL, + CONSTRAINT pk_plan_items_id PRIMARY KEY ( id ), + CONSTRAINT fk_plan_items_plans FOREIGN KEY ( plan_id ) REFERENCES plans( id ) +); \ No newline at end of file diff --git a/services/subscription-service/migrations/pg/migrations/sqls/20240805112128-remove-plan-items-up.sql b/services/subscription-service/migrations/pg/migrations/sqls/20240805112128-remove-plan-items-up.sql new file mode 100644 index 0000000..355fbb7 --- /dev/null +++ b/services/subscription-service/migrations/pg/migrations/sqls/20240805112128-remove-plan-items-up.sql @@ -0,0 +1 @@ +DROP TABLE main.plan_items; \ No newline at end of file diff --git a/services/subscription-service/migrations/pg/migrations/sqls/20240805112316-add-plan-sizes-table-down.sql b/services/subscription-service/migrations/pg/migrations/sqls/20240805112316-add-plan-sizes-table-down.sql new file mode 100644 index 0000000..5dd741c --- /dev/null +++ b/services/subscription-service/migrations/pg/migrations/sqls/20240805112316-add-plan-sizes-table-down.sql @@ -0,0 +1 @@ +DROP TABLE main.plan_sizes; \ No newline at end of file diff --git a/services/subscription-service/migrations/pg/migrations/sqls/20240805112316-add-plan-sizes-table-up.sql b/services/subscription-service/migrations/pg/migrations/sqls/20240805112316-add-plan-sizes-table-up.sql new file mode 100644 index 0000000..e755e8f --- /dev/null +++ b/services/subscription-service/migrations/pg/migrations/sqls/20240805112316-add-plan-sizes-table-up.sql @@ -0,0 +1,15 @@ +CREATE TABLE main.plan_sizes +( + id uuid DEFAULT (md5(((random())::text || (clock_timestamp())::text)))::uuid NOT NULL , + size text NOT NULL, + config jsonb, + PRIMARY KEY (id), + created_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL, + modified_on timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL, + deleted boolean DEFAULT false NOT NULL, + deleted_on timestamptz, + deleted_by uuid, + created_by uuid NOT NULL, + modified_by uuid, + CONSTRAINT unique_size_name UNIQUE (size) +); \ No newline at end of file diff --git a/services/subscription-service/migrations/pg/migrations/sqls/20240805112817-add-plan-size-column-down.sql b/services/subscription-service/migrations/pg/migrations/sqls/20240805112817-add-plan-size-column-down.sql new file mode 100644 index 0000000..cad66c0 --- /dev/null +++ b/services/subscription-service/migrations/pg/migrations/sqls/20240805112817-add-plan-size-column-down.sql @@ -0,0 +1 @@ +ALTER TABLE IF EXISTS main.plans DROP COLUMN IF EXISTS size; \ No newline at end of file diff --git a/services/subscription-service/migrations/pg/migrations/sqls/20240805112817-add-plan-size-column-up.sql b/services/subscription-service/migrations/pg/migrations/sqls/20240805112817-add-plan-size-column-up.sql new file mode 100644 index 0000000..3e64cf9 --- /dev/null +++ b/services/subscription-service/migrations/pg/migrations/sqls/20240805112817-add-plan-size-column-up.sql @@ -0,0 +1,2 @@ +ALTER TABLE IF EXISTS main.plans + ADD COLUMN size text; \ No newline at end of file diff --git a/services/subscription-service/src/__tests__/acceptance/mock-data.ts b/services/subscription-service/src/__tests__/acceptance/mock-data.ts index 73259ad..ed5d06b 100644 --- a/services/subscription-service/src/__tests__/acceptance/mock-data.ts +++ b/services/subscription-service/src/__tests__/acceptance/mock-data.ts @@ -1,6 +1,6 @@ import {DataObject} from '@loopback/repository'; -import {PlanTier, SubscriptionStatus} from '../../enums'; -import {Plan, PlanItem, Resource, Service, Subscription} from '../../models'; +import {SubscriptionStatus} from '../../enums'; +import {Plan, Resource, Service, Subscription} from '../../models'; export const mockService: DataObject = { name: 'test-service', @@ -31,15 +31,7 @@ export const mockPlan: DataObject = { price: 100, currencyId: 'currrency-id', billingCycleId: 'test-billing-id', - tier: PlanTier.POOLED, -}; - -export const mockPlanItem: DataObject = { - name: 'test-plan-item', - planItemType: 'test-type', - value: { - test: 'test', - }, + tier: 'Standard', }; export const mockSubscription: DataObject = { diff --git a/services/subscription-service/src/__tests__/acceptance/plan-item.controller.acceptance.ts b/services/subscription-service/src/__tests__/acceptance/plan-item.controller.acceptance.ts deleted file mode 100644 index 5bf8df7..0000000 --- a/services/subscription-service/src/__tests__/acceptance/plan-item.controller.acceptance.ts +++ /dev/null @@ -1,143 +0,0 @@ -import {mockPlanItem} from './mock-data'; -import {Client, expect} from '@loopback/testlab'; -import {SubscriptionServiceApplication} from '../..'; -import {PlanItem} from '../../models'; -import {PermissionKey} from '../../permissions'; -import {PlanItemRepository} from '../../repositories'; - -import {getRepo, getToken, setupApplication} from './test-helper'; -import {STATUS_CODE} from '@sourceloop/core'; - -const basePath = '/plan-items'; - -describe('PlanItemController', () => { - let app: SubscriptionServiceApplication; - let client: Client; - - let savedPlanItem: PlanItem; - let planItemRepo: PlanItemRepository; - const updatedName = 'updated-test'; - before('setupApplication', async () => { - ({app, client} = await setupApplication()); - planItemRepo = await getRepo(app, 'repositories.PlanItemRepository'); - }); - - after(async () => { - await app.stop(); - }); - - beforeEach(async () => { - await seedData(); - }); - - afterEach(async () => { - await planItemRepo.deleteAllHard(); - }); - - it('invokes POST /plan-items with valid token', async () => { - const token = getToken([PermissionKey.CreatePlanItem]); - const {body} = await client - .post(basePath) - .set('Authorization', token) - .send({...mockPlanItem, name: 'test2'}) - .expect(STATUS_CODE.OK); - expect(body.id).to.be.String(); - expect(body.name).to.eql('test2'); - }); - - it('invokes GET /plan-items with valid token', async () => { - const token = getToken([PermissionKey.ViewPlanItem]); - const {body} = await client - .get(basePath) - .set('Authorization', token) - .expect(STATUS_CODE.OK); - expect(body.length).to.eql(1); - expect(body[0].name).to.eql(mockPlanItem.name); - }); - - it('should not allow GET /plan-items with invalid token', async () => { - const token = getToken([PermissionKey.ViewSubscription]); - await client - .get(basePath) - .set('Authorization', token) - .expect(STATUS_CODE.FORBIDDEN); - }); - - it('invokes GET /plan-items/{id} with valid token', async () => { - const token = getToken([PermissionKey.ViewPlanItem]); - const {body} = await client - .get(`${basePath}/${savedPlanItem.id}`) - .set('Authorization', token) - .expect(STATUS_CODE.OK); - expect(body.name).to.eql(mockPlanItem.name); - }); - - it('invokes GET /plan-items/count with valid token', async () => { - const token = getToken([PermissionKey.ViewPlanItem]); - const {body} = await client - .get(`${basePath}/count`) - .set('Authorization', token) - .expect(STATUS_CODE.OK); - expect(body.count).to.eql(1); - }); - - it('invokes PUT /plan-items/{id} with valid token', async () => { - const token = getToken([PermissionKey.UpdatePlanItem]); - - await client - .put(`${basePath}/${savedPlanItem.id}`) - .set('Authorization', token) - .send({...savedPlanItem, name: updatedName, id: undefined}) - .expect(STATUS_CODE.NO_CONTENT); - - const updated = await planItemRepo.findById(savedPlanItem.id); - expect(updated?.name).to.eql(updatedName); - }); - - it('invokes PATCH /plan-items/{id} with valid token', async () => { - const token = getToken([PermissionKey.UpdatePlanItem]); - - await client - .patch(`${basePath}/${savedPlanItem.id}`) - .set('Authorization', token) - .send({name: updatedName}) - .expect(STATUS_CODE.NO_CONTENT); - - const updated = await planItemRepo.findById(savedPlanItem.id); - expect(updated?.name).to.eql(updatedName); - }); - - it('invokes PATCH /plan-items with valid token', async () => { - const token = getToken([PermissionKey.UpdatePlanItem]); - - const {body} = await client - .patch(`${basePath}`) - .set('Authorization', token) - .send({name: 'updated-test-all'}) - .expect(STATUS_CODE.OK); - - expect(body.count).to.eql(1); - const updated = await planItemRepo.findById(savedPlanItem.id); - expect(updated?.name).to.eql('updated-test-all'); - }); - - it('invokes DELETE /plan-items/{id} with valid token', async () => { - const token = getToken([PermissionKey.DeletePlanItem]); - - await client - .delete(`${basePath}/${savedPlanItem.id}`) - .set('Authorization', token) - .expect(STATUS_CODE.NO_CONTENT); - - try { - await planItemRepo.findById(savedPlanItem.id); - throw new Error('Plan not deleted'); - } catch (err) { - expect(err.status).to.eql(STATUS_CODE.NOT_FOUND); - } - }); - - async function seedData() { - savedPlanItem = await planItemRepo.create(mockPlanItem); - } -}); diff --git a/services/subscription-service/src/component.ts b/services/subscription-service/src/component.ts index b2902c9..9455848 100644 --- a/services/subscription-service/src/component.ts +++ b/services/subscription-service/src/component.ts @@ -32,8 +32,8 @@ import {ISubscriptionServiceConfig} from './types'; import { BillingCycleRepository, CurrencyRepository, - PlanItemRepository, PlanRepository, + PlanSizesRepository, ResourceRepository, ServiceRepository, SubscriptionRepository, @@ -44,7 +44,8 @@ import { HomePageController, PingController, PlanController, - PlanItemController, + PlanFeaturesController, + PlanSizesController, PlanSubscriptionController, ResourceController, ServiceController, @@ -53,8 +54,8 @@ import { import { BillingCycle, Currency, - PlanItem, Plan, + PlanSizes, Resource, Service, Subscription, @@ -85,7 +86,7 @@ export class SubscriptionServiceComponent implements Component { this.application.api({ openapi: '3.0.0', info: { - title: 'Audit Service', + title: 'Subscription Service', version: '1.0.0', }, paths: {}, @@ -103,21 +104,21 @@ export class SubscriptionServiceComponent implements Component { this.repositories = [ BillingCycleRepository, CurrencyRepository, - PlanItemRepository, PlanRepository, ResourceRepository, ServiceRepository, SubscriptionRepository, + PlanSizesRepository, ]; this.models = [ BillingCycle, Currency, - PlanItem, Plan, Resource, Service, Subscription, + PlanSizes, ]; this.controllers = [ @@ -125,12 +126,13 @@ export class SubscriptionServiceComponent implements Component { HomePageController, PingController, CurrencyController, - PlanItemController, PlanController, ResourceController, ServiceController, SubscriptionController, PlanSubscriptionController, + PlanSizesController, + PlanFeaturesController, ]; } diff --git a/services/subscription-service/src/controllers/index.ts b/services/subscription-service/src/controllers/index.ts index 2a24d93..7910a50 100644 --- a/services/subscription-service/src/controllers/index.ts +++ b/services/subscription-service/src/controllers/index.ts @@ -2,9 +2,10 @@ export * from './ping.controller'; export * from './home-page.controller'; export * from './subscription.controller'; export * from './plan.controller'; -export * from './plan-item.controller'; export * from './service.controller'; export * from './resource.controller'; export * from './billing-cycle.controller'; export * from './currency.controller'; export * from './plan-subscription.controller'; +export * from './plan-sizes.controller'; +export * from './plan-features.controller'; diff --git a/services/subscription-service/src/controllers/plan-features.controller.ts b/services/subscription-service/src/controllers/plan-features.controller.ts new file mode 100644 index 0000000..fd0f294 --- /dev/null +++ b/services/subscription-service/src/controllers/plan-features.controller.ts @@ -0,0 +1,215 @@ +import {authorize} from 'loopback4-authorization'; +import {PermissionKey} from '../permissions'; +import {authenticate, STRATEGY} from 'loopback4-authentication'; +import { + param, + get, + getModelSchemaRef, + post, + requestBody, + patch, +} from '@loopback/rest'; +import {OPERATION_SECURITY_SPEC, STATUS_CODE} from '@sourceloop/core'; +import {Plan} from '../models'; +import { + Feature, + FeatureRepository, + FeatureValues, + FeatureValuesRepository, +} from '@sourceloop/feature-toggle-service'; +import {DataObject, repository} from '@loopback/repository'; +import {PlanRepository} from '../repositories'; + +const basePath = 'plans/{id}/features'; + +export class PlanFeaturesController { + constructor( + @repository(PlanRepository) + public planRepository: PlanRepository, + @repository(FeatureValuesRepository) + public featureValuesRepository: FeatureValuesRepository, + @repository(FeatureRepository) + public featureRepository: FeatureRepository, + ) {} + + @authorize({ + permissions: [PermissionKey.ViewPlanFeatures], + }) + @authenticate(STRATEGY.BEARER, { + passReqToCallback: true, + }) + @get(basePath, { + security: OPERATION_SECURITY_SPEC, + responses: { + [STATUS_CODE.OK]: { + description: 'Plan Features Retrieved', + content: { + 'application/json': { + schema: { + ...getModelSchemaRef(Plan), + ...getModelSchemaRef(FeatureValues), + }, + }, + }, + }, + }, + }) + async getPlanFeatures(@param.path.string('id') id: string): Promise< + DataObject & { + features: DataObject[]; + } + > { + const plan = await this.planRepository.findById(id, { + fields: ['id', 'name', 'tier', 'size'], + }); + const allFeatures = await this.featureRepository.find({ + fields: [ + 'id', + 'key', + 'name', + 'description', + 'type', + 'defaultValue', + 'metadata', + ], + }); + + const features: DataObject[] = []; + + const featureValuesThePlanHas = await this.featureValuesRepository.find({ + where: { + strategyEntityId: id, + }, + fields: [ + 'id', + 'featureKey', + 'value', + 'status', + 'strategyEntityId', + 'strategyKey', + ], + }); + + for (const featDefinition of allFeatures) { + features.push({ + ...featDefinition, + value: featureValuesThePlanHas.find( + e => e.featureKey === featDefinition.id, + ), + }); + } + + return { + ...plan, + features: features, + }; + } + + @authorize({ + permissions: [PermissionKey.AddPlanFeatures], + }) + @authenticate(STRATEGY.BEARER, { + passReqToCallback: true, + }) + @post(basePath, { + security: OPERATION_SECURITY_SPEC, + responses: { + [STATUS_CODE.OK]: { + description: 'Plan Features Created', + content: { + 'application/json': { + schema: { + ...getModelSchemaRef(FeatureValues), + }, + }, + }, + }, + }, + }) + async setPlanFeatures( + @param.path.string('id') id: string, + @requestBody() + featureValues: FeatureValues[], + ): Promise { + const values = featureValues.map(e => { + e.strategyEntityId = id; + e.strategyKey = 'Plan'; + return e; + }); + return this.featureValuesRepository.createAll(values); + } + + @authorize({ + permissions: [PermissionKey.UpdatePlanFeatures], + }) + @authenticate(STRATEGY.BEARER, { + passReqToCallback: true, + }) + @patch(basePath, { + security: OPERATION_SECURITY_SPEC, + responses: { + [STATUS_CODE.OK]: { + description: 'Plan Features Updated', + content: { + 'application/json': { + schema: { + type: 'array', + items: getModelSchemaRef(FeatureValues), + }, + }, + }, + }, + }, + }) + async updatePlanFeatures( + @param.path.string('id') id: string, + @requestBody({ + content: { + 'application/json': { + schema: { + type: 'array', + items: getModelSchemaRef(FeatureValues, {partial: true}), + }, + }, + }, + }) + featureValues: Partial[], + ): Promise { + const updatedFeatures: FeatureValues[] = []; + + for (const featureValue of featureValues) { + if (!featureValue.id) { + throw new Error('Feature value ID is required for update'); + } + + // Ensure the feature value belongs to the specified plan + const existingFeatureValue = await this.featureValuesRepository.findOne({ + where: { + id: featureValue.id, + strategyEntityId: id, + strategyKey: 'Plan', + }, + }); + + if (!existingFeatureValue) { + throw new Error( + `Feature value with ID ${featureValue.id} not found for this plan`, + ); + } + + // Update the feature value + await this.featureValuesRepository.updateById( + featureValue.id, + featureValue, + ); + + // Fetch the updated feature value + const updatedFeatureValue = await this.featureValuesRepository.findById( + featureValue.id, + ); + updatedFeatures.push(updatedFeatureValue); + } + + return updatedFeatures; + } +} diff --git a/services/subscription-service/src/controllers/plan-item.controller.ts b/services/subscription-service/src/controllers/plan-sizes.controller.ts similarity index 57% rename from services/subscription-service/src/controllers/plan-item.controller.ts rename to services/subscription-service/src/controllers/plan-sizes.controller.ts index 1a99731..c880999 100644 --- a/services/subscription-service/src/controllers/plan-item.controller.ts +++ b/services/subscription-service/src/controllers/plan-sizes.controller.ts @@ -16,22 +16,23 @@ import { del, requestBody, } from '@loopback/rest'; -import {PlanItem} from '../models'; -import {PlanItemRepository} from '../repositories'; +import {PlanSizes} from '../models'; +import {PlanSizesRepository} from '../repositories'; import {authorize} from 'loopback4-authorization'; -import {authenticate, STRATEGY} from 'loopback4-authentication'; import {PermissionKey} from '../permissions'; +import {authenticate, STRATEGY} from 'loopback4-authentication'; import {OPERATION_SECURITY_SPEC, STATUS_CODE} from '@sourceloop/core'; -const basePath = '/plan-items'; -export class PlanItemController { +const basePath = '/plan-sizes'; + +export class PlanSizesController { constructor( - @repository(PlanItemRepository) - public planItemRepository: PlanItemRepository, + @repository(PlanSizesRepository) + public planSizesRepository: PlanSizesRepository, ) {} @authorize({ - permissions: [PermissionKey.CreatePlanItem], + permissions: [PermissionKey.CreatePlanSizes], }) @authenticate(STRATEGY.BEARER, { passReqToCallback: true, @@ -40,10 +41,8 @@ export class PlanItemController { security: OPERATION_SECURITY_SPEC, responses: { [STATUS_CODE.OK]: { - description: 'PlanItem model instance', - content: { - 'application/json': {schema: getModelSchemaRef(PlanItem)}, - }, + description: 'PlanSizes model instance', + content: {'application/json': {schema: getModelSchemaRef(PlanSizes)}}, }, }, }) @@ -51,20 +50,20 @@ export class PlanItemController { @requestBody({ content: { 'application/json': { - schema: getModelSchemaRef(PlanItem, { - title: 'NewPlanItem', + schema: getModelSchemaRef(PlanSizes, { + title: 'NewPlanSizes', exclude: ['id'], }), }, }, }) - planItem: Omit, - ): Promise { - return this.planItemRepository.create(planItem); + planSizes: Omit, + ): Promise { + return this.planSizesRepository.create(planSizes); } @authorize({ - permissions: [PermissionKey.ViewPlanItem], + permissions: [PermissionKey.ViewPlanSizes], }) @authenticate(STRATEGY.BEARER, { passReqToCallback: true, @@ -73,17 +72,19 @@ export class PlanItemController { security: OPERATION_SECURITY_SPEC, responses: { [STATUS_CODE.OK]: { - description: 'PlanItem model count', + description: 'PlanSizes model count', content: {'application/json': {schema: CountSchema}}, }, }, }) - async count(@param.where(PlanItem) where?: Where): Promise { - return this.planItemRepository.count(where); + async count( + @param.where(PlanSizes) where?: Where, + ): Promise { + return this.planSizesRepository.count(where); } @authorize({ - permissions: [PermissionKey.ViewPlanItem], + permissions: [PermissionKey.ViewPlanSizes], }) @authenticate(STRATEGY.BEARER, { passReqToCallback: true, @@ -92,12 +93,12 @@ export class PlanItemController { security: OPERATION_SECURITY_SPEC, responses: { [STATUS_CODE.OK]: { - description: 'Array of PlanItem model instances', + description: 'Array of PlanSizes model instances', content: { 'application/json': { schema: { type: 'array', - items: getModelSchemaRef(PlanItem, {includeRelations: true}), + items: getModelSchemaRef(PlanSizes, {includeRelations: true}), }, }, }, @@ -105,13 +106,13 @@ export class PlanItemController { }, }) async find( - @param.filter(PlanItem) filter?: Filter, - ): Promise { - return this.planItemRepository.find(filter); + @param.filter(PlanSizes) filter?: Filter, + ): Promise { + return this.planSizesRepository.find(filter); } @authorize({ - permissions: [PermissionKey.UpdatePlanItem], + permissions: [PermissionKey.UpdatePlanSizes], }) @authenticate(STRATEGY.BEARER, { passReqToCallback: true, @@ -120,7 +121,7 @@ export class PlanItemController { security: OPERATION_SECURITY_SPEC, responses: { [STATUS_CODE.OK]: { - description: 'PlanItem PATCH success count', + description: 'PlanSizes PATCH success count', content: {'application/json': {schema: CountSchema}}, }, }, @@ -129,18 +130,18 @@ export class PlanItemController { @requestBody({ content: { 'application/json': { - schema: getModelSchemaRef(PlanItem, {partial: true}), + schema: getModelSchemaRef(PlanSizes, {partial: true}), }, }, }) - planItem: PlanItem, - @param.where(PlanItem) where?: Where, + planSizes: PlanSizes, + @param.where(PlanSizes) where?: Where, ): Promise { - return this.planItemRepository.updateAll(planItem, where); + return this.planSizesRepository.updateAll(planSizes, where); } @authorize({ - permissions: [PermissionKey.ViewPlanItem], + permissions: [PermissionKey.ViewPlanSizes], }) @authenticate(STRATEGY.BEARER, { passReqToCallback: true, @@ -149,10 +150,10 @@ export class PlanItemController { security: OPERATION_SECURITY_SPEC, responses: { [STATUS_CODE.OK]: { - description: 'PlanItem model instance', + description: 'PlanSizes model instance', content: { 'application/json': { - schema: getModelSchemaRef(PlanItem, {includeRelations: true}), + schema: getModelSchemaRef(PlanSizes, {includeRelations: true}), }, }, }, @@ -160,14 +161,14 @@ export class PlanItemController { }) async findById( @param.path.string('id') id: string, - @param.filter(PlanItem, {exclude: 'where'}) - filter?: FilterExcludingWhere, - ): Promise { - return this.planItemRepository.findById(id, filter); + @param.filter(PlanSizes, {exclude: 'where'}) + filter?: FilterExcludingWhere, + ): Promise { + return this.planSizesRepository.findById(id, filter); } @authorize({ - permissions: [PermissionKey.UpdatePlanItem], + permissions: [PermissionKey.UpdatePlanSizes], }) @authenticate(STRATEGY.BEARER, { passReqToCallback: true, @@ -176,7 +177,7 @@ export class PlanItemController { security: OPERATION_SECURITY_SPEC, responses: { [STATUS_CODE.NO_CONTENT]: { - description: 'PlanItem PATCH success', + description: 'PlanSizes PATCH success', }, }, }) @@ -185,17 +186,17 @@ export class PlanItemController { @requestBody({ content: { 'application/json': { - schema: getModelSchemaRef(PlanItem, {partial: true}), + schema: getModelSchemaRef(PlanSizes, {partial: true}), }, }, }) - planItem: PlanItem, + planSizes: PlanSizes, ): Promise { - await this.planItemRepository.updateById(id, planItem); + await this.planSizesRepository.updateById(id, planSizes); } @authorize({ - permissions: [PermissionKey.UpdatePlanItem], + permissions: [PermissionKey.UpdatePlanSizes], }) @authenticate(STRATEGY.BEARER, { passReqToCallback: true, @@ -204,19 +205,19 @@ export class PlanItemController { security: OPERATION_SECURITY_SPEC, responses: { [STATUS_CODE.NO_CONTENT]: { - description: 'PlanItem PUT success', + description: 'PlanSizes PUT success', }, }, }) async replaceById( @param.path.string('id') id: string, - @requestBody() planItem: PlanItem, + @requestBody() planSizes: PlanSizes, ): Promise { - await this.planItemRepository.replaceById(id, planItem); + await this.planSizesRepository.replaceById(id, planSizes); } @authorize({ - permissions: [PermissionKey.DeletePlanItem], + permissions: [PermissionKey.DeletePlanSizes], }) @authenticate(STRATEGY.BEARER, { passReqToCallback: true, @@ -225,11 +226,11 @@ export class PlanItemController { security: OPERATION_SECURITY_SPEC, responses: { [STATUS_CODE.NO_CONTENT]: { - description: 'PlanItem DELETE success', + description: 'PlanSizes DELETE success', }, }, }) async deleteById(@param.path.string('id') id: string): Promise { - await this.planItemRepository.deleteById(id); + await this.planSizesRepository.deleteById(id); } } diff --git a/services/subscription-service/src/enums/index.ts b/services/subscription-service/src/enums/index.ts index 26539c7..f908ad7 100644 --- a/services/subscription-service/src/enums/index.ts +++ b/services/subscription-service/src/enums/index.ts @@ -1,3 +1,2 @@ export * from './billing-cycle.enum'; export * from './subscription-status.enum'; -export * from './plans-tier.enum'; diff --git a/services/subscription-service/src/enums/plans-tier.enum.ts b/services/subscription-service/src/enums/plans-tier.enum.ts deleted file mode 100644 index acc3154..0000000 --- a/services/subscription-service/src/enums/plans-tier.enum.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum PlanTier { - POOLED, - SILO, -} diff --git a/services/subscription-service/src/models/index.ts b/services/subscription-service/src/models/index.ts index 1685546..0dc32c6 100644 --- a/services/subscription-service/src/models/index.ts +++ b/services/subscription-service/src/models/index.ts @@ -1,7 +1,7 @@ export * from './plan.model'; export * from './subscription.model'; -export * from './plan-item.model'; export * from './service.model'; export * from './resource.model'; export * from './billing-cycle.model'; export * from './currency.model'; +export * from './plan-sizes.model'; diff --git a/services/subscription-service/src/models/plan-item.model.ts b/services/subscription-service/src/models/plan-item.model.ts deleted file mode 100644 index 7fdec65..0000000 --- a/services/subscription-service/src/models/plan-item.model.ts +++ /dev/null @@ -1,53 +0,0 @@ -import {belongsTo, model, property} from '@loopback/repository'; -import {UserModifiableEntity} from '@sourceloop/core'; -import {Plan} from './plan.model'; - -@model({ - name: 'plan_items', -}) -export class PlanItem extends UserModifiableEntity { - @property({ - type: 'string', - id: true, - generated: true, - }) - id: string; - - @property({ - type: 'string', - required: true, - description: 'name of the plan item', - }) - name: string; - - @property({ - type: 'string', - required: true, - name: 'plan_item_type', - description: 'type of the plan item', - }) - planItemType: string; - - @property({ - type: 'object', - required: true, - description: 'value of the plan item', - }) - value: object; - - @belongsTo(() => Plan, undefined, { - description: 'plan id of the plan item', - name: 'plan_id', - }) - planId: string; - - constructor(data?: Partial) { - super(data); - } -} - -export interface PlanItemRelations { - plan: Plan; -} - -export type PlanItemWithRelations = PlanItem & PlanItemRelations; diff --git a/services/subscription-service/src/models/plan-sizes.model.ts b/services/subscription-service/src/models/plan-sizes.model.ts new file mode 100644 index 0000000..77b7f81 --- /dev/null +++ b/services/subscription-service/src/models/plan-sizes.model.ts @@ -0,0 +1,33 @@ +import {model, property} from '@loopback/repository'; +import {UserModifiableEntity} from '@sourceloop/core'; + +@model({ + name: 'plan_sizes', +}) +export class PlanSizes extends UserModifiableEntity { + @property({ + type: 'string', + id: true, + generated: true, + }) + id: string; + + @property({ + type: 'string', + required: true, + }) + size: string; + + @property({ + type: 'object', + }) + config?: object; + + constructor(data?: Partial) { + super(data); + } +} + +export interface PlanSizesRelations {} + +export type PlanSizesWithRelations = PlanSizes; diff --git a/services/subscription-service/src/models/plan.model.ts b/services/subscription-service/src/models/plan.model.ts index 4d074c1..9002c06 100644 --- a/services/subscription-service/src/models/plan.model.ts +++ b/services/subscription-service/src/models/plan.model.ts @@ -1,10 +1,7 @@ -import {model, property, hasMany, belongsTo} from '@loopback/repository'; +import {model, property, belongsTo} from '@loopback/repository'; import {UserModifiableEntity} from '@sourceloop/core'; -import {PlanItem} from './plan-item.model'; import {BillingCycle} from './billing-cycle.model'; import {Currency} from './currency.model'; -import {numericEnumValues} from '../utils'; -import {PlanTier} from '../enums'; @model({ name: 'plans', @@ -31,29 +28,30 @@ export class Plan extends UserModifiableEntity { description?: string; @property({ - type: 'number', + type: 'string', required: true, - description: 'Tier of the plan, it can be - 0(Pooled) and 1(Silo)', - jsonSchema: { - enum: numericEnumValues(PlanTier), - }, - default: PlanTier.POOLED, + description: 'Tier of the plan.', }) - tier: PlanTier; + tier: string; + + @property({ + type: 'string', + description: 'Size of the plan.', + }) + size?: string; @property({ type: 'number', required: true, }) price: number; + @property({ type: 'object', name: 'meta_data', description: 'Meta data of the plan', }) metaData?: object; - @hasMany(() => PlanItem, {keyTo: 'planId'}) - planItems: PlanItem; @belongsTo( () => BillingCycle, @@ -76,8 +74,6 @@ export class Plan extends UserModifiableEntity { } } -export interface PlanRelations { - planItems: PlanItem[]; -} +export interface PlanRelations {} -export type PlanWithRelations = Plan & PlanRelations; +export type PlanWithRelations = Plan; diff --git a/services/subscription-service/src/openapi.json b/services/subscription-service/src/openapi.json index e7a74f8..8914c5e 100644 --- a/services/subscription-service/src/openapi.json +++ b/services/subscription-service/src/openapi.json @@ -1,9 +1,9 @@ { "openapi": "3.0.0", "info": { - "title": "subscription-service", + "title": "Subscription Service", "version": "1.0.0", - "description": "subscription-service", + "description": "Subscription management microservice for SaaS control plane", "contact": { "name": "Sourcefuse" } @@ -13,7 +13,9 @@ "get": { "x-controller-name": "BillinCycleController", "x-operation-name": "count", - "tags": ["BillinCycleController"], + "tags": [ + "BillinCycleController" + ], "security": [ { "HTTPBearer": [] @@ -55,7 +57,9 @@ "put": { "x-controller-name": "BillinCycleController", "x-operation-name": "replaceById", - "tags": ["BillinCycleController"], + "tags": [ + "BillinCycleController" + ], "security": [ { "HTTPBearer": [] @@ -92,7 +96,9 @@ "patch": { "x-controller-name": "BillinCycleController", "x-operation-name": "updateById", - "tags": ["BillinCycleController"], + "tags": [ + "BillinCycleController" + ], "security": [ { "HTTPBearer": [] @@ -129,7 +135,9 @@ "get": { "x-controller-name": "BillinCycleController", "x-operation-name": "findById", - "tags": ["BillinCycleController"], + "tags": [ + "BillinCycleController" + ], "security": [ { "HTTPBearer": [] @@ -174,7 +182,9 @@ "delete": { "x-controller-name": "BillinCycleController", "x-operation-name": "deleteById", - "tags": ["BillinCycleController"], + "tags": [ + "BillinCycleController" + ], "security": [ { "HTTPBearer": [] @@ -203,7 +213,9 @@ "post": { "x-controller-name": "BillinCycleController", "x-operation-name": "create", - "tags": ["BillinCycleController"], + "tags": [ + "BillinCycleController" + ], "security": [ { "HTTPBearer": [] @@ -236,7 +248,9 @@ "patch": { "x-controller-name": "BillinCycleController", "x-operation-name": "updateAll", - "tags": ["BillinCycleController"], + "tags": [ + "BillinCycleController" + ], "security": [ { "HTTPBearer": [] @@ -285,7 +299,9 @@ "get": { "x-controller-name": "BillinCycleController", "x-operation-name": "find", - "tags": ["BillinCycleController"], + "tags": [ + "BillinCycleController" + ], "security": [ { "HTTPBearer": [] @@ -327,7 +343,9 @@ "get": { "x-controller-name": "CurrencyController", "x-operation-name": "count", - "tags": ["CurrencyController"], + "tags": [ + "CurrencyController" + ], "security": [ { "HTTPBearer": [] @@ -369,7 +387,9 @@ "put": { "x-controller-name": "CurrencyController", "x-operation-name": "replaceById", - "tags": ["CurrencyController"], + "tags": [ + "CurrencyController" + ], "security": [ { "HTTPBearer": [] @@ -406,7 +426,9 @@ "patch": { "x-controller-name": "CurrencyController", "x-operation-name": "updateById", - "tags": ["CurrencyController"], + "tags": [ + "CurrencyController" + ], "security": [ { "HTTPBearer": [] @@ -443,7 +465,9 @@ "get": { "x-controller-name": "CurrencyController", "x-operation-name": "findById", - "tags": ["CurrencyController"], + "tags": [ + "CurrencyController" + ], "security": [ { "HTTPBearer": [] @@ -488,7 +512,9 @@ "delete": { "x-controller-name": "CurrencyController", "x-operation-name": "deleteById", - "tags": ["CurrencyController"], + "tags": [ + "CurrencyController" + ], "security": [ { "HTTPBearer": [] @@ -517,7 +543,9 @@ "post": { "x-controller-name": "CurrencyController", "x-operation-name": "create", - "tags": ["CurrencyController"], + "tags": [ + "CurrencyController" + ], "security": [ { "HTTPBearer": [] @@ -550,7 +578,9 @@ "patch": { "x-controller-name": "CurrencyController", "x-operation-name": "updateAll", - "tags": ["CurrencyController"], + "tags": [ + "CurrencyController" + ], "security": [ { "HTTPBearer": [] @@ -599,7 +629,9 @@ "get": { "x-controller-name": "CurrencyController", "x-operation-name": "find", - "tags": ["CurrencyController"], + "tags": [ + "CurrencyController" + ], "security": [ { "HTTPBearer": [] @@ -637,32 +669,13 @@ "operationId": "CurrencyController.find" } }, - "/ping": { - "get": { - "x-controller-name": "PingController", - "x-operation-name": "ping", - "tags": ["PingController"], - "responses": { - "200": { - "description": "Ping Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PingResponse" - } - } - } - } - }, - "description": "", - "operationId": "PingController.ping" - } - }, - "/plan-items/count": { + "/feature-values/count": { "get": { - "x-controller-name": "PlanItemController", + "x-controller-name": "FeatureValuesController", "x-operation-name": "count", - "tags": ["PlanItemController"], + "tags": [ + "FeatureValuesController" + ], "security": [ { "HTTPBearer": [] @@ -670,7 +683,7 @@ ], "responses": { "200": { - "description": "PlanItem model count", + "description": "FeatureValues model count", "content": { "application/json": { "schema": { @@ -680,7 +693,7 @@ } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7012 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| ViewFeatureValues |\n| 9 |\n", "parameters": [ { "name": "where", @@ -689,22 +702,24 @@ "application/json": { "schema": { "type": "object", - "title": "plan_items.WhereFilter", + "title": "feature_values.WhereFilter", "additionalProperties": true, - "x-typescript-type": "@loopback/repository#Where" + "x-typescript-type": "@loopback/repository#Where" } } } } ], - "operationId": "PlanItemController.count" + "operationId": "FeatureValuesController.count" } }, - "/plan-items/{id}": { + "/feature-values/{id}": { "put": { - "x-controller-name": "PlanItemController", + "x-controller-name": "FeatureValuesController", "x-operation-name": "replaceById", - "tags": ["PlanItemController"], + "tags": [ + "FeatureValuesController" + ], "security": [ { "HTTPBearer": [] @@ -712,10 +727,10 @@ ], "responses": { "204": { - "description": "PlanItem PUT success" + "description": "FeatureValues PUT success" } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7010 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| UpdateFeatureValues |\n| 11 |\n", "parameters": [ { "name": "id", @@ -730,18 +745,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PlanItem" + "$ref": "#/components/schemas/FeatureValues" } } }, "x-parameter-index": 1 }, - "operationId": "PlanItemController.replaceById" + "operationId": "FeatureValuesController.replaceById" }, "patch": { - "x-controller-name": "PlanItemController", + "x-controller-name": "FeatureValuesController", "x-operation-name": "updateById", - "tags": ["PlanItemController"], + "tags": [ + "FeatureValuesController" + ], "security": [ { "HTTPBearer": [] @@ -749,10 +766,10 @@ ], "responses": { "204": { - "description": "PlanItem PATCH success" + "description": "FeatureValues PATCH success" } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7010 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| UpdateFeatureValues |\n| 11 |\n", "parameters": [ { "name": "id", @@ -767,18 +784,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PlanItemPartial" + "$ref": "#/components/schemas/FeatureValuesPartial" } } }, "x-parameter-index": 1 }, - "operationId": "PlanItemController.updateById" + "operationId": "FeatureValuesController.updateById" }, "get": { - "x-controller-name": "PlanItemController", + "x-controller-name": "FeatureValuesController", "x-operation-name": "findById", - "tags": ["PlanItemController"], + "tags": [ + "FeatureValuesController" + ], "security": [ { "HTTPBearer": [] @@ -786,17 +805,17 @@ ], "responses": { "200": { - "description": "PlanItem model instance", + "description": "FeatureValues model instance", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PlanItemWithRelations" + "$ref": "#/components/schemas/FeatureValuesWithRelations" } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7012 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| ViewFeatureValues |\n| 9 |\n", "parameters": [ { "name": "id", @@ -812,18 +831,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/plan_items.Filter" + "$ref": "#/components/schemas/feature_values.Filter" } } } } ], - "operationId": "PlanItemController.findById" + "operationId": "FeatureValuesController.findById" }, "delete": { - "x-controller-name": "PlanItemController", + "x-controller-name": "FeatureValuesController", "x-operation-name": "deleteById", - "tags": ["PlanItemController"], + "tags": [ + "FeatureValuesController" + ], "security": [ { "HTTPBearer": [] @@ -831,10 +852,10 @@ ], "responses": { "204": { - "description": "PlanItem DELETE success" + "description": "FeatureValues DELETE success" } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7011 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| DeleteFeatureValues |\n| 12 |\n", "parameters": [ { "name": "id", @@ -845,14 +866,16 @@ "required": true } ], - "operationId": "PlanItemController.deleteById" + "operationId": "FeatureValuesController.deleteById" } }, - "/plan-items": { + "/feature-values": { "post": { - "x-controller-name": "PlanItemController", + "x-controller-name": "FeatureValuesController", "x-operation-name": "create", - "tags": ["PlanItemController"], + "tags": [ + "FeatureValuesController" + ], "security": [ { "HTTPBearer": [] @@ -860,32 +883,34 @@ ], "responses": { "200": { - "description": "PlanItem model instance", + "description": "FeatureValues model instance", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PlanItem" + "$ref": "#/components/schemas/FeatureValues" } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7009 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| CreateFeatureValues |\n| 10 |\n", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NewPlanItem" + "$ref": "#/components/schemas/NewFeatureValues" } } } }, - "operationId": "PlanItemController.create" + "operationId": "FeatureValuesController.create" }, "patch": { - "x-controller-name": "PlanItemController", + "x-controller-name": "FeatureValuesController", "x-operation-name": "updateAll", - "tags": ["PlanItemController"], + "tags": [ + "FeatureValuesController" + ], "security": [ { "HTTPBearer": [] @@ -893,7 +918,7 @@ ], "responses": { "200": { - "description": "PlanItem PATCH success count", + "description": "FeatureValues PATCH success count", "content": { "application/json": { "schema": { @@ -903,7 +928,7 @@ } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7010 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| UpdateFeatureValues |\n| 11 |\n", "parameters": [ { "name": "where", @@ -912,9 +937,9 @@ "application/json": { "schema": { "type": "object", - "title": "plan_items.WhereFilter", + "title": "feature_values.WhereFilter", "additionalProperties": true, - "x-typescript-type": "@loopback/repository#Where" + "x-typescript-type": "@loopback/repository#Where" } } } @@ -924,17 +949,19 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PlanItemPartial" + "$ref": "#/components/schemas/FeatureValuesPartial" } } } }, - "operationId": "PlanItemController.updateAll" + "operationId": "FeatureValuesController.updateAll" }, "get": { - "x-controller-name": "PlanItemController", + "x-controller-name": "FeatureValuesController", "x-operation-name": "find", - "tags": ["PlanItemController"], + "tags": [ + "FeatureValuesController" + ], "security": [ { "HTTPBearer": [] @@ -942,20 +969,20 @@ ], "responses": { "200": { - "description": "Array of PlanItem model instances", + "description": "Array of FeatureValues model instances", "content": { "application/json": { "schema": { "type": "array", "items": { - "$ref": "#/components/schemas/PlanItemWithRelations" + "$ref": "#/components/schemas/FeatureValuesWithRelations" } } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7012 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| ViewFeatureValues |\n| 9 |\n", "parameters": [ { "name": "filter", @@ -963,20 +990,22 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/plan_items.Filter1" + "$ref": "#/components/schemas/feature_values.Filter1" } } } } ], - "operationId": "PlanItemController.find" + "operationId": "FeatureValuesController.find" } }, - "/plans/count": { + "/features/count": { "get": { - "x-controller-name": "PlanController", + "x-controller-name": "FeatureController", "x-operation-name": "count", - "tags": ["PlanController"], + "tags": [ + "FeatureController" + ], "security": [ { "HTTPBearer": [] @@ -984,7 +1013,7 @@ ], "responses": { "200": { - "description": "Plan model count", + "description": "Feature model count", "content": { "application/json": { "schema": { @@ -994,7 +1023,7 @@ } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7008 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| ViewFeature |\n| 1 |\n", "parameters": [ { "name": "where", @@ -1003,22 +1032,24 @@ "application/json": { "schema": { "type": "object", - "title": "plans.WhereFilter", + "title": "features.WhereFilter", "additionalProperties": true, - "x-typescript-type": "@loopback/repository#Where" + "x-typescript-type": "@loopback/repository#Where" } } } } ], - "operationId": "PlanController.count" + "operationId": "FeatureController.count" } }, - "/plans/{id}": { + "/features/{id}": { "put": { - "x-controller-name": "PlanController", + "x-controller-name": "FeatureController", "x-operation-name": "replaceById", - "tags": ["PlanController"], + "tags": [ + "FeatureController" + ], "security": [ { "HTTPBearer": [] @@ -1026,10 +1057,10 @@ ], "responses": { "204": { - "description": "Plan PUT success" + "description": "Feature PUT success" } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7006 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| UpdateFeature |\n| 3 |\n", "parameters": [ { "name": "id", @@ -1044,18 +1075,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Plan" + "$ref": "#/components/schemas/Feature" } } }, "x-parameter-index": 1 }, - "operationId": "PlanController.replaceById" + "operationId": "FeatureController.replaceById" }, "patch": { - "x-controller-name": "PlanController", + "x-controller-name": "FeatureController", "x-operation-name": "updateById", - "tags": ["PlanController"], + "tags": [ + "FeatureController" + ], "security": [ { "HTTPBearer": [] @@ -1063,10 +1096,10 @@ ], "responses": { "204": { - "description": "Plan PATCH success" + "description": "Feature PATCH success" } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7006 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| UpdateFeature |\n| 3 |\n", "parameters": [ { "name": "id", @@ -1081,18 +1114,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PlanPartial" + "$ref": "#/components/schemas/FeaturePartial" } } }, "x-parameter-index": 1 }, - "operationId": "PlanController.updateById" + "operationId": "FeatureController.updateById" }, "get": { - "x-controller-name": "PlanController", + "x-controller-name": "FeatureController", "x-operation-name": "findById", - "tags": ["PlanController"], + "tags": [ + "FeatureController" + ], "security": [ { "HTTPBearer": [] @@ -1100,17 +1135,17 @@ ], "responses": { "200": { - "description": "Plan model instance", + "description": "Feature model instance", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PlanWithRelations" + "$ref": "#/components/schemas/FeatureWithRelations" } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7008 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| ViewFeature |\n| 1 |\n", "parameters": [ { "name": "id", @@ -1126,18 +1161,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/plans.Filter" + "$ref": "#/components/schemas/features.Filter" } } } } ], - "operationId": "PlanController.findById" + "operationId": "FeatureController.findById" }, "delete": { - "x-controller-name": "PlanController", + "x-controller-name": "FeatureController", "x-operation-name": "deleteById", - "tags": ["PlanController"], + "tags": [ + "FeatureController" + ], "security": [ { "HTTPBearer": [] @@ -1145,10 +1182,10 @@ ], "responses": { "204": { - "description": "Plan DELETE success" + "description": "Feature DELETE success" } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7007 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| DeleteFeature |\n| 4 |\n", "parameters": [ { "name": "id", @@ -1159,14 +1196,16 @@ "required": true } ], - "operationId": "PlanController.deleteById" + "operationId": "FeatureController.deleteById" } }, - "/plans": { + "/features": { "post": { - "x-controller-name": "PlanController", + "x-controller-name": "FeatureController", "x-operation-name": "create", - "tags": ["PlanController"], + "tags": [ + "FeatureController" + ], "security": [ { "HTTPBearer": [] @@ -1174,32 +1213,34 @@ ], "responses": { "200": { - "description": "Plan model instance", + "description": "Feature model instance", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Plan" + "$ref": "#/components/schemas/Feature" } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7005 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| CreateFeature |\n| 2 |\n", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NewPlan" + "$ref": "#/components/schemas/NewFeature" } } } }, - "operationId": "PlanController.create" + "operationId": "FeatureController.create" }, "patch": { - "x-controller-name": "PlanController", + "x-controller-name": "FeatureController", "x-operation-name": "updateAll", - "tags": ["PlanController"], + "tags": [ + "FeatureController" + ], "security": [ { "HTTPBearer": [] @@ -1207,7 +1248,7 @@ ], "responses": { "200": { - "description": "Plan PATCH success count", + "description": "Feature PATCH success count", "content": { "application/json": { "schema": { @@ -1217,7 +1258,7 @@ } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7006 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| UpdateFeature |\n| 3 |\n", "parameters": [ { "name": "where", @@ -1226,9 +1267,9 @@ "application/json": { "schema": { "type": "object", - "title": "plans.WhereFilter", + "title": "features.WhereFilter", "additionalProperties": true, - "x-typescript-type": "@loopback/repository#Where" + "x-typescript-type": "@loopback/repository#Where" } } } @@ -1238,17 +1279,19 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PlanPartial" + "$ref": "#/components/schemas/FeaturePartial" } } } }, - "operationId": "PlanController.updateAll" + "operationId": "FeatureController.updateAll" }, "get": { - "x-controller-name": "PlanController", + "x-controller-name": "FeatureController", "x-operation-name": "find", - "tags": ["PlanController"], + "tags": [ + "FeatureController" + ], "security": [ { "HTTPBearer": [] @@ -1256,20 +1299,20 @@ ], "responses": { "200": { - "description": "Array of Plan model instances", + "description": "Array of Feature model instances", "content": { "application/json": { "schema": { "type": "array", "items": { - "$ref": "#/components/schemas/PlanWithRelations" + "$ref": "#/components/schemas/FeatureWithRelations" } } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7008 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| ViewFeature |\n| 1 |\n", "parameters": [ { "name": "filter", @@ -1277,28 +1320,48 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/plans.Filter1" + "$ref": "#/components/schemas/features.Filter1" } } } } ], - "operationId": "PlanController.find" + "operationId": "FeatureController.find" } }, - "/resources/count": { + "/ping": { "get": { - "x-controller-name": "ResourceController", - "x-operation-name": "count", - "tags": ["ResourceController"], - "security": [ - { - "HTTPBearer": [] + "x-controller-name": "PingController", + "x-operation-name": "ping", + "tags": [ + "PingController" + ], + "responses": { + "200": { + "description": "Ping Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PingResponse" + } + } + } } + }, + "description": "", + "operationId": "PingController.ping" + } + }, + "/plan-sizes/count": { + "get": { + "x-controller-name": "PlanSizesController", + "x-operation-name": "count", + "tags": [ + "PlanSizesController" ], "responses": { "200": { - "description": "Resource model count", + "description": "PlanSizes model count", "content": { "application/json": { "schema": { @@ -1308,7 +1371,6 @@ } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7016 |\n", "parameters": [ { "name": "where", @@ -1317,33 +1379,36 @@ "application/json": { "schema": { "type": "object", - "title": "resources.WhereFilter", + "title": "plan_sizes.WhereFilter", "additionalProperties": true, - "x-typescript-type": "@loopback/repository#Where" + "x-typescript-type": "@loopback/repository#Where" } } } } ], - "operationId": "ResourceController.count" + "operationId": "PlanSizesController.count" } }, - "/resources/{id}": { + "/plan-sizes/{id}": { "put": { - "x-controller-name": "ResourceController", + "x-controller-name": "PlanSizesController", "x-operation-name": "replaceById", - "tags": ["ResourceController"], - "security": [ - { - "HTTPBearer": [] - } + "tags": [ + "PlanSizesController" ], "responses": { "204": { - "description": "Resource PUT success" + "description": "No Content", + "content": { + "application/json": { + "schema": { + "description": "PlanSizes PUT success" + } + } + } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7014 |\n", "parameters": [ { "name": "id", @@ -1358,29 +1423,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Resource" + "$ref": "#/components/schemas/PlanSizes" } } }, "x-parameter-index": 1 }, - "operationId": "ResourceController.replaceById" + "operationId": "PlanSizesController.replaceById" }, "patch": { - "x-controller-name": "ResourceController", + "x-controller-name": "PlanSizesController", "x-operation-name": "updateById", - "tags": ["ResourceController"], - "security": [ - { - "HTTPBearer": [] - } + "tags": [ + "PlanSizesController" ], "responses": { "204": { - "description": "Resource PATCH success" + "description": "No Content", + "content": { + "application/json": { + "schema": { + "description": "PlanSizes PATCH success" + } + } + } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7014 |\n", "parameters": [ { "name": "id", @@ -1395,36 +1463,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResourcePartial" + "$ref": "#/components/schemas/PlanSizesPartial" } } }, "x-parameter-index": 1 }, - "operationId": "ResourceController.updateById" + "operationId": "PlanSizesController.updateById" }, "get": { - "x-controller-name": "ResourceController", + "x-controller-name": "PlanSizesController", "x-operation-name": "findById", - "tags": ["ResourceController"], - "security": [ - { - "HTTPBearer": [] - } + "tags": [ + "PlanSizesController" ], "responses": { "200": { - "description": "Resource model instance", + "description": "PlanSizes model instance", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResourceWithRelations" + "$ref": "#/components/schemas/PlanSizesWithRelations" } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7016 |\n", "parameters": [ { "name": "id", @@ -1440,29 +1504,32 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/resources.Filter" + "$ref": "#/components/schemas/plan_sizes.Filter" } } } } ], - "operationId": "ResourceController.findById" + "operationId": "PlanSizesController.findById" }, "delete": { - "x-controller-name": "ResourceController", + "x-controller-name": "PlanSizesController", "x-operation-name": "deleteById", - "tags": ["ResourceController"], - "security": [ - { - "HTTPBearer": [] - } + "tags": [ + "PlanSizesController" ], "responses": { "204": { - "description": "Resource DELETE success" + "description": "No Content", + "content": { + "application/json": { + "schema": { + "description": "PlanSizes DELETE success" + } + } + } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7015 |\n", "parameters": [ { "name": "id", @@ -1473,55 +1540,48 @@ "required": true } ], - "operationId": "ResourceController.deleteById" + "operationId": "PlanSizesController.deleteById" } }, - "/resources": { + "/plan-sizes": { "post": { - "x-controller-name": "ResourceController", + "x-controller-name": "PlanSizesController", "x-operation-name": "create", - "tags": ["ResourceController"], - "security": [ - { - "HTTPBearer": [] - } + "tags": [ + "PlanSizesController" ], "responses": { "200": { - "description": "Resource model instance", + "description": "PlanSizes model instance", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Resource" + "$ref": "#/components/schemas/PlanSizes" } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7013 |\n", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NewResource" + "$ref": "#/components/schemas/NewPlanSizes" } } } }, - "operationId": "ResourceController.create" + "operationId": "PlanSizesController.create" }, "patch": { - "x-controller-name": "ResourceController", + "x-controller-name": "PlanSizesController", "x-operation-name": "updateAll", - "tags": ["ResourceController"], - "security": [ - { - "HTTPBearer": [] - } + "tags": [ + "PlanSizesController" ], "responses": { "200": { - "description": "Resource PATCH success count", + "description": "PlanSizes PATCH success count", "content": { "application/json": { "schema": { @@ -1531,7 +1591,6 @@ } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7014 |\n", "parameters": [ { "name": "where", @@ -1540,9 +1599,9 @@ "application/json": { "schema": { "type": "object", - "title": "resources.WhereFilter", + "title": "plan_sizes.WhereFilter", "additionalProperties": true, - "x-typescript-type": "@loopback/repository#Where" + "x-typescript-type": "@loopback/repository#Where" } } } @@ -1552,38 +1611,34 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ResourcePartial" + "$ref": "#/components/schemas/PlanSizesPartial" } } } }, - "operationId": "ResourceController.updateAll" + "operationId": "PlanSizesController.updateAll" }, "get": { - "x-controller-name": "ResourceController", + "x-controller-name": "PlanSizesController", "x-operation-name": "find", - "tags": ["ResourceController"], - "security": [ - { - "HTTPBearer": [] - } + "tags": [ + "PlanSizesController" ], "responses": { "200": { - "description": "Array of Resource model instances", + "description": "Array of PlanSizes model instances", "content": { "application/json": { "schema": { "type": "array", "items": { - "$ref": "#/components/schemas/ResourceWithRelations" + "$ref": "#/components/schemas/PlanSizesWithRelations" } } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7016 |\n", "parameters": [ { "name": "filter", @@ -1591,20 +1646,22 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/resources.Filter1" + "$ref": "#/components/schemas/plan_sizes.Filter1" } } } } ], - "operationId": "ResourceController.find" + "operationId": "PlanSizesController.find" } }, - "/services/count": { + "/plans/count": { "get": { - "x-controller-name": "ServiceController", + "x-controller-name": "PlanController", "x-operation-name": "count", - "tags": ["ServiceController"], + "tags": [ + "PlanController" + ], "security": [ { "HTTPBearer": [] @@ -1612,7 +1669,7 @@ ], "responses": { "200": { - "description": "Service model count", + "description": "Plan model count", "content": { "application/json": { "schema": { @@ -1622,7 +1679,7 @@ } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7020 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7008 |\n", "parameters": [ { "name": "where", @@ -1631,33 +1688,42 @@ "application/json": { "schema": { "type": "object", - "title": "services.WhereFilter", + "title": "plans.WhereFilter", "additionalProperties": true, - "x-typescript-type": "@loopback/repository#Where" + "x-typescript-type": "@loopback/repository#Where" } } } } ], - "operationId": "ServiceController.count" + "operationId": "PlanController.count" } }, - "/services/{id}": { - "put": { - "x-controller-name": "ServiceController", - "x-operation-name": "replaceById", - "tags": ["ServiceController"], + "/plans/{id}/subscriptions": { + "get": { + "x-controller-name": "PlanSubscriptionController", + "x-operation-name": "find", + "tags": [ + "PlanSubscriptionController" + ], "security": [ { "HTTPBearer": [] } ], "responses": { - "204": { - "description": "Service PUT success" + "200": { + "description": "Plan model instance", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionWithRelations" + } + } + } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7018 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7008 |\n| 7004 |\n", "parameters": [ { "name": "id", @@ -1668,22 +1734,55 @@ "required": true } ], - "requestBody": { - "content": { - "application/json": { + "operationId": "PlanSubscriptionController.find" + } + }, + "/plans/{id}": { + "put": { + "x-controller-name": "PlanController", + "x-operation-name": "replaceById", + "tags": [ + "PlanController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "Plan PUT success" + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7006 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "requestBody": { + "content": { + "application/json": { "schema": { - "$ref": "#/components/schemas/Service" + "$ref": "#/components/schemas/Plan" } } }, "x-parameter-index": 1 }, - "operationId": "ServiceController.replaceById" + "operationId": "PlanController.replaceById" }, "patch": { - "x-controller-name": "ServiceController", + "x-controller-name": "PlanController", "x-operation-name": "updateById", - "tags": ["ServiceController"], + "tags": [ + "PlanController" + ], "security": [ { "HTTPBearer": [] @@ -1691,10 +1790,10 @@ ], "responses": { "204": { - "description": "Service PATCH success" + "description": "Plan PATCH success" } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7018 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7006 |\n", "parameters": [ { "name": "id", @@ -1709,18 +1808,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ServicePartial" + "$ref": "#/components/schemas/PlanPartial" } } }, "x-parameter-index": 1 }, - "operationId": "ServiceController.updateById" + "operationId": "PlanController.updateById" }, "get": { - "x-controller-name": "ServiceController", + "x-controller-name": "PlanController", "x-operation-name": "findById", - "tags": ["ServiceController"], + "tags": [ + "PlanController" + ], "security": [ { "HTTPBearer": [] @@ -1728,17 +1829,17 @@ ], "responses": { "200": { - "description": "Service model instance", + "description": "Plan model instance", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ServiceWithRelations" + "$ref": "#/components/schemas/PlanWithRelations" } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7020 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7008 |\n", "parameters": [ { "name": "id", @@ -1754,18 +1855,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/services.Filter" + "$ref": "#/components/schemas/plans.Filter" } } } } ], - "operationId": "ServiceController.findById" + "operationId": "PlanController.findById" }, "delete": { - "x-controller-name": "ServiceController", + "x-controller-name": "PlanController", "x-operation-name": "deleteById", - "tags": ["ServiceController"], + "tags": [ + "PlanController" + ], "security": [ { "HTTPBearer": [] @@ -1773,10 +1876,10 @@ ], "responses": { "204": { - "description": "Service DELETE success" + "description": "Plan DELETE success" } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7019 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7007 |\n", "parameters": [ { "name": "id", @@ -1787,14 +1890,16 @@ "required": true } ], - "operationId": "ServiceController.deleteById" + "operationId": "PlanController.deleteById" } }, - "/services": { + "/plans": { "post": { - "x-controller-name": "ServiceController", + "x-controller-name": "PlanController", "x-operation-name": "create", - "tags": ["ServiceController"], + "tags": [ + "PlanController" + ], "security": [ { "HTTPBearer": [] @@ -1802,32 +1907,34 @@ ], "responses": { "200": { - "description": "Service model instance", + "description": "Plan model instance", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Service" + "$ref": "#/components/schemas/Plan" } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7017 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7005 |\n", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NewService" + "$ref": "#/components/schemas/NewPlan" } } } }, - "operationId": "ServiceController.create" + "operationId": "PlanController.create" }, "patch": { - "x-controller-name": "ServiceController", + "x-controller-name": "PlanController", "x-operation-name": "updateAll", - "tags": ["ServiceController"], + "tags": [ + "PlanController" + ], "security": [ { "HTTPBearer": [] @@ -1835,7 +1942,7 @@ ], "responses": { "200": { - "description": "Service PATCH success count", + "description": "Plan PATCH success count", "content": { "application/json": { "schema": { @@ -1845,7 +1952,7 @@ } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7018 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7006 |\n", "parameters": [ { "name": "where", @@ -1854,9 +1961,9 @@ "application/json": { "schema": { "type": "object", - "title": "services.WhereFilter", + "title": "plans.WhereFilter", "additionalProperties": true, - "x-typescript-type": "@loopback/repository#Where" + "x-typescript-type": "@loopback/repository#Where" } } } @@ -1866,17 +1973,19 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ServicePartial" + "$ref": "#/components/schemas/PlanPartial" } } } }, - "operationId": "ServiceController.updateAll" + "operationId": "PlanController.updateAll" }, "get": { - "x-controller-name": "ServiceController", + "x-controller-name": "PlanController", "x-operation-name": "find", - "tags": ["ServiceController"], + "tags": [ + "PlanController" + ], "security": [ { "HTTPBearer": [] @@ -1884,20 +1993,20 @@ ], "responses": { "200": { - "description": "Array of Service model instances", + "description": "Array of Plan model instances", "content": { "application/json": { "schema": { "type": "array", "items": { - "$ref": "#/components/schemas/ServiceWithRelations" + "$ref": "#/components/schemas/PlanWithRelations" } } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7020 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7008 |\n", "parameters": [ { "name": "filter", @@ -1905,20 +2014,22 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/services.Filter1" + "$ref": "#/components/schemas/plans.Filter1" } } } } ], - "operationId": "ServiceController.find" + "operationId": "PlanController.find" } }, - "/subscriptions/count": { + "/resources/count": { "get": { - "x-controller-name": "SubscriptionController", + "x-controller-name": "ResourceController", "x-operation-name": "count", - "tags": ["SubscriptionController"], + "tags": [ + "ResourceController" + ], "security": [ { "HTTPBearer": [] @@ -1926,7 +2037,7 @@ ], "responses": { "200": { - "description": "Subscription model count", + "description": "Resource model count", "content": { "application/json": { "schema": { @@ -1936,7 +2047,7 @@ } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7004 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7016 |\n", "parameters": [ { "name": "where", @@ -1945,22 +2056,24 @@ "application/json": { "schema": { "type": "object", - "title": "subscriptions.WhereFilter", + "title": "resources.WhereFilter", "additionalProperties": true, - "x-typescript-type": "@loopback/repository#Where" + "x-typescript-type": "@loopback/repository#Where" } } } } ], - "operationId": "SubscriptionController.count" + "operationId": "ResourceController.count" } }, - "/subscriptions/{id}": { + "/resources/{id}": { "put": { - "x-controller-name": "SubscriptionController", + "x-controller-name": "ResourceController", "x-operation-name": "replaceById", - "tags": ["SubscriptionController"], + "tags": [ + "ResourceController" + ], "security": [ { "HTTPBearer": [] @@ -1968,10 +2081,10 @@ ], "responses": { "204": { - "description": "Subscription PUT success" + "description": "Resource PUT success" } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7002 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7014 |\n", "parameters": [ { "name": "id", @@ -1986,18 +2099,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Subscription" + "$ref": "#/components/schemas/Resource" } } }, "x-parameter-index": 1 }, - "operationId": "SubscriptionController.replaceById" + "operationId": "ResourceController.replaceById" }, "patch": { - "x-controller-name": "SubscriptionController", + "x-controller-name": "ResourceController", "x-operation-name": "updateById", - "tags": ["SubscriptionController"], + "tags": [ + "ResourceController" + ], "security": [ { "HTTPBearer": [] @@ -2005,10 +2120,10 @@ ], "responses": { "204": { - "description": "Subscription PATCH success" + "description": "Resource PATCH success" } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7002 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7014 |\n", "parameters": [ { "name": "id", @@ -2023,18 +2138,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SubscriptionPartial" + "$ref": "#/components/schemas/ResourcePartial" } } }, "x-parameter-index": 1 }, - "operationId": "SubscriptionController.updateById" + "operationId": "ResourceController.updateById" }, "get": { - "x-controller-name": "SubscriptionController", + "x-controller-name": "ResourceController", "x-operation-name": "findById", - "tags": ["SubscriptionController"], + "tags": [ + "ResourceController" + ], "security": [ { "HTTPBearer": [] @@ -2042,17 +2159,17 @@ ], "responses": { "200": { - "description": "Subscription model instance", + "description": "Resource model instance", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SubscriptionWithRelations" + "$ref": "#/components/schemas/ResourceWithRelations" } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7004 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7016 |\n", "parameters": [ { "name": "id", @@ -2068,18 +2185,20 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/subscriptions.Filter" + "$ref": "#/components/schemas/resources.Filter" } } } } ], - "operationId": "SubscriptionController.findById" + "operationId": "ResourceController.findById" }, "delete": { - "x-controller-name": "SubscriptionController", + "x-controller-name": "ResourceController", "x-operation-name": "deleteById", - "tags": ["SubscriptionController"], + "tags": [ + "ResourceController" + ], "security": [ { "HTTPBearer": [] @@ -2087,10 +2206,10 @@ ], "responses": { "204": { - "description": "Subscription DELETE success" + "description": "Resource DELETE success" } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7003 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7015 |\n", "parameters": [ { "name": "id", @@ -2101,14 +2220,16 @@ "required": true } ], - "operationId": "SubscriptionController.deleteById" + "operationId": "ResourceController.deleteById" } }, - "/subscriptions": { + "/resources": { "post": { - "x-controller-name": "SubscriptionController", + "x-controller-name": "ResourceController", "x-operation-name": "create", - "tags": ["SubscriptionController"], + "tags": [ + "ResourceController" + ], "security": [ { "HTTPBearer": [] @@ -2116,32 +2237,34 @@ ], "responses": { "200": { - "description": "Subscription model instance", + "description": "Resource model instance", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Subscription" + "$ref": "#/components/schemas/Resource" } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7001 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7013 |\n", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NewSubscription" + "$ref": "#/components/schemas/NewResource" } } } }, - "operationId": "SubscriptionController.create" + "operationId": "ResourceController.create" }, "patch": { - "x-controller-name": "SubscriptionController", + "x-controller-name": "ResourceController", "x-operation-name": "updateAll", - "tags": ["SubscriptionController"], + "tags": [ + "ResourceController" + ], "security": [ { "HTTPBearer": [] @@ -2149,7 +2272,7 @@ ], "responses": { "200": { - "description": "Subscription PATCH success count", + "description": "Resource PATCH success count", "content": { "application/json": { "schema": { @@ -2159,7 +2282,7 @@ } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7002 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7014 |\n", "parameters": [ { "name": "where", @@ -2168,9 +2291,9 @@ "application/json": { "schema": { "type": "object", - "title": "subscriptions.WhereFilter", + "title": "resources.WhereFilter", "additionalProperties": true, - "x-typescript-type": "@loopback/repository#Where" + "x-typescript-type": "@loopback/repository#Where" } } } @@ -2180,17 +2303,19 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SubscriptionPartial" + "$ref": "#/components/schemas/ResourcePartial" } } } }, - "operationId": "SubscriptionController.updateAll" + "operationId": "ResourceController.updateAll" }, "get": { - "x-controller-name": "SubscriptionController", + "x-controller-name": "ResourceController", "x-operation-name": "find", - "tags": ["SubscriptionController"], + "tags": [ + "ResourceController" + ], "security": [ { "HTTPBearer": [] @@ -2198,20 +2323,20 @@ ], "responses": { "200": { - "description": "Array of Subscription model instances", + "description": "Array of Resource model instances", "content": { "application/json": { "schema": { "type": "array", "items": { - "$ref": "#/components/schemas/SubscriptionWithRelations" + "$ref": "#/components/schemas/ResourceWithRelations" } } } } } }, - "description": "\n\n| Permissions |\n| ------- |\n| 7004 |\n", + "description": "\n\n| Permissions |\n| ------- |\n| 7016 |\n", "parameters": [ { "name": "filter", @@ -2219,38 +2344,1125 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/subscriptions.Filter1" + "$ref": "#/components/schemas/resources.Filter1" } } } } ], - "operationId": "SubscriptionController.find" + "operationId": "ResourceController.find" } }, - "/": { + "/services/count": { "get": { - "x-controller-name": "HomePageController", - "x-operation-name": "homePage", - "tags": ["HomePageController"], + "x-controller-name": "ServiceController", + "x-operation-name": "count", + "tags": [ + "ServiceController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], "responses": { "200": { - "description": "Home Page", + "description": "Service model count", "content": { - "text/html": { + "application/json": { "schema": { - "type": "string" + "$ref": "#/components/schemas/loopback.Count" } } } } }, - "description": "", - "operationId": "HomePageController.homePage" + "description": "\n\n| Permissions |\n| ------- |\n| 7020 |\n", + "parameters": [ + { + "name": "where", + "in": "query", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "services.WhereFilter", + "additionalProperties": true, + "x-typescript-type": "@loopback/repository#Where" + } + } + } + } + ], + "operationId": "ServiceController.count" } - } - }, - "components": { + }, + "/services/{id}": { + "put": { + "x-controller-name": "ServiceController", + "x-operation-name": "replaceById", + "tags": [ + "ServiceController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "Service PUT success" + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7018 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Service" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "ServiceController.replaceById" + }, + "patch": { + "x-controller-name": "ServiceController", + "x-operation-name": "updateById", + "tags": [ + "ServiceController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "Service PATCH success" + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7018 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServicePartial" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "ServiceController.updateById" + }, + "get": { + "x-controller-name": "ServiceController", + "x-operation-name": "findById", + "tags": [ + "ServiceController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Service model instance", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServiceWithRelations" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7020 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "filter", + "in": "query", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/services.Filter" + } + } + } + } + ], + "operationId": "ServiceController.findById" + }, + "delete": { + "x-controller-name": "ServiceController", + "x-operation-name": "deleteById", + "tags": [ + "ServiceController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "Service DELETE success" + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7019 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "operationId": "ServiceController.deleteById" + } + }, + "/services": { + "post": { + "x-controller-name": "ServiceController", + "x-operation-name": "create", + "tags": [ + "ServiceController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Service model instance", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Service" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7017 |\n", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewService" + } + } + } + }, + "operationId": "ServiceController.create" + }, + "patch": { + "x-controller-name": "ServiceController", + "x-operation-name": "updateAll", + "tags": [ + "ServiceController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Service PATCH success count", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/loopback.Count" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7018 |\n", + "parameters": [ + { + "name": "where", + "in": "query", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "services.WhereFilter", + "additionalProperties": true, + "x-typescript-type": "@loopback/repository#Where" + } + } + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServicePartial" + } + } + } + }, + "operationId": "ServiceController.updateAll" + }, + "get": { + "x-controller-name": "ServiceController", + "x-operation-name": "find", + "tags": [ + "ServiceController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Array of Service model instances", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ServiceWithRelations" + } + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7020 |\n", + "parameters": [ + { + "name": "filter", + "in": "query", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/services.Filter1" + } + } + } + } + ], + "operationId": "ServiceController.find" + } + }, + "/strategies/count": { + "get": { + "x-controller-name": "StrategyController", + "x-operation-name": "count", + "tags": [ + "StrategyController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Strategy model count", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/loopback.Count" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| ViewStrategy |\n| 5 |\n", + "parameters": [ + { + "name": "where", + "in": "query", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "strategies.WhereFilter", + "additionalProperties": true, + "x-typescript-type": "@loopback/repository#Where" + } + } + } + } + ], + "operationId": "StrategyController.count" + } + }, + "/strategies/{id}": { + "put": { + "x-controller-name": "StrategyController", + "x-operation-name": "replaceById", + "tags": [ + "StrategyController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "Strategy PUT success" + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| UpdateStrategy |\n| 7 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Strategy" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "StrategyController.replaceById" + }, + "patch": { + "x-controller-name": "StrategyController", + "x-operation-name": "updateById", + "tags": [ + "StrategyController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "Strategy PATCH success" + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| UpdateStrategy |\n| 7 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StrategyPartial" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "StrategyController.updateById" + }, + "get": { + "x-controller-name": "StrategyController", + "x-operation-name": "findById", + "tags": [ + "StrategyController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Strategy model instance", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StrategyWithRelations" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| ViewStrategy |\n| 5 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "filter", + "in": "query", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/strategies.Filter" + } + } + } + } + ], + "operationId": "StrategyController.findById" + }, + "delete": { + "x-controller-name": "StrategyController", + "x-operation-name": "deleteById", + "tags": [ + "StrategyController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "Strategy DELETE success" + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| DeleteStrategy |\n| 8 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "operationId": "StrategyController.deleteById" + } + }, + "/strategies": { + "post": { + "x-controller-name": "StrategyController", + "x-operation-name": "create", + "tags": [ + "StrategyController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Strategy model instance", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Strategy" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| CreateStrategy |\n| 6 |\n", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewStrategy" + } + } + } + }, + "operationId": "StrategyController.create" + }, + "patch": { + "x-controller-name": "StrategyController", + "x-operation-name": "updateAll", + "tags": [ + "StrategyController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Strategy PATCH success count", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/loopback.Count" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| UpdateStrategy |\n| 7 |\n", + "parameters": [ + { + "name": "where", + "in": "query", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "strategies.WhereFilter", + "additionalProperties": true, + "x-typescript-type": "@loopback/repository#Where" + } + } + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StrategyPartial" + } + } + } + }, + "operationId": "StrategyController.updateAll" + }, + "get": { + "x-controller-name": "StrategyController", + "x-operation-name": "find", + "tags": [ + "StrategyController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Array of Strategy model instances", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/StrategyWithRelations" + } + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| ViewStrategy |\n| 5 |\n", + "parameters": [ + { + "name": "filter", + "in": "query", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/strategies.Filter1" + } + } + } + } + ], + "operationId": "StrategyController.find" + } + }, + "/subscriptions/count": { + "get": { + "x-controller-name": "SubscriptionController", + "x-operation-name": "count", + "tags": [ + "SubscriptionController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Subscription model count", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/loopback.Count" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7004 |\n", + "parameters": [ + { + "name": "where", + "in": "query", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "subscriptions.WhereFilter", + "additionalProperties": true, + "x-typescript-type": "@loopback/repository#Where" + } + } + } + } + ], + "operationId": "SubscriptionController.count" + } + }, + "/subscriptions/expire-soon": { + "get": { + "x-controller-name": "SubscriptionController", + "x-operation-name": "expireSoonSubscription", + "tags": [ + "SubscriptionController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Array of Subscription model instances", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SubscriptionWithRelations" + } + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7004 |\n", + "parameters": [ + { + "name": "filter", + "in": "query", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/subscriptions.Filter" + } + } + } + } + ], + "operationId": "SubscriptionController.expireSoonSubscription" + } + }, + "/subscriptions/expired": { + "get": { + "x-controller-name": "SubscriptionController", + "x-operation-name": "expiredSubscription", + "tags": [ + "SubscriptionController" + ], + "description": "api that will return newly expired subscription\n\n| Permissions |\n| ------- |\n| 7004 |\n", + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Array of Subscription model instances", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SubscriptionWithRelations" + } + } + } + } + } + }, + "parameters": [ + { + "name": "days", + "in": "header", + "schema": { + "type": "number" + } + }, + { + "name": "filter", + "in": "query", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/subscriptions.Filter" + } + } + } + } + ], + "operationId": "SubscriptionController.expiredSubscription" + } + }, + "/subscriptions/{id}": { + "put": { + "x-controller-name": "SubscriptionController", + "x-operation-name": "replaceById", + "tags": [ + "SubscriptionController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "Subscription PUT success" + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7002 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Subscription" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "SubscriptionController.replaceById" + }, + "patch": { + "x-controller-name": "SubscriptionController", + "x-operation-name": "updateById", + "tags": [ + "SubscriptionController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "Subscription PATCH success" + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7002 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionPartial" + } + } + }, + "x-parameter-index": 1 + }, + "operationId": "SubscriptionController.updateById" + }, + "get": { + "x-controller-name": "SubscriptionController", + "x-operation-name": "findById", + "tags": [ + "SubscriptionController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Subscription model instance", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionWithRelations" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7004 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + }, + { + "name": "filter", + "in": "query", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/subscriptions.Filter1" + } + } + } + } + ], + "operationId": "SubscriptionController.findById" + }, + "delete": { + "x-controller-name": "SubscriptionController", + "x-operation-name": "deleteById", + "tags": [ + "SubscriptionController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "204": { + "description": "Subscription DELETE success" + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7003 |\n", + "parameters": [ + { + "name": "id", + "in": "path", + "schema": { + "type": "string" + }, + "required": true + } + ], + "operationId": "SubscriptionController.deleteById" + } + }, + "/subscriptions": { + "post": { + "x-controller-name": "SubscriptionController", + "x-operation-name": "create", + "tags": [ + "SubscriptionController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Subscription model instance", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Subscription" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7001 |\n", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NewSubscription" + } + } + } + }, + "operationId": "SubscriptionController.create" + }, + "patch": { + "x-controller-name": "SubscriptionController", + "x-operation-name": "updateAll", + "tags": [ + "SubscriptionController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Subscription PATCH success count", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/loopback.Count" + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7002 |\n", + "parameters": [ + { + "name": "where", + "in": "query", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "subscriptions.WhereFilter", + "additionalProperties": true, + "x-typescript-type": "@loopback/repository#Where" + } + } + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionPartial" + } + } + } + }, + "operationId": "SubscriptionController.updateAll" + }, + "get": { + "x-controller-name": "SubscriptionController", + "x-operation-name": "find", + "tags": [ + "SubscriptionController" + ], + "security": [ + { + "HTTPBearer": [] + } + ], + "responses": { + "200": { + "description": "Array of Subscription model instances", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SubscriptionWithRelations" + } + } + } + } + } + }, + "description": "\n\n| Permissions |\n| ------- |\n| 7004 |\n", + "parameters": [ + { + "name": "filter", + "in": "query", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/subscriptions.Filter" + } + } + } + } + ], + "operationId": "SubscriptionController.find" + } + }, + "/": { + "get": { + "x-controller-name": "HomePageController", + "x-operation-name": "homePage", + "tags": [ + "HomePageController" + ], + "responses": { + "200": { + "description": "Home Page", + "content": { + "text/html": { + "schema": { + "type": "string" + } + } + } + } + }, + "description": "", + "operationId": "HomePageController.homePage" + } + } + }, + "components": { "securitySchemes": { "HTTPBearer": { "type": "http", @@ -2259,9 +3471,346 @@ } }, "schemas": { - "Subscription": { - "title": "Subscription", + "Feature": { + "title": "Feature", + "type": "object", + "description": "The features table", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "deletedBy": { + "type": "string", + "nullable": true + }, + "createdOn": { + "type": "string", + "format": "date-time" + }, + "modifiedOn": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "string" + }, + "modifiedBy": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "key": { + "type": "string" + }, + "description": { + "type": "string" + }, + "defaultValue": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": { + "type": "object" + } + }, + "required": [ + "name", + "key" + ], + "additionalProperties": false + }, + "NewFeature": { + "title": "NewFeature", + "type": "object", + "description": "The features table (tsType: Feature, schemaOptions: { title: 'NewFeature' })", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "deletedBy": { + "type": "string", + "nullable": true + }, + "createdOn": { + "type": "string", + "format": "date-time" + }, + "modifiedOn": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "string" + }, + "modifiedBy": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "key": { + "type": "string" + }, + "description": { + "type": "string" + }, + "defaultValue": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": { + "type": "object" + } + }, + "required": [ + "name", + "key" + ], + "additionalProperties": false + }, + "FeatureWithRelations": { + "title": "FeatureWithRelations", + "type": "object", + "description": "The features table (tsType: FeatureWithRelations, schemaOptions: { includeRelations: true })", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "deletedBy": { + "type": "string", + "nullable": true + }, + "createdOn": { + "type": "string", + "format": "date-time" + }, + "modifiedOn": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "string" + }, + "modifiedBy": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "key": { + "type": "string" + }, + "description": { + "type": "string" + }, + "defaultValue": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": { + "type": "object" + } + }, + "required": [ + "name", + "key" + ], + "additionalProperties": false + }, + "FeaturePartial": { + "title": "FeaturePartial", + "type": "object", + "description": "The features table (tsType: Partial, schemaOptions: { partial: true })", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "deletedBy": { + "type": "string", + "nullable": true + }, + "createdOn": { + "type": "string", + "format": "date-time" + }, + "modifiedOn": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "string" + }, + "modifiedBy": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "key": { + "type": "string" + }, + "description": { + "type": "string" + }, + "defaultValue": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": { + "type": "object" + } + }, + "additionalProperties": false + }, + "FeatureValues": { + "title": "FeatureValues", + "type": "object", + "description": "The feature-values table", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "deletedBy": { + "type": "string", + "nullable": true + }, + "createdOn": { + "type": "string", + "format": "date-time" + }, + "modifiedOn": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "string" + }, + "modifiedBy": { + "type": "string" + }, + "id": { + "type": "string" + }, + "featureKey": { + "type": "string" + }, + "strategyKey": { + "type": "string" + }, + "strategyEntityId": { + "type": "string" + }, + "status": { + "type": "boolean" + }, + "value": { + "type": "string" + } + }, + "additionalProperties": false + }, + "NewFeatureValues": { + "title": "NewFeatureValues", + "type": "object", + "description": "The feature-values table (tsType: FeatureValues, schemaOptions: { title: 'NewFeatureValues' })", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "deletedBy": { + "type": "string", + "nullable": true + }, + "createdOn": { + "type": "string", + "format": "date-time" + }, + "modifiedOn": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "string" + }, + "modifiedBy": { + "type": "string" + }, + "id": { + "type": "string" + }, + "featureKey": { + "type": "string" + }, + "strategyKey": { + "type": "string" + }, + "strategyEntityId": { + "type": "string" + }, + "status": { + "type": "boolean" + }, + "value": { + "type": "string" + } + }, + "additionalProperties": false + }, + "FeatureValuesWithRelations": { + "title": "FeatureValuesWithRelations", "type": "object", + "description": "The feature-values table (tsType: FeatureValuesWithRelations, schemaOptions: { includeRelations: true })", "properties": { "deleted": { "type": "boolean" @@ -2292,32 +3841,28 @@ "id": { "type": "string" }, - "subscriberId": { + "featureKey": { "type": "string" }, - "startDate": { + "strategyKey": { "type": "string" }, - "endDate": { + "strategyEntityId": { "type": "string" }, "status": { - "type": "number", - "description": "status of the subscription, it can be - 0(pending), 1(active), 2(inactive), 3(cancelled) and 4(expired)", - "enum": [0, 1, 2, 3, 4] + "type": "boolean" }, - "planId": { - "type": "string", - "description": "plan id of the subscription" + "value": { + "type": "string" } }, - "required": ["subscriberId", "startDate", "endDate", "status"], "additionalProperties": false }, - "NewSubscription": { - "title": "NewSubscription", + "FeatureValuesPartial": { + "title": "FeatureValuesPartial", "type": "object", - "description": "(tsType: Omit, schemaOptions: { title: 'NewSubscription', exclude: [ 'id' ] })", + "description": "The feature-values table (tsType: Partial, schemaOptions: { partial: true })", "properties": { "deleted": { "type": "boolean" @@ -2345,33 +3890,131 @@ "modifiedBy": { "type": "string" }, - "subscriberId": { + "id": { "type": "string" }, - "startDate": { + "featureKey": { "type": "string" }, - "endDate": { + "strategyKey": { + "type": "string" + }, + "strategyEntityId": { "type": "string" }, "status": { - "type": "number", - "description": "status of the subscription, it can be - 0(pending), 1(active), 2(inactive), 3(cancelled) and 4(expired)", - "enum": [0, 1, 2, 3, 4] + "type": "boolean" }, - "planId": { + "value": { + "type": "string" + } + }, + "additionalProperties": false + }, + "Strategy": { + "title": "Strategy", + "type": "object", + "description": "The strategies table", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { "type": "string", - "description": "plan id of the subscription" + "format": "date-time", + "nullable": true + }, + "deletedBy": { + "type": "string", + "nullable": true + }, + "createdOn": { + "type": "string", + "format": "date-time" + }, + "modifiedOn": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "string" + }, + "modifiedBy": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "key": { + "type": "string" + }, + "priority": { + "type": "number" } }, - "required": ["subscriberId", "startDate", "endDate", "status"], - "additionalProperties": false, - "x-typescript-type": "Omit" + "required": [ + "name", + "key" + ], + "additionalProperties": false + }, + "NewStrategy": { + "title": "NewStrategy", + "type": "object", + "description": "The strategies table (tsType: Strategy, schemaOptions: { title: 'NewStrategy' })", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "deletedBy": { + "type": "string", + "nullable": true + }, + "createdOn": { + "type": "string", + "format": "date-time" + }, + "modifiedOn": { + "type": "string", + "format": "date-time" + }, + "createdBy": { + "type": "string" + }, + "modifiedBy": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "key": { + "type": "string" + }, + "priority": { + "type": "number" + } + }, + "required": [ + "name", + "key" + ], + "additionalProperties": false }, - "PlanItemWithRelations": { - "title": "PlanItemWithRelations", + "StrategyWithRelations": { + "title": "StrategyWithRelations", "type": "object", - "description": "(tsType: PlanItemWithRelations, schemaOptions: { includeRelations: true })", + "description": "The strategies table (tsType: StrategyWithRelations, schemaOptions: { includeRelations: true })", "properties": { "deleted": { "type": "boolean" @@ -2403,34 +4046,70 @@ "type": "string" }, "name": { + "type": "string" + }, + "key": { + "type": "string" + }, + "priority": { + "type": "number" + } + }, + "required": [ + "name", + "key" + ], + "additionalProperties": false + }, + "StrategyPartial": { + "title": "StrategyPartial", + "type": "object", + "description": "The strategies table (tsType: Partial, schemaOptions: { partial: true })", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { "type": "string", - "description": "name of the plan item" + "format": "date-time", + "nullable": true }, - "planItemType": { + "deletedBy": { "type": "string", - "description": "type of the plan item" + "nullable": true }, - "value": { - "type": "object", - "description": "value of the plan item" + "createdOn": { + "type": "string", + "format": "date-time" }, - "planId": { + "modifiedOn": { "type": "string", - "description": "plan id of the plan item" + "format": "date-time" }, - "plan": { - "$ref": "#/components/schemas/PlanWithRelations" + "createdBy": { + "type": "string" }, - "foreignKey": {} + "modifiedBy": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "key": { + "type": "string" + }, + "priority": { + "type": "number" + } }, - "required": ["name", "planItemType", "value"], - "additionalProperties": false, - "x-typescript-type": "PlanItemWithRelations" + "additionalProperties": false }, - "BillingCycleWithRelations": { - "title": "BillingCycleWithRelations", + "BillingCycle": { + "title": "BillingCycle", "type": "object", - "description": "(tsType: BillingCycleWithRelations, schemaOptions: { includeRelations: true })", "properties": { "deleted": { "type": "boolean" @@ -2474,39 +4153,69 @@ "type": "string" } }, - "required": ["cycleName", "duration", "durationUnit"], - "additionalProperties": false, - "x-typescript-type": "BillingCycleWithRelations" + "required": [ + "cycleName", + "duration", + "durationUnit" + ], + "additionalProperties": false }, - "CurrencyWithRelations": { - "title": "CurrencyWithRelations", + "NewBillingCycle": { + "title": "NewBillingCycle", "type": "object", - "description": "(tsType: CurrencyWithRelations, schemaOptions: { includeRelations: true })", + "description": "(tsType: Omit, schemaOptions: { title: 'NewBillingCycle', exclude: [ 'id' ] })", "properties": { - "id": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "deletedBy": { + "type": "string", + "nullable": true + }, + "createdOn": { + "type": "string", + "format": "date-time" + }, + "modifiedOn": { + "type": "string", + "format": "date-time" + }, + "createdBy": { "type": "string" }, - "currencyCode": { + "modifiedBy": { "type": "string" }, - "currencyName": { + "cycleName": { "type": "string" }, - "symbol": { + "duration": { + "type": "number" + }, + "durationUnit": { "type": "string" }, - "country": { + "description": { "type": "string" } }, - "required": ["currencyCode", "currencyName"], + "required": [ + "cycleName", + "duration", + "durationUnit" + ], "additionalProperties": false, - "x-typescript-type": "CurrencyWithRelations" + "x-typescript-type": "Omit" }, - "PlanWithRelations": { - "title": "PlanWithRelations", + "BillingCycleWithRelations": { + "title": "BillingCycleWithRelations", "type": "object", - "description": "(tsType: PlanWithRelations, schemaOptions: { includeRelations: true })", + "description": "(tsType: BillingCycleWithRelations, schemaOptions: { includeRelations: true })", "properties": { "deleted": { "type": "boolean" @@ -2537,54 +4246,31 @@ "id": { "type": "string" }, - "name": { - "type": "string", - "description": "name of the plan" - }, - "description": { - "type": "string", - "description": "description of the plan" - }, - "tier": { - "type": "number", - "description": "Tier of the plan, it can be - 0(Pooled) and 1(Silo)", - "enum": [0, 1] + "cycleName": { + "type": "string" }, - "price": { + "duration": { "type": "number" }, - "metaData": { - "type": "object", - "description": "Meta data of the plan" - }, - "billingCycleId": { + "durationUnit": { "type": "string" }, - "currencyId": { + "description": { "type": "string" - }, - "planItems": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PlanItemWithRelations" - } - }, - "billingCycle": { - "$ref": "#/components/schemas/BillingCycleWithRelations" - }, - "foreignKey": {}, - "currency": { - "$ref": "#/components/schemas/CurrencyWithRelations" } }, - "required": ["name", "description", "tier", "price"], + "required": [ + "cycleName", + "duration", + "durationUnit" + ], "additionalProperties": false, - "x-typescript-type": "PlanWithRelations" + "x-typescript-type": "BillingCycleWithRelations" }, - "SubscriptionWithRelations": { - "title": "SubscriptionWithRelations", + "BillingCyclePartial": { + "title": "BillingCyclePartial", "type": "object", - "description": "(tsType: SubscriptionWithRelations, schemaOptions: { includeRelations: true })", + "description": "(tsType: Partial, schemaOptions: { partial: true })", "properties": { "deleted": { "type": "boolean" @@ -2615,91 +4301,127 @@ "id": { "type": "string" }, - "subscriberId": { + "cycleName": { "type": "string" }, - "startDate": { + "duration": { + "type": "number" + }, + "durationUnit": { "type": "string" }, - "endDate": { + "description": { + "type": "string" + } + }, + "additionalProperties": false, + "x-typescript-type": "Partial" + }, + "Currency": { + "title": "Currency", + "type": "object", + "properties": { + "id": { "type": "string" }, - "status": { - "type": "number", - "description": "status of the subscription, it can be - 0(pending), 1(active), 2(inactive), 3(cancelled) and 4(expired)", - "enum": [0, 1, 2, 3, 4] + "currencyCode": { + "type": "string" }, - "planId": { - "type": "string", - "description": "plan id of the subscription" + "currencyName": { + "type": "string" }, - "plan": { - "$ref": "#/components/schemas/PlanWithRelations" + "symbol": { + "type": "string" }, - "foreignKey": {} + "country": { + "type": "string" + } }, - "required": ["subscriberId", "startDate", "endDate", "status"], - "additionalProperties": false, - "x-typescript-type": "SubscriptionWithRelations" + "required": [ + "currencyCode", + "currencyName" + ], + "additionalProperties": false }, - "SubscriptionPartial": { - "title": "SubscriptionPartial", + "NewCurrency": { + "title": "NewCurrency", "type": "object", - "description": "(tsType: Partial, schemaOptions: { partial: true })", + "description": "(tsType: Omit, schemaOptions: { title: 'NewCurrency', exclude: [ 'id' ] })", "properties": { - "deleted": { - "type": "boolean" + "currencyCode": { + "type": "string" }, - "deletedOn": { - "type": "string", - "format": "date-time", - "nullable": true + "currencyName": { + "type": "string" }, - "deletedBy": { - "type": "string", - "nullable": true + "symbol": { + "type": "string" }, - "createdOn": { - "type": "string", - "format": "date-time" + "country": { + "type": "string" + } + }, + "required": [ + "currencyCode", + "currencyName" + ], + "additionalProperties": false, + "x-typescript-type": "Omit" + }, + "CurrencyWithRelations": { + "title": "CurrencyWithRelations", + "type": "object", + "description": "(tsType: CurrencyWithRelations, schemaOptions: { includeRelations: true })", + "properties": { + "id": { + "type": "string" }, - "modifiedOn": { - "type": "string", - "format": "date-time" + "currencyCode": { + "type": "string" }, - "createdBy": { + "currencyName": { "type": "string" }, - "modifiedBy": { + "symbol": { "type": "string" }, + "country": { + "type": "string" + } + }, + "required": [ + "currencyCode", + "currencyName" + ], + "additionalProperties": false, + "x-typescript-type": "CurrencyWithRelations" + }, + "CurrencyPartial": { + "title": "CurrencyPartial", + "type": "object", + "description": "(tsType: Partial, schemaOptions: { partial: true })", + "properties": { "id": { "type": "string" }, - "subscriberId": { + "currencyCode": { "type": "string" }, - "startDate": { + "currencyName": { "type": "string" }, - "endDate": { + "symbol": { "type": "string" }, - "status": { - "type": "number", - "description": "status of the subscription, it can be - 0(pending), 1(active), 2(inactive), 3(cancelled) and 4(expired)", - "enum": [0, 1, 2, 3, 4] - }, - "planId": { - "type": "string", - "description": "plan id of the subscription" + "country": { + "type": "string" } }, "additionalProperties": false, - "x-typescript-type": "Partial" + "x-typescript-type": "Partial" }, - "Service": { - "title": "Service", + "Plan": { + "title": "Plan", "type": "object", "properties": { "deleted": { @@ -2733,16 +4455,42 @@ }, "name": { "type": "string", - "description": "name of the service" + "description": "name of the plan" + }, + "description": { + "type": "string", + "description": "description of the plan" + }, + "tier": { + "type": "string", + "description": "Tier of the plan." + }, + "price": { + "type": "number" + }, + "metaData": { + "type": "object", + "description": "Meta data of the plan" + }, + "billingCycleId": { + "type": "string" + }, + "currencyId": { + "type": "string" } }, - "required": ["name"], + "required": [ + "name", + "description", + "tier", + "price" + ], "additionalProperties": false }, - "NewService": { - "title": "NewService", + "NewPlan": { + "title": "NewPlan", "type": "object", - "description": "(tsType: Omit, schemaOptions: { title: 'NewService', exclude: [ 'id' ] })", + "description": "(tsType: Omit, schemaOptions: { title: 'NewPlan', exclude: [ 'id' ] })", "properties": { "deleted": { "type": "boolean" @@ -2772,17 +4520,43 @@ }, "name": { "type": "string", - "description": "name of the service" + "description": "name of the plan" + }, + "description": { + "type": "string", + "description": "description of the plan" + }, + "tier": { + "type": "string", + "description": "Tier of the plan." + }, + "price": { + "type": "number" + }, + "metaData": { + "type": "object", + "description": "Meta data of the plan" + }, + "billingCycleId": { + "type": "string" + }, + "currencyId": { + "type": "string" } }, - "required": ["name"], + "required": [ + "name", + "description", + "tier", + "price" + ], "additionalProperties": false, - "x-typescript-type": "Omit" + "x-typescript-type": "Omit" }, - "ServiceWithRelations": { - "title": "ServiceWithRelations", + "PlanWithRelations": { + "title": "PlanWithRelations", "type": "object", - "description": "(tsType: ServiceWithRelations, schemaOptions: { includeRelations: true })", + "description": "(tsType: PlanWithRelations, schemaOptions: { includeRelations: true })", "properties": { "deleted": { "type": "boolean" @@ -2815,17 +4589,50 @@ }, "name": { "type": "string", - "description": "name of the service" + "description": "name of the plan" + }, + "description": { + "type": "string", + "description": "description of the plan" + }, + "tier": { + "type": "string", + "description": "Tier of the plan." + }, + "price": { + "type": "number" + }, + "metaData": { + "type": "object", + "description": "Meta data of the plan" + }, + "billingCycleId": { + "type": "string" + }, + "currencyId": { + "type": "string" + }, + "billingCycle": { + "$ref": "#/components/schemas/BillingCycleWithRelations" + }, + "foreignKey": {}, + "currency": { + "$ref": "#/components/schemas/CurrencyWithRelations" } }, - "required": ["name"], + "required": [ + "name", + "description", + "tier", + "price" + ], "additionalProperties": false, - "x-typescript-type": "ServiceWithRelations" + "x-typescript-type": "PlanWithRelations" }, - "ServicePartial": { - "title": "ServicePartial", + "PlanPartial": { + "title": "PlanPartial", "type": "object", - "description": "(tsType: Partial, schemaOptions: { partial: true })", + "description": "(tsType: Partial, schemaOptions: { partial: true })", "properties": { "deleted": { "type": "boolean" @@ -2858,11 +4665,32 @@ }, "name": { "type": "string", - "description": "name of the service" + "description": "name of the plan" + }, + "description": { + "type": "string", + "description": "description of the plan" + }, + "tier": { + "type": "string", + "description": "Tier of the plan." + }, + "price": { + "type": "number" + }, + "metaData": { + "type": "object", + "description": "Meta data of the plan" + }, + "billingCycleId": { + "type": "string" + }, + "currencyId": { + "type": "string" } }, "additionalProperties": false, - "x-typescript-type": "Partial" + "x-typescript-type": "Partial" }, "Resource": { "title": "Resource", @@ -2906,7 +4734,10 @@ "description": "config of the resource" } }, - "required": ["name", "config"], + "required": [ + "name", + "config" + ], "additionalProperties": false }, "NewResource": { @@ -2949,7 +4780,10 @@ "description": "config of the resource" } }, - "required": ["name", "config"], + "required": [ + "name", + "config" + ], "additionalProperties": false, "x-typescript-type": "Omit" }, @@ -2996,7 +4830,10 @@ "description": "config of the resource" } }, - "required": ["name", "config"], + "required": [ + "name", + "config" + ], "additionalProperties": false, "x-typescript-type": "ResourceWithRelations" }, @@ -3046,8 +4883,8 @@ "additionalProperties": false, "x-typescript-type": "Partial" }, - "Plan": { - "title": "Plan", + "Service": { + "title": "Service", "type": "object", "properties": { "deleted": { @@ -3081,38 +4918,60 @@ }, "name": { "type": "string", - "description": "name of the plan" + "description": "name of the service" + } + }, + "required": [ + "name" + ], + "additionalProperties": false + }, + "NewService": { + "title": "NewService", + "type": "object", + "description": "(tsType: Omit, schemaOptions: { title: 'NewService', exclude: [ 'id' ] })", + "properties": { + "deleted": { + "type": "boolean" }, - "description": { + "deletedOn": { "type": "string", - "description": "description of the plan" + "format": "date-time", + "nullable": true }, - "tier": { - "type": "number", - "description": "Tier of the plan, it can be - 0(Pooled) and 1(Silo)", - "enum": [0, 1] + "deletedBy": { + "type": "string", + "nullable": true }, - "price": { - "type": "number" + "createdOn": { + "type": "string", + "format": "date-time" }, - "metaData": { - "type": "object", - "description": "Meta data of the plan" + "modifiedOn": { + "type": "string", + "format": "date-time" }, - "billingCycleId": { + "createdBy": { "type": "string" }, - "currencyId": { + "modifiedBy": { "type": "string" + }, + "name": { + "type": "string", + "description": "name of the service" } }, - "required": ["name", "description", "tier", "price"], - "additionalProperties": false + "required": [ + "name" + ], + "additionalProperties": false, + "x-typescript-type": "Omit" }, - "NewPlan": { - "title": "NewPlan", + "ServiceWithRelations": { + "title": "ServiceWithRelations", "type": "object", - "description": "(tsType: Omit, schemaOptions: { title: 'NewPlan', exclude: [ 'id' ] })", + "description": "(tsType: ServiceWithRelations, schemaOptions: { includeRelations: true })", "properties": { "deleted": { "type": "boolean" @@ -3140,41 +4999,65 @@ "modifiedBy": { "type": "string" }, + "id": { + "type": "string" + }, "name": { "type": "string", - "description": "name of the plan" + "description": "name of the service" + } + }, + "required": [ + "name" + ], + "additionalProperties": false, + "x-typescript-type": "ServiceWithRelations" + }, + "ServicePartial": { + "title": "ServicePartial", + "type": "object", + "description": "(tsType: Partial, schemaOptions: { partial: true })", + "properties": { + "deleted": { + "type": "boolean" }, - "description": { + "deletedOn": { "type": "string", - "description": "description of the plan" + "format": "date-time", + "nullable": true }, - "tier": { - "type": "number", - "description": "Tier of the plan, it can be - 0(Pooled) and 1(Silo)", - "enum": [0, 1] + "deletedBy": { + "type": "string", + "nullable": true }, - "price": { - "type": "number" + "createdOn": { + "type": "string", + "format": "date-time" }, - "metaData": { - "type": "object", - "description": "Meta data of the plan" + "modifiedOn": { + "type": "string", + "format": "date-time" }, - "billingCycleId": { + "createdBy": { "type": "string" }, - "currencyId": { + "modifiedBy": { + "type": "string" + }, + "id": { "type": "string" + }, + "name": { + "type": "string", + "description": "name of the service" } }, - "required": ["name", "description", "tier", "price"], "additionalProperties": false, - "x-typescript-type": "Omit" + "x-typescript-type": "Partial" }, - "PlanPartial": { - "title": "PlanPartial", + "Subscription": { + "title": "Subscription", "type": "object", - "description": "(tsType: Partial, schemaOptions: { partial: true })", "properties": { "deleted": { "type": "boolean" @@ -3205,39 +5088,43 @@ "id": { "type": "string" }, - "name": { - "type": "string", - "description": "name of the plan" - }, - "description": { - "type": "string", - "description": "description of the plan" - }, - "tier": { - "type": "number", - "description": "Tier of the plan, it can be - 0(Pooled) and 1(Silo)", - "enum": [0, 1] - }, - "price": { - "type": "number" - }, - "metaData": { - "type": "object", - "description": "Meta data of the plan" + "subscriberId": { + "type": "string" }, - "billingCycleId": { + "startDate": { "type": "string" }, - "currencyId": { + "endDate": { "type": "string" + }, + "status": { + "type": "number", + "description": "status of the subscription, it can be - 0(pending), 1(active), 2(inactive), 3(cancelled) and 4(expired)", + "enum": [ + 0, + 1, + 2, + 3, + 4 + ] + }, + "planId": { + "type": "string", + "description": "plan id of the subscription" } }, - "additionalProperties": false, - "x-typescript-type": "Partial" + "required": [ + "subscriberId", + "startDate", + "endDate", + "status" + ], + "additionalProperties": false }, - "PlanItem": { - "title": "PlanItem", + "NewSubscription": { + "title": "NewSubscription", "type": "object", + "description": "(tsType: Omit, schemaOptions: { title: 'NewSubscription', exclude: [ 'id', 'startDate', 'endDate' ] })", "properties": { "deleted": { "type": "boolean" @@ -3265,33 +5152,36 @@ "modifiedBy": { "type": "string" }, - "id": { + "subscriberId": { "type": "string" }, - "name": { - "type": "string", - "description": "name of the plan item" - }, - "planItemType": { - "type": "string", - "description": "type of the plan item" - }, - "value": { - "type": "object", - "description": "value of the plan item" + "status": { + "type": "number", + "description": "status of the subscription, it can be - 0(pending), 1(active), 2(inactive), 3(cancelled) and 4(expired)", + "enum": [ + 0, + 1, + 2, + 3, + 4 + ] }, "planId": { "type": "string", - "description": "plan id of the plan item" + "description": "plan id of the subscription" } }, - "required": ["name", "planItemType", "value"], - "additionalProperties": false + "required": [ + "subscriberId", + "status" + ], + "additionalProperties": false, + "x-typescript-type": "Omit" }, - "NewPlanItem": { - "title": "NewPlanItem", + "SubscriptionWithRelations": { + "title": "SubscriptionWithRelations", "type": "object", - "description": "(tsType: Omit, schemaOptions: { title: 'NewPlanItem', exclude: [ 'id' ] })", + "description": "(tsType: SubscriptionWithRelations, schemaOptions: { includeRelations: true })", "properties": { "deleted": { "type": "boolean" @@ -3319,31 +5209,51 @@ "modifiedBy": { "type": "string" }, - "name": { - "type": "string", - "description": "name of the plan item" + "id": { + "type": "string" }, - "planItemType": { - "type": "string", - "description": "type of the plan item" + "subscriberId": { + "type": "string" }, - "value": { - "type": "object", - "description": "value of the plan item" + "startDate": { + "type": "string" + }, + "endDate": { + "type": "string" + }, + "status": { + "type": "number", + "description": "status of the subscription, it can be - 0(pending), 1(active), 2(inactive), 3(cancelled) and 4(expired)", + "enum": [ + 0, + 1, + 2, + 3, + 4 + ] }, "planId": { "type": "string", - "description": "plan id of the plan item" - } + "description": "plan id of the subscription" + }, + "plan": { + "$ref": "#/components/schemas/PlanWithRelations" + }, + "foreignKey": {} }, - "required": ["name", "planItemType", "value"], + "required": [ + "subscriberId", + "startDate", + "endDate", + "status" + ], "additionalProperties": false, - "x-typescript-type": "Omit" + "x-typescript-type": "SubscriptionWithRelations" }, - "PlanItemPartial": { - "title": "PlanItemPartial", + "SubscriptionPartial": { + "title": "SubscriptionPartial", "type": "object", - "description": "(tsType: Partial, schemaOptions: { partial: true })", + "description": "(tsType: Partial, schemaOptions: { partial: true })", "properties": { "deleted": { "type": "boolean" @@ -3374,255 +5284,489 @@ "id": { "type": "string" }, - "name": { - "type": "string", - "description": "name of the plan item" + "subscriberId": { + "type": "string" }, - "planItemType": { - "type": "string", - "description": "type of the plan item" + "startDate": { + "type": "string" }, - "value": { - "type": "object", - "description": "value of the plan item" + "endDate": { + "type": "string" + }, + "status": { + "type": "number", + "description": "status of the subscription, it can be - 0(pending), 1(active), 2(inactive), 3(cancelled) and 4(expired)", + "enum": [ + 0, + 1, + 2, + 3, + 4 + ] }, "planId": { "type": "string", - "description": "plan id of the plan item" + "description": "plan id of the subscription" } }, "additionalProperties": false, - "x-typescript-type": "Partial" + "x-typescript-type": "Partial" }, - "Currency": { - "title": "Currency", + "PlanSizes": { + "title": "PlanSizes", "type": "object", "properties": { "id": { "type": "string" }, - "currencyCode": { - "type": "string" - }, - "currencyName": { - "type": "string" - }, - "symbol": { + "size": { "type": "string" }, - "country": { - "type": "string" + "config": { + "type": "object" } }, - "required": ["currencyCode", "currencyName"], + "required": [ + "size" + ], "additionalProperties": false }, - "NewCurrency": { - "title": "NewCurrency", + "NewPlanSizes": { + "title": "NewPlanSizes", "type": "object", - "description": "(tsType: Omit, schemaOptions: { title: 'NewCurrency', exclude: [ 'id' ] })", + "description": "(tsType: Omit, schemaOptions: { title: 'NewPlanSizes', exclude: [ 'id' ] })", "properties": { - "currencyCode": { - "type": "string" - }, - "currencyName": { + "size": { "type": "string" }, - "symbol": { - "type": "string" - }, - "country": { - "type": "string" + "config": { + "type": "object" } }, - "required": ["currencyCode", "currencyName"], + "required": [ + "size" + ], "additionalProperties": false, - "x-typescript-type": "Omit" + "x-typescript-type": "Omit" }, - "CurrencyPartial": { - "title": "CurrencyPartial", + "PlanSizesWithRelations": { + "title": "PlanSizesWithRelations", "type": "object", - "description": "(tsType: Partial, schemaOptions: { partial: true })", + "description": "(tsType: PlanSizesWithRelations, schemaOptions: { includeRelations: true })", "properties": { "id": { "type": "string" }, - "currencyCode": { + "size": { "type": "string" }, - "currencyName": { + "config": { + "type": "object" + } + }, + "required": [ + "size" + ], + "additionalProperties": false, + "x-typescript-type": "PlanSizesWithRelations" + }, + "PlanSizesPartial": { + "title": "PlanSizesPartial", + "type": "object", + "description": "(tsType: Partial, schemaOptions: { partial: true })", + "properties": { + "id": { "type": "string" }, - "symbol": { + "size": { "type": "string" }, - "country": { - "type": "string" + "config": { + "type": "object" } }, "additionalProperties": false, - "x-typescript-type": "Partial" + "x-typescript-type": "Partial" }, - "BillingCycle": { - "title": "BillingCycle", + "loopback.Count": { "type": "object", + "title": "loopback.Count", + "x-typescript-type": "@loopback/repository#Count", "properties": { - "deleted": { - "type": "boolean" - }, - "deletedOn": { - "type": "string", - "format": "date-time", - "nullable": true - }, - "deletedBy": { - "type": "string", - "nullable": true + "count": { + "type": "number" + } + } + }, + "billing_cycles.Filter": { + "type": "object", + "title": "billing_cycles.Filter", + "properties": { + "offset": { + "type": "integer", + "minimum": 0 }, - "createdOn": { - "type": "string", - "format": "date-time" + "limit": { + "type": "integer", + "minimum": 1, + "example": 100 }, - "modifiedOn": { - "type": "string", - "format": "date-time" + "skip": { + "type": "integer", + "minimum": 0 }, - "createdBy": { - "type": "string" + "order": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] }, - "modifiedBy": { - "type": "string" + "fields": { + "oneOf": [ + { + "type": "object", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "boolean" + }, + "deletedBy": { + "type": "boolean" + }, + "createdOn": { + "type": "boolean" + }, + "modifiedOn": { + "type": "boolean" + }, + "createdBy": { + "type": "boolean" + }, + "modifiedBy": { + "type": "boolean" + }, + "id": { + "type": "boolean" + }, + "cycleName": { + "type": "boolean" + }, + "duration": { + "type": "boolean" + }, + "durationUnit": { + "type": "boolean" + }, + "description": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "deleted", + "deletedOn", + "deletedBy", + "createdOn", + "modifiedOn", + "createdBy", + "modifiedBy", + "id", + "cycleName", + "duration", + "durationUnit", + "description" + ], + "example": "deleted" + }, + "uniqueItems": true + } + ], + "title": "billing_cycles.Fields" + } + }, + "additionalProperties": false, + "x-typescript-type": "@loopback/repository#Filter" + }, + "billing_cycles.Filter1": { + "type": "object", + "title": "billing_cycles.Filter", + "properties": { + "offset": { + "type": "integer", + "minimum": 0 }, - "id": { - "type": "string" + "limit": { + "type": "integer", + "minimum": 1, + "example": 100 }, - "cycleName": { - "type": "string" + "skip": { + "type": "integer", + "minimum": 0 }, - "duration": { - "type": "number" + "order": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] }, - "durationUnit": { - "type": "string" + "where": { + "title": "billing_cycles.WhereFilter", + "type": "object", + "additionalProperties": true }, - "description": { - "type": "string" + "fields": { + "oneOf": [ + { + "type": "object", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "boolean" + }, + "deletedBy": { + "type": "boolean" + }, + "createdOn": { + "type": "boolean" + }, + "modifiedOn": { + "type": "boolean" + }, + "createdBy": { + "type": "boolean" + }, + "modifiedBy": { + "type": "boolean" + }, + "id": { + "type": "boolean" + }, + "cycleName": { + "type": "boolean" + }, + "duration": { + "type": "boolean" + }, + "durationUnit": { + "type": "boolean" + }, + "description": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "deleted", + "deletedOn", + "deletedBy", + "createdOn", + "modifiedOn", + "createdBy", + "modifiedBy", + "id", + "cycleName", + "duration", + "durationUnit", + "description" + ], + "example": "deleted" + }, + "uniqueItems": true + } + ], + "title": "billing_cycles.Fields" } }, - "required": ["cycleName", "duration", "durationUnit"], - "additionalProperties": false + "additionalProperties": false, + "x-typescript-type": "@loopback/repository#Filter" }, - "NewBillingCycle": { - "title": "NewBillingCycle", + "currencies.Filter": { "type": "object", - "description": "(tsType: Omit, schemaOptions: { title: 'NewBillingCycle', exclude: [ 'id' ] })", + "title": "currencies.Filter", "properties": { - "deleted": { - "type": "boolean" - }, - "deletedOn": { - "type": "string", - "format": "date-time", - "nullable": true - }, - "deletedBy": { - "type": "string", - "nullable": true - }, - "createdOn": { - "type": "string", - "format": "date-time" - }, - "modifiedOn": { - "type": "string", - "format": "date-time" - }, - "createdBy": { - "type": "string" - }, - "modifiedBy": { - "type": "string" + "offset": { + "type": "integer", + "minimum": 0 }, - "cycleName": { - "type": "string" + "limit": { + "type": "integer", + "minimum": 1, + "example": 100 }, - "duration": { - "type": "number" + "skip": { + "type": "integer", + "minimum": 0 }, - "durationUnit": { - "type": "string" + "order": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] }, - "description": { - "type": "string" + "fields": { + "oneOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "boolean" + }, + "currencyCode": { + "type": "boolean" + }, + "currencyName": { + "type": "boolean" + }, + "symbol": { + "type": "boolean" + }, + "country": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "id", + "currencyCode", + "currencyName", + "symbol", + "country" + ], + "example": "id" + }, + "uniqueItems": true + } + ], + "title": "currencies.Fields" } }, - "required": ["cycleName", "duration", "durationUnit"], "additionalProperties": false, - "x-typescript-type": "Omit" + "x-typescript-type": "@loopback/repository#Filter" }, - "BillingCyclePartial": { - "title": "BillingCyclePartial", + "currencies.Filter1": { "type": "object", - "description": "(tsType: Partial, schemaOptions: { partial: true })", + "title": "currencies.Filter", "properties": { - "deleted": { - "type": "boolean" - }, - "deletedOn": { - "type": "string", - "format": "date-time", - "nullable": true - }, - "deletedBy": { - "type": "string", - "nullable": true - }, - "createdOn": { - "type": "string", - "format": "date-time" - }, - "modifiedOn": { - "type": "string", - "format": "date-time" - }, - "createdBy": { - "type": "string" - }, - "modifiedBy": { - "type": "string" + "offset": { + "type": "integer", + "minimum": 0 }, - "id": { - "type": "string" + "limit": { + "type": "integer", + "minimum": 1, + "example": 100 }, - "cycleName": { - "type": "string" + "skip": { + "type": "integer", + "minimum": 0 }, - "duration": { - "type": "number" + "order": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] }, - "durationUnit": { - "type": "string" + "where": { + "title": "currencies.WhereFilter", + "type": "object", + "additionalProperties": true }, - "description": { - "type": "string" + "fields": { + "oneOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "boolean" + }, + "currencyCode": { + "type": "boolean" + }, + "currencyName": { + "type": "boolean" + }, + "symbol": { + "type": "boolean" + }, + "country": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "id", + "currencyCode", + "currencyName", + "symbol", + "country" + ], + "example": "id" + }, + "uniqueItems": true + } + ], + "title": "currencies.Fields" } }, "additionalProperties": false, - "x-typescript-type": "Partial" - }, - "loopback.Count": { - "type": "object", - "title": "loopback.Count", - "x-typescript-type": "@loopback/repository#Count", - "properties": { - "count": { - "type": "number" - } - } + "x-typescript-type": "@loopback/repository#Filter" }, - "billing_cycles.Filter": { + "feature_values.Filter": { "type": "object", - "title": "billing_cycles.Filter", + "title": "feature_values.Filter", "properties": { "offset": { "type": "integer", @@ -3679,16 +5823,19 @@ "id": { "type": "boolean" }, - "cycleName": { + "featureKey": { + "type": "boolean" + }, + "strategyKey": { "type": "boolean" }, - "duration": { + "strategyEntityId": { "type": "boolean" }, - "durationUnit": { + "status": { "type": "boolean" }, - "description": { + "value": { "type": "boolean" } }, @@ -3707,25 +5854,26 @@ "createdBy", "modifiedBy", "id", - "cycleName", - "duration", - "durationUnit", - "description" + "featureKey", + "strategyKey", + "strategyEntityId", + "status", + "value" ], "example": "deleted" }, "uniqueItems": true } ], - "title": "billing_cycles.Fields" + "title": "feature_values.Fields" } }, "additionalProperties": false, - "x-typescript-type": "@loopback/repository#Filter" + "x-typescript-type": "@loopback/repository#Filter" }, - "billing_cycles.Filter1": { + "feature_values.Filter1": { "type": "object", - "title": "billing_cycles.Filter", + "title": "feature_values.Filter", "properties": { "offset": { "type": "integer", @@ -3754,7 +5902,7 @@ ] }, "where": { - "title": "billing_cycles.WhereFilter", + "title": "feature_values.WhereFilter", "type": "object", "additionalProperties": true }, @@ -3787,16 +5935,19 @@ "id": { "type": "boolean" }, - "cycleName": { + "featureKey": { "type": "boolean" }, - "duration": { + "strategyKey": { "type": "boolean" }, - "durationUnit": { + "strategyEntityId": { "type": "boolean" }, - "description": { + "status": { + "type": "boolean" + }, + "value": { "type": "boolean" } }, @@ -3815,25 +5966,26 @@ "createdBy", "modifiedBy", "id", - "cycleName", - "duration", - "durationUnit", - "description" + "featureKey", + "strategyKey", + "strategyEntityId", + "status", + "value" ], "example": "deleted" }, "uniqueItems": true } ], - "title": "billing_cycles.Fields" + "title": "feature_values.Fields" } }, "additionalProperties": false, - "x-typescript-type": "@loopback/repository#Filter" + "x-typescript-type": "@loopback/repository#Filter" }, - "currencies.Filter": { + "features.Filter": { "type": "object", - "title": "currencies.Filter", + "title": "features.Filter", "properties": { "offset": { "type": "integer", @@ -3866,19 +6018,46 @@ { "type": "object", "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "boolean" + }, + "deletedBy": { + "type": "boolean" + }, + "createdOn": { + "type": "boolean" + }, + "modifiedOn": { + "type": "boolean" + }, + "createdBy": { + "type": "boolean" + }, + "modifiedBy": { + "type": "boolean" + }, "id": { "type": "boolean" }, - "currencyCode": { + "name": { "type": "boolean" }, - "currencyName": { + "key": { "type": "boolean" }, - "symbol": { + "description": { "type": "boolean" }, - "country": { + "defaultValue": { + "type": "boolean" + }, + "type": { + "type": "boolean" + }, + "metadata": { "type": "boolean" } }, @@ -3889,26 +6068,35 @@ "items": { "type": "string", "enum": [ + "deleted", + "deletedOn", + "deletedBy", + "createdOn", + "modifiedOn", + "createdBy", + "modifiedBy", "id", - "currencyCode", - "currencyName", - "symbol", - "country" + "name", + "key", + "description", + "defaultValue", + "type", + "metadata" ], - "example": "id" + "example": "deleted" }, "uniqueItems": true } ], - "title": "currencies.Fields" + "title": "features.Fields" } }, "additionalProperties": false, - "x-typescript-type": "@loopback/repository#Filter" + "x-typescript-type": "@loopback/repository#Filter" }, - "currencies.Filter1": { + "features.Filter1": { "type": "object", - "title": "currencies.Filter", + "title": "features.Filter", "properties": { "offset": { "type": "integer", @@ -3937,7 +6125,7 @@ ] }, "where": { - "title": "currencies.WhereFilter", + "title": "features.WhereFilter", "type": "object", "additionalProperties": true }, @@ -3946,19 +6134,46 @@ { "type": "object", "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "boolean" + }, + "deletedBy": { + "type": "boolean" + }, + "createdOn": { + "type": "boolean" + }, + "modifiedOn": { + "type": "boolean" + }, + "createdBy": { + "type": "boolean" + }, + "modifiedBy": { + "type": "boolean" + }, "id": { "type": "boolean" }, - "currencyCode": { + "name": { "type": "boolean" }, - "currencyName": { + "key": { "type": "boolean" }, - "symbol": { + "description": { "type": "boolean" }, - "country": { + "defaultValue": { + "type": "boolean" + }, + "type": { + "type": "boolean" + }, + "metadata": { "type": "boolean" } }, @@ -3969,22 +6184,31 @@ "items": { "type": "string", "enum": [ + "deleted", + "deletedOn", + "deletedBy", + "createdOn", + "modifiedOn", + "createdBy", + "modifiedBy", "id", - "currencyCode", - "currencyName", - "symbol", - "country" + "name", + "key", + "description", + "defaultValue", + "type", + "metadata" ], - "example": "id" + "example": "deleted" }, "uniqueItems": true } ], - "title": "currencies.Fields" + "title": "features.Fields" } }, "additionalProperties": false, - "x-typescript-type": "@loopback/repository#Filter" + "x-typescript-type": "@loopback/repository#Filter" }, "PingResponse": { "type": "object", @@ -4010,83 +6234,9 @@ } } }, - "plan_items.ScopeFilter": { - "type": "object", - "properties": { - "offset": { - "type": "integer", - "minimum": 0 - }, - "limit": { - "type": "integer", - "minimum": 1, - "example": 100 - }, - "skip": { - "type": "integer", - "minimum": 0 - }, - "order": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "where": { - "type": "object", - "additionalProperties": true - }, - "fields": { - "oneOf": [ - { - "type": "object", - "properties": {}, - "additionalProperties": true - }, - { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true - } - ] - }, - "include": { - "type": "array", - "items": { - "type": "object", - "properties": {}, - "additionalProperties": true - } - } - }, - "additionalProperties": false, - "title": "plan_items.ScopeFilter" - }, - "plan_items.IncludeFilter.Items": { - "title": "plan_items.IncludeFilter.Items", - "type": "object", - "properties": { - "relation": { - "type": "string", - "enum": ["plan"] - }, - "scope": { - "$ref": "#/components/schemas/plan_items.ScopeFilter" - } - } - }, - "plan_items.Filter": { + "plan_sizes.Filter": { "type": "object", - "title": "plan_items.Filter", + "title": "plan_sizes.Filter", "properties": { "offset": { "type": "integer", @@ -4119,40 +6269,13 @@ { "type": "object", "properties": { - "deleted": { - "type": "boolean" - }, - "deletedOn": { - "type": "boolean" - }, - "deletedBy": { - "type": "boolean" - }, - "createdOn": { - "type": "boolean" - }, - "modifiedOn": { - "type": "boolean" - }, - "createdBy": { - "type": "boolean" - }, - "modifiedBy": { - "type": "boolean" - }, "id": { "type": "boolean" }, - "name": { - "type": "boolean" - }, - "planItemType": { + "size": { "type": "boolean" }, - "value": { - "type": "boolean" - }, - "planId": { + "config": { "type": "boolean" } }, @@ -4163,47 +6286,24 @@ "items": { "type": "string", "enum": [ - "deleted", - "deletedOn", - "deletedBy", - "createdOn", - "modifiedOn", - "createdBy", - "modifiedBy", "id", - "name", - "planItemType", - "value", - "planId" + "size", + "config" ], - "example": "deleted" - }, - "uniqueItems": true - } - ], - "title": "plan_items.Fields" - }, - "include": { - "title": "plan_items.IncludeFilter", - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/plan_items.IncludeFilter.Items" - }, - { - "type": "string" - } - ] - } + "example": "id" + }, + "uniqueItems": true + } + ], + "title": "plan_sizes.Fields" } }, "additionalProperties": false, - "x-typescript-type": "@loopback/repository#Filter" + "x-typescript-type": "@loopback/repository#Filter" }, - "plan_items.Filter1": { + "plan_sizes.Filter1": { "type": "object", - "title": "plan_items.Filter", + "title": "plan_sizes.Filter", "properties": { "offset": { "type": "integer", @@ -4232,7 +6332,7 @@ ] }, "where": { - "title": "plan_items.WhereFilter", + "title": "plan_sizes.WhereFilter", "type": "object", "additionalProperties": true }, @@ -4241,40 +6341,13 @@ { "type": "object", "properties": { - "deleted": { - "type": "boolean" - }, - "deletedOn": { - "type": "boolean" - }, - "deletedBy": { - "type": "boolean" - }, - "createdOn": { - "type": "boolean" - }, - "modifiedOn": { - "type": "boolean" - }, - "createdBy": { - "type": "boolean" - }, - "modifiedBy": { - "type": "boolean" - }, "id": { "type": "boolean" }, - "name": { - "type": "boolean" - }, - "planItemType": { - "type": "boolean" - }, - "value": { + "size": { "type": "boolean" }, - "planId": { + "config": { "type": "boolean" } }, @@ -4285,43 +6358,20 @@ "items": { "type": "string", "enum": [ - "deleted", - "deletedOn", - "deletedBy", - "createdOn", - "modifiedOn", - "createdBy", - "modifiedBy", "id", - "name", - "planItemType", - "value", - "planId" + "size", + "config" ], - "example": "deleted" + "example": "id" }, "uniqueItems": true } ], - "title": "plan_items.Fields" - }, - "include": { - "title": "plan_items.IncludeFilter", - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/plan_items.IncludeFilter.Items" - }, - { - "type": "string" - } - ] - } + "title": "plan_sizes.Fields" } }, "additionalProperties": false, - "x-typescript-type": "@loopback/repository#Filter" + "x-typescript-type": "@loopback/repository#Filter" }, "plans.ScopeFilter": { "type": "object", @@ -4390,7 +6440,10 @@ "properties": { "relation": { "type": "string", - "enum": ["planItems", "billingCycle", "currency"] + "enum": [ + "billingCycle", + "currency" + ] }, "scope": { "$ref": "#/components/schemas/plans.ScopeFilter" @@ -5042,6 +7095,209 @@ "additionalProperties": false, "x-typescript-type": "@loopback/repository#Filter" }, + "strategies.Filter": { + "type": "object", + "title": "strategies.Filter", + "properties": { + "offset": { + "type": "integer", + "minimum": 0 + }, + "limit": { + "type": "integer", + "minimum": 1, + "example": 100 + }, + "skip": { + "type": "integer", + "minimum": 0 + }, + "order": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "fields": { + "oneOf": [ + { + "type": "object", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "boolean" + }, + "deletedBy": { + "type": "boolean" + }, + "createdOn": { + "type": "boolean" + }, + "modifiedOn": { + "type": "boolean" + }, + "createdBy": { + "type": "boolean" + }, + "modifiedBy": { + "type": "boolean" + }, + "id": { + "type": "boolean" + }, + "name": { + "type": "boolean" + }, + "key": { + "type": "boolean" + }, + "priority": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "deleted", + "deletedOn", + "deletedBy", + "createdOn", + "modifiedOn", + "createdBy", + "modifiedBy", + "id", + "name", + "key", + "priority" + ], + "example": "deleted" + }, + "uniqueItems": true + } + ], + "title": "strategies.Fields" + } + }, + "additionalProperties": false, + "x-typescript-type": "@loopback/repository#Filter" + }, + "strategies.Filter1": { + "type": "object", + "title": "strategies.Filter", + "properties": { + "offset": { + "type": "integer", + "minimum": 0 + }, + "limit": { + "type": "integer", + "minimum": 1, + "example": 100 + }, + "skip": { + "type": "integer", + "minimum": 0 + }, + "order": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "where": { + "title": "strategies.WhereFilter", + "type": "object", + "additionalProperties": true + }, + "fields": { + "oneOf": [ + { + "type": "object", + "properties": { + "deleted": { + "type": "boolean" + }, + "deletedOn": { + "type": "boolean" + }, + "deletedBy": { + "type": "boolean" + }, + "createdOn": { + "type": "boolean" + }, + "modifiedOn": { + "type": "boolean" + }, + "createdBy": { + "type": "boolean" + }, + "modifiedBy": { + "type": "boolean" + }, + "id": { + "type": "boolean" + }, + "name": { + "type": "boolean" + }, + "key": { + "type": "boolean" + }, + "priority": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + { + "type": "array", + "items": { + "type": "string", + "enum": [ + "deleted", + "deletedOn", + "deletedBy", + "createdOn", + "modifiedOn", + "createdBy", + "modifiedBy", + "id", + "name", + "key", + "priority" + ], + "example": "deleted" + }, + "uniqueItems": true + } + ], + "title": "strategies.Fields" + } + }, + "additionalProperties": false, + "x-typescript-type": "@loopback/repository#Filter" + }, "subscriptions.ScopeFilter": { "type": "object", "properties": { @@ -5109,7 +7365,9 @@ "properties": { "relation": { "type": "string", - "enum": ["plan"] + "enum": [ + "plan" + ] }, "scope": { "$ref": "#/components/schemas/subscriptions.ScopeFilter" @@ -5146,6 +7404,11 @@ } ] }, + "where": { + "title": "subscriptions.WhereFilter", + "type": "object", + "additionalProperties": true + }, "fields": { "oneOf": [ { @@ -5267,11 +7530,6 @@ } ] }, - "where": { - "title": "subscriptions.WhereFilter", - "type": "object", - "additionalProperties": true - }, "fields": { "oneOf": [ { @@ -5370,4 +7628,4 @@ "url": "/" } ] -} +} \ No newline at end of file diff --git a/services/subscription-service/src/permissions.ts b/services/subscription-service/src/permissions.ts index 6b75b20..d1b5c60 100644 --- a/services/subscription-service/src/permissions.ts +++ b/services/subscription-service/src/permissions.ts @@ -7,10 +7,6 @@ export const PermissionKey = { UpdatePlan: '7006', DeletePlan: '7007', ViewPlan: '7008', - CreatePlanItem: '7009', - UpdatePlanItem: '7010', - DeletePlanItem: '7011', - ViewPlanItem: '7012', CreateResource: '7013', UpdateResource: '7014', DeleteResource: '7015', @@ -27,6 +23,13 @@ export const PermissionKey = { UpdateCurrency: '7026', DeleteCurrency: '7027', ViewCurrency: '7028', + ViewPlanSizes: '7029', + CreatePlanSizes: '7030', + UpdatePlanSizes: '7031', + DeletePlanSizes: '7032', + ViewPlanFeatures: '7033', + AddPlanFeatures: '7034', + UpdatePlanFeatures: '7035', CreateLead: '10200', UpdateLead: '10201', DeleteLead: '10202', diff --git a/services/subscription-service/src/repositories/index.ts b/services/subscription-service/src/repositories/index.ts index 504174c..6a82b38 100644 --- a/services/subscription-service/src/repositories/index.ts +++ b/services/subscription-service/src/repositories/index.ts @@ -1,7 +1,7 @@ -export * from './plan-item.repository'; export * from './plan.repository'; export * from './resource.repository'; export * from './service.repository'; export * from './subscription.repository'; export * from './billing-cycle.repository'; export * from './currency.repository'; +export * from './plan-sizes.repository'; diff --git a/services/subscription-service/src/repositories/plan-item.repository.ts b/services/subscription-service/src/repositories/plan-item.repository.ts deleted file mode 100644 index 7e2083f..0000000 --- a/services/subscription-service/src/repositories/plan-item.repository.ts +++ /dev/null @@ -1,31 +0,0 @@ -import {Getter, inject} from '@loopback/core'; -import {PlanItem, PlanItemRelations, Plan} from '../models'; -import { - DefaultUserModifyCrudRepository, - IAuthUserWithPermissions, -} from '@sourceloop/core'; -import {AuthenticationBindings} from 'loopback4-authentication'; -import {repository, BelongsToAccessor, juggler} from '@loopback/repository'; -import {PlanRepository} from './plan.repository'; -import {SubscriptionDbSourceName} from '../types'; - -export class PlanItemRepository extends DefaultUserModifyCrudRepository< - PlanItem, - typeof PlanItem.prototype.id, - PlanItemRelations -> { - public readonly plan: BelongsToAccessor; - - constructor( - @inject(`datasources.${SubscriptionDbSourceName}`) - dataSource: juggler.DataSource, - @inject.getter(AuthenticationBindings.CURRENT_USER) - public readonly getCurrentUser: Getter, - @repository.getter('PlanRepository') - protected planRepositoryGetter: Getter, - ) { - super(PlanItem, dataSource, getCurrentUser); - this.plan = this.createBelongsToAccessorFor('plan', planRepositoryGetter); - this.registerInclusionResolver('plan', this.plan.inclusionResolver); - } -} diff --git a/services/subscription-service/src/repositories/plan-sizes.repository.ts b/services/subscription-service/src/repositories/plan-sizes.repository.ts new file mode 100644 index 0000000..399a4a0 --- /dev/null +++ b/services/subscription-service/src/repositories/plan-sizes.repository.ts @@ -0,0 +1,24 @@ +import {Getter, inject} from '@loopback/core'; +import {PlanSizes, PlanSizesRelations} from '../models'; +import { + DefaultUserModifyCrudRepository, + IAuthUserWithPermissions, +} from '@sourceloop/core'; +import {AuthenticationBindings} from 'loopback4-authentication'; +import {juggler} from '@loopback/repository'; +import {SubscriptionDbSourceName} from '../types'; + +export class PlanSizesRepository extends DefaultUserModifyCrudRepository< + PlanSizes, + typeof PlanSizes.prototype.id, + PlanSizesRelations +> { + constructor( + @inject(`datasources.${SubscriptionDbSourceName}`) + dataSource: juggler.DataSource, + @inject.getter(AuthenticationBindings.CURRENT_USER) + public readonly getCurrentUser: Getter, + ) { + super(PlanSizes, dataSource, getCurrentUser); + } +} diff --git a/services/subscription-service/src/repositories/plan.repository.ts b/services/subscription-service/src/repositories/plan.repository.ts index 27e1651..9480d82 100644 --- a/services/subscription-service/src/repositories/plan.repository.ts +++ b/services/subscription-service/src/repositories/plan.repository.ts @@ -1,17 +1,11 @@ import {Getter, inject} from '@loopback/core'; -import {Plan, PlanRelations, PlanItem, BillingCycle, Currency} from '../models'; +import {Plan, PlanRelations, BillingCycle, Currency} from '../models'; import { DefaultUserModifyCrudRepository, IAuthUserWithPermissions, } from '@sourceloop/core'; import {AuthenticationBindings} from 'loopback4-authentication'; -import { - repository, - HasManyRepositoryFactory, - BelongsToAccessor, - juggler, -} from '@loopback/repository'; -import {PlanItemRepository} from './plan-item.repository'; +import {repository, BelongsToAccessor, juggler} from '@loopback/repository'; import {BillingCycleRepository} from './billing-cycle.repository'; import {CurrencyRepository} from './currency.repository'; import {SubscriptionDbSourceName} from '../types'; @@ -21,11 +15,6 @@ export class PlanRepository extends DefaultUserModifyCrudRepository< typeof Plan.prototype.id, PlanRelations > { - public readonly planItems: HasManyRepositoryFactory< - PlanItem, - typeof Plan.prototype.id - >; - public readonly billingCycle: BelongsToAccessor< BillingCycle, typeof Plan.prototype.id @@ -41,8 +30,6 @@ export class PlanRepository extends DefaultUserModifyCrudRepository< dataSource: juggler.DataSource, @inject.getter(AuthenticationBindings.CURRENT_USER) public readonly getCurrentUser: Getter, - @repository.getter('PlanItemRepository') - protected planItemRepositoryGetter: Getter, @repository.getter('BillingCycleRepository') protected billingCycleRepositoryGetter: Getter, @repository.getter('CurrencyRepository') @@ -62,14 +49,5 @@ export class PlanRepository extends DefaultUserModifyCrudRepository< this.billingCycle.inclusionResolver, ); this.registerInclusionResolver('currency', this.currency.inclusionResolver); - - this.planItems = this.createHasManyRepositoryFactoryFor( - 'planItems', - planItemRepositoryGetter, - ); - this.registerInclusionResolver( - 'planItems', - this.planItems.inclusionResolver, - ); } } diff --git a/services/tenant-management-service/src/__tests__/acceptance/mock-data.ts b/services/tenant-management-service/src/__tests__/acceptance/mock-data.ts index 54e8266..73d83cf 100644 --- a/services/tenant-management-service/src/__tests__/acceptance/mock-data.ts +++ b/services/tenant-management-service/src/__tests__/acceptance/mock-data.ts @@ -1,10 +1,5 @@ import {AnyObject, DataObject, DeepPartial} from '@loopback/repository'; -import { - InvoiceStatus, - NotificationType, - PlanTier, - TenantStatus, -} from '../../enums'; +import {InvoiceStatus, NotificationType, TenantStatus} from '../../enums'; import { Address, Contact, @@ -96,8 +91,7 @@ export const mockSubscriptionId = 'test-subscription-id'; export const mockSusbcription: DeepPartial = { id: '1', plan: { - tier: PlanTier.POOLED, - planItems: [], + tier: 'Standard', }, }; diff --git a/services/tenant-management-service/src/enums/index.ts b/services/tenant-management-service/src/enums/index.ts index 2d931b6..3b6659c 100644 --- a/services/tenant-management-service/src/enums/index.ts +++ b/services/tenant-management-service/src/enums/index.ts @@ -3,4 +3,3 @@ export * from './invoice-status.enum'; export * from './webhook-types.enum'; export * from './subscription-status.enum'; export * from './notification-type.enum'; -export * from './plans-tier.enum'; diff --git a/services/tenant-management-service/src/enums/plans-tier.enum.ts b/services/tenant-management-service/src/enums/plans-tier.enum.ts deleted file mode 100644 index acc3154..0000000 --- a/services/tenant-management-service/src/enums/plans-tier.enum.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum PlanTier { - POOLED, - SILO, -} diff --git a/services/tenant-management-service/src/models/dtos/plan-item-dto.model.ts b/services/tenant-management-service/src/models/dtos/plan-item-dto.model.ts deleted file mode 100644 index b1a3620..0000000 --- a/services/tenant-management-service/src/models/dtos/plan-item-dto.model.ts +++ /dev/null @@ -1,40 +0,0 @@ -import {Model, model, property} from '@loopback/repository'; -import {IPlanItem, IValue} from '../../types'; - -@model({ - description: 'model describing plan items', -}) -export class PlanItemDTO extends Model implements IPlanItem { - @property({ - type: 'string', - id: true, - generated: true, - }) - id: string; - - @property({ - type: 'string', - required: true, - description: 'name of the plan item', - }) - name: string; - - @property({ - type: 'string', - required: true, - name: 'plan_item_type', - description: 'type of the plan item', - }) - planItemType: string; - - @property({ - type: 'object', - required: true, - description: 'value of the plan item', - }) - value: IValue; - - constructor(data?: Partial) { - super(data); - } -} diff --git a/services/tenant-management-service/src/types/i-subscription.interface.ts b/services/tenant-management-service/src/types/i-subscription.interface.ts index ce0f6f1..5e0debe 100644 --- a/services/tenant-management-service/src/types/i-subscription.interface.ts +++ b/services/tenant-management-service/src/types/i-subscription.interface.ts @@ -1,5 +1,5 @@ +import {AnyObject} from '@loopback/repository'; import {IServiceConfig} from '@sourceloop/core'; -import {PlanTier} from '../enums'; export interface ISubscription { deleted?: boolean; @@ -88,9 +88,10 @@ export interface IPlan { price: number; currencyId: string; metaData: IMetaData; - tier: PlanTier; + tier: string; + size?: string; + sizeConfig?: AnyObject; billingCycleId: string; - planItems?: IPlanItem[]; billingCycle?: IBillingCycle; currency?: ICurrency; } @@ -98,23 +99,3 @@ export interface IPlan { export interface IMetaData { pipelineName: string; } - -export interface IPlanItem { - deleted?: boolean; - deletedOn?: string; - deletedBy?: string; - createdOn?: string; - modifiedOn?: string; - createdBy?: string; - modifiedBy?: string; - id: string; - name: string; - planItemType: string; - value: IValue; - planId?: string; -} - -export interface IValue { - name: string; - value: number | string | boolean; -} diff --git a/services/tenant-management-service/src/types/index.ts b/services/tenant-management-service/src/types/index.ts index ac6487e..9cea043 100644 --- a/services/tenant-management-service/src/types/index.ts +++ b/services/tenant-management-service/src/types/index.ts @@ -37,3 +37,4 @@ export * from './webhook-payload.type'; export * from './resource.type'; export * from './i-provisioning-service.interface'; export * from './i-subscription.interface'; +export * from './i-event-connector.interface';