From 8b97673100e9c4c43e2fba7ba2cdb208bae0d538 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Tue, 13 Oct 2020 21:46:32 +0200 Subject: [PATCH] feat: retrieve organization subscriptions list api. feat: subscriptions reducers. --- .../Dashboard/DashboardLoadingIndicator.js | 1 - .../Dashboard/EnsureOrganizationIsReady.js | 6 +- .../src/components/Dashboard/PrivatePages.js | 17 ++++- .../src/containers/Setup/SetupLeftSection.js | 12 ++-- .../containers/Setup/SetupOrganizationForm.js | 39 ++++++----- .../src/containers/Setup/SetupRightSection.js | 22 ++++--- .../containers/Setup/SetupSubscriptionForm.js | 26 ++++++-- .../Subscriptions/billingPeriods.js | 2 +- .../containers/Subscriptions/billingPlans.js | 2 +- .../Subscriptions/withSubscriptions.js | 22 +++++++ .../Subscriptions/withSubscriptionsActions.js | 10 +++ client/src/lang/en/index.js | 1 + client/src/store/reducers.js | 5 +- .../subscription/subscription.actions.js | 14 ++++ .../subscription/subscription.reducer.js | 19 ++++++ .../subscription/subscription.selectors.js | 23 +++++++ .../store/subscription/subscription.types.js | 4 ++ client/src/store/types.js | 2 + .../src/style/pages/register-wizard-page.scss | 65 +++++++++++++++++-- .../src/api/controllers/Subscription/index.ts | 31 ++++++++- server/src/data/options.js | 4 ++ server/src/services/Organization/index.ts | 2 +- .../Subscription/SubscriptionService.ts | 15 ++++- 23 files changed, 289 insertions(+), 55 deletions(-) create mode 100644 client/src/containers/Subscriptions/withSubscriptions.js create mode 100644 client/src/containers/Subscriptions/withSubscriptionsActions.js create mode 100644 client/src/store/subscription/subscription.actions.js create mode 100644 client/src/store/subscription/subscription.reducer.js create mode 100644 client/src/store/subscription/subscription.selectors.js create mode 100644 client/src/store/subscription/subscription.types.js diff --git a/client/src/components/Dashboard/DashboardLoadingIndicator.js b/client/src/components/Dashboard/DashboardLoadingIndicator.js index e2d905f89..8a8009226 100644 --- a/client/src/components/Dashboard/DashboardLoadingIndicator.js +++ b/client/src/components/Dashboard/DashboardLoadingIndicator.js @@ -13,7 +13,6 @@ export default function DashboardLoadingIndicator({
- Please wait while resources loading...
diff --git a/client/src/components/Dashboard/EnsureOrganizationIsReady.js b/client/src/components/Dashboard/EnsureOrganizationIsReady.js index d24e32079..8870a4fed 100644 --- a/client/src/components/Dashboard/EnsureOrganizationIsReady.js +++ b/client/src/components/Dashboard/EnsureOrganizationIsReady.js @@ -13,9 +13,9 @@ function EnsureOrganizationIsReady({ redirectTo = '/setup', // #withOrganizationByOrgId - isOrganizationBuilt, + isOrganizationInitialized, }) { - return (isOrganizationBuilt) ? children : ( + return (isOrganizationInitialized) ? children : ( @@ -27,5 +27,5 @@ export default compose( connect((state, props) => ({ organizationId: props.currentOrganizationId, })), - withOrganization(({ isOrganizationBuilt }) => ({ isOrganizationBuilt })), + withOrganization(({ isOrganizationInitialized }) => ({ isOrganizationInitialized })), )(EnsureOrganizationIsReady); \ No newline at end of file diff --git a/client/src/components/Dashboard/PrivatePages.js b/client/src/components/Dashboard/PrivatePages.js index 499898113..b5909647b 100644 --- a/client/src/components/Dashboard/PrivatePages.js +++ b/client/src/components/Dashboard/PrivatePages.js @@ -7,6 +7,7 @@ import SetupWizardPage from 'containers/Setup/WizardSetupPage'; import DashboardLoadingIndicator from 'components/Dashboard/DashboardLoadingIndicator'; import withOrganizationActions from 'containers/Organization/withOrganizationActions'; +import withSubscriptionsActions from 'containers/Subscriptions/withSubscriptionsActions'; import { compose } from 'utils'; @@ -17,13 +18,26 @@ function DashboardPrivatePages({ // #withOrganizationActions requestAllOrganizations, + + // #withSubscriptionsActions + requestFetchSubscriptions, }) { + // Fetch all user's organizatins. const fetchOrganizations = useQuery( ['organizations'], () => requestAllOrganizations(), ); + // Fetchs organization subscriptions. + const fetchSuscriptions = useQuery( + ['susbcriptions'], () => requestFetchSubscriptions(), + { enabled: fetchOrganizations.data }, + ) + return ( - + @@ -39,4 +53,5 @@ function DashboardPrivatePages({ export default compose( withOrganizationActions, + withSubscriptionsActions, )(DashboardPrivatePages); \ No newline at end of file diff --git a/client/src/containers/Setup/SetupLeftSection.js b/client/src/containers/Setup/SetupLeftSection.js index 480a1947f..ae56c4db4 100644 --- a/client/src/containers/Setup/SetupLeftSection.js +++ b/client/src/containers/Setup/SetupLeftSection.js @@ -43,14 +43,18 @@ function SetupLeftSection({

+
- Your oragnization ID: { currentOrganizationId },
- + + Your oragnization ID: { currentOrganizationId }, + +
+ + +
- -

{'+21892-791-8381'}

diff --git a/client/src/containers/Setup/SetupOrganizationForm.js b/client/src/containers/Setup/SetupOrganizationForm.js index d865fffa0..be3b4e117 100644 --- a/client/src/containers/Setup/SetupOrganizationForm.js +++ b/client/src/containers/Setup/SetupOrganizationForm.js @@ -16,16 +16,20 @@ import classNames from 'classnames'; import { TimezonePicker } from '@blueprintjs/timezone'; import { FormattedMessage as T, useIntl } from 'react-intl'; import { DateInput } from '@blueprintjs/datetime'; +import { withWizard } from 'react-albus'; import { momentFormatter, tansformDateValue } from 'utils'; import { ListSelect, ErrorMessage, FieldRequiredHint } from 'components'; -import { useHistory } from 'react-router-dom'; import withSettingsActions from 'containers/Settings/withSettingsActions'; import withOrganizationActions from 'containers/Organization/withOrganizationActions'; import { compose, optionsMapToArray } from 'utils'; -function SetupOrganizationForm({ requestSubmitOptions, requestSeedTenant }) { +function SetupOrganizationForm({ + requestSubmitOptions, + requestOrganizationSeed, + wizard, +}) { const { formatMessage } = useIntl(); const [selected, setSelected] = useState(); @@ -130,7 +134,7 @@ function SetupOrganizationForm({ requestSubmitOptions, requestSeedTenant }) { name: Yup.string() .required() .label(formatMessage({ id: 'organization_name_' })), - date_start: Yup.date() + financial_date_start: Yup.date() .required() .label(formatMessage({ id: 'date_start_' })), base_currency: Yup.string() @@ -148,7 +152,7 @@ function SetupOrganizationForm({ requestSubmitOptions, requestSeedTenant }) { const initialValues = useMemo( () => ({ name: '', - date_start: moment(new Date()).format('YYYY-MM-DD'), + financial_date_start: moment(new Date()).format('YYYY-MM-DD'), base_currency: '', language: '', fiscal_year: '', @@ -176,7 +180,11 @@ function SetupOrganizationForm({ requestSubmitOptions, requestSeedTenant }) { return { key: option.key, ...option, group: 'organization' }; }); requestSubmitOptions({ options }) + .then(() => { + return requestOrganizationSeed(); + }) .then((response) => { + wizard.next(); setSubmitting(false); }) .catch((erros) => { @@ -220,29 +228,29 @@ function SetupOrganizationForm({ requestSubmitOptions, requestSeedTenant }) { const handleDateChange = useCallback( (date) => { const formatted = moment(date).format('YYYY-MM-DD'); - setFieldValue('date_start', formatted); + setFieldValue('financial_date_start', formatted); }, [setFieldValue], ); return ( -
-
-

+
+
+

-

-

+

+

-
+

} + label={} labelInfo={} className={'form-group--name'} intent={errors.name && touched.name && Intent.DANGER} @@ -258,15 +266,15 @@ function SetupOrganizationForm({ requestSubmitOptions, requestSeedTenant }) { } labelInfo={} - intent={errors.date_start && touched.date_start && Intent.DANGER} + intent={errors.financial_date_start && touched.financial_date_start && Intent.DANGER} helperText={ - + } className={classNames('form-group--select-list', Classes.FILL)} > @@ -410,4 +418,5 @@ function SetupOrganizationForm({ requestSubmitOptions, requestSeedTenant }) { export default compose( withSettingsActions, withOrganizationActions, + withWizard, )(SetupOrganizationForm); diff --git a/client/src/containers/Setup/SetupRightSection.js b/client/src/containers/Setup/SetupRightSection.js index b6e490889..d8b1360fb 100644 --- a/client/src/containers/Setup/SetupRightSection.js +++ b/client/src/containers/Setup/SetupRightSection.js @@ -5,6 +5,7 @@ import { useHistory } from "react-router-dom"; import { connect } from 'react-redux'; import WizardSetupSteps from './WizardSetupSteps'; +import withSubscriptions from 'containers/Subscriptions/withSubscriptions'; import SetupSubscriptionForm from './SetupSubscriptionForm'; import SetupOrganizationForm from './SetupOrganizationForm'; @@ -23,16 +24,18 @@ function SetupRightSection ({ // #withOrganization isOrganizationInitialized, - isOrganizationSubscribed: hasSubscriptions, - isOrganizationSeeded + isOrganizationSeeded, + + // #withSubscriptions + isSubscriptionActive }) { const history = useHistory(); const handleSkip = useCallback(({ step, push }) => { const scenarios = [ - { condition: !hasSubscriptions, redirectTo: 'subscription' }, - { condition: hasSubscriptions && !isOrganizationInitialized, redirectTo: 'initializing' }, - { condition: hasSubscriptions && !isOrganizationSeeded, redirectTo: 'organization' }, + { condition: !isSubscriptionActive, redirectTo: 'subscription' }, + { condition: isSubscriptionActive && !isOrganizationInitialized, redirectTo: 'initializing' }, + { condition: isSubscriptionActive && !isOrganizationSeeded, redirectTo: 'organization' }, ]; const scenario = scenarios.find((scenario) => scenario.condition); @@ -40,7 +43,7 @@ function SetupRightSection ({ push(scenario.redirectTo); } }, [ - hasSubscriptions, + isSubscriptionActive, isOrganizationInitialized, isOrganizationSeeded, ]); @@ -92,12 +95,15 @@ export default compose( withOrganization(({ organization, isOrganizationInitialized, - isOrganizationSubscribed, isOrganizationSeeded, }) => ({ organization, isOrganizationInitialized, - isOrganizationSubscribed, isOrganizationSeeded, })), + withSubscriptions(({ + isSubscriptionActive, + }) => ({ + isSubscriptionActive + }), 'main'), )(SetupRightSection); \ No newline at end of file diff --git a/client/src/containers/Setup/SetupSubscriptionForm.js b/client/src/containers/Setup/SetupSubscriptionForm.js index d9c69e04c..ba3c2be35 100644 --- a/client/src/containers/Setup/SetupSubscriptionForm.js +++ b/client/src/containers/Setup/SetupSubscriptionForm.js @@ -3,10 +3,11 @@ import * as Yup from 'yup'; import { useFormik } from 'formik'; import { FormattedMessage as T, useIntl } from 'react-intl'; import { Button, Intent } from '@blueprintjs/core'; +import { withWizard } from 'react-albus'; +import withSubscriptionsActions from 'containers/Subscriptions/withSubscriptionsActions'; import BillingPlans from 'containers/Subscriptions/billingPlans'; import BillingPeriods from 'containers/Subscriptions/billingPeriods'; import { BillingPaymentmethod } from 'containers/Subscriptions/billingPaymentmethod'; - import withBillingActions from 'containers/Subscriptions/withBillingActions'; import { compose } from 'utils'; @@ -14,18 +15,23 @@ import { compose } from 'utils'; * Subscription step of wizard setup. */ function SetupSubscriptionForm({ - //#withBillingActions + // #withBillingActions requestSubmitBilling, + + // #withWizard + wizard, + + // #withSubscriptionsActions + requestFetchSubscriptions }) { const { formatMessage } = useIntl(); - const validationSchema = Yup.object().shape({ plan_slug: Yup.string() .required() .label(formatMessage({ id: 'plan_slug' })), license_code: Yup.string() - .min(7) - .max(7) + .min(10) + .max(10) .required() .label(formatMessage({ id: 'license_code_' })) .trim(), @@ -48,6 +54,10 @@ function SetupSubscriptionForm({ onSubmit: (values, { setSubmitting, setErrors }) => { requestSubmitBilling(values) .then((response) => { + return requestFetchSubscriptions(); + }) + .then(() => { + wizard.next(); setSubmitting(false); }) .catch((errors) => { @@ -76,4 +86,8 @@ function SetupSubscriptionForm({ ); } -export default compose(withBillingActions)(SetupSubscriptionForm); +export default compose( + withBillingActions, + withWizard, + withSubscriptionsActions, +)(SetupSubscriptionForm); diff --git a/client/src/containers/Subscriptions/billingPeriods.js b/client/src/containers/Subscriptions/billingPeriods.js index ad2d03ad1..9454bdaff 100644 --- a/client/src/containers/Subscriptions/billingPeriods.js +++ b/client/src/containers/Subscriptions/billingPeriods.js @@ -45,7 +45,7 @@ function BillingPeriods({ formik, title, selected = 1 }) { return (
-

+

diff --git a/client/src/containers/Subscriptions/billingPlans.js b/client/src/containers/Subscriptions/billingPlans.js index 41aa17070..f94e14c1e 100644 --- a/client/src/containers/Subscriptions/billingPlans.js +++ b/client/src/containers/Subscriptions/billingPlans.js @@ -62,7 +62,7 @@ function BillingPlans({ formik, title, selected = 1 }) { return (

-

+

diff --git a/client/src/containers/Subscriptions/withSubscriptions.js b/client/src/containers/Subscriptions/withSubscriptions.js new file mode 100644 index 000000000..441dc0fb6 --- /dev/null +++ b/client/src/containers/Subscriptions/withSubscriptions.js @@ -0,0 +1,22 @@ +import { connect } from 'react-redux'; +import { + isSubscriptionOnTrialFactory, + isSubscriptionInactiveFactory, + isSubscriptionActiveFactory, +} from 'store/subscription/subscription.selectors'; + +export default (mapState, slug) => { + const isSubscriptionOnTrial = isSubscriptionOnTrialFactory(slug); + const isSubscriptionInactive = isSubscriptionInactiveFactory(slug); + const isSubscriptionActive = isSubscriptionActiveFactory(slug); + + const mapStateToProps = (state, props) => { + const mapped = { + isSubscriptionOnTrial: isSubscriptionOnTrial(state, props), + isSubscriptionInactive: isSubscriptionInactive(state, props), + isSubscriptionActive: isSubscriptionActive(state, props), + }; + return (mapState) ? mapState(mapped, state, props) : mapped; + }; + return connect(mapStateToProps); +}; \ No newline at end of file diff --git a/client/src/containers/Subscriptions/withSubscriptionsActions.js b/client/src/containers/Subscriptions/withSubscriptionsActions.js new file mode 100644 index 000000000..2b8ed6694 --- /dev/null +++ b/client/src/containers/Subscriptions/withSubscriptionsActions.js @@ -0,0 +1,10 @@ +import { connect } from 'react-redux'; +import { + fetchSubscriptions, +} from 'store/subscription/subscription.actions' + +const mapDispatchToProps = (dispatch) => ({ + requestFetchSubscriptions: () => dispatch(fetchSubscriptions()), +}); + +export default connect(null, mapDispatchToProps); \ No newline at end of file diff --git a/client/src/lang/en/index.js b/client/src/lang/en/index.js index 5396a8dd7..2fc8eb4c4 100644 --- a/client/src/lang/en/index.js +++ b/client/src/lang/en/index.js @@ -765,4 +765,5 @@ export default { something_wentwrong: 'Something went wrong.', new_password: 'New password', license_code_: 'License code', + legal_organization_name: 'Legal Organization Name' }; diff --git a/client/src/store/reducers.js b/client/src/store/reducers.js index 2827e1eed..62e4188ce 100644 --- a/client/src/store/reducers.js +++ b/client/src/store/reducers.js @@ -26,10 +26,12 @@ import vendors from './vendors/vendors.reducer'; import paymentReceives from './PaymentReceive/paymentReceive.reducer'; import paymentMades from './PaymentMades/paymentMade.reducer'; import organizations from './organizations/organizations.reducers'; +import subscriptions from './subscription/subscription.reducer'; export default combineReducers({ authentication, organizations, + subscriptions, dashboard, users, accounts, @@ -47,12 +49,11 @@ export default combineReducers({ exchangeRates, globalErrors, customers, - salesEstimates, salesInvoices, salesReceipts, bills, vendors, paymentReceives, - paymentMades + paymentMades, }); diff --git a/client/src/store/subscription/subscription.actions.js b/client/src/store/subscription/subscription.actions.js new file mode 100644 index 000000000..28ef9d8f2 --- /dev/null +++ b/client/src/store/subscription/subscription.actions.js @@ -0,0 +1,14 @@ +import ApiService from 'services/ApiService'; +import t from 'store/types'; + +export const fetchSubscriptions = () => (dispatch) => new Promise((resolve, reject) => { + ApiService.get('subscription').then((response) => { + dispatch({ + type: t.SET_PLAN_SUBSCRIPTIONS_LIST, + payload: { + subscriptions: response.data.subscriptions, + }, + }); + resolve(response); + }).catch((error) => { reject(error); }) +}); \ No newline at end of file diff --git a/client/src/store/subscription/subscription.reducer.js b/client/src/store/subscription/subscription.reducer.js new file mode 100644 index 000000000..ee9e20f9b --- /dev/null +++ b/client/src/store/subscription/subscription.reducer.js @@ -0,0 +1,19 @@ +import { createReducer } from '@reduxjs/toolkit'; +import t from 'store/types'; + +const initialState = { + data: {}, +}; + +export default createReducer(initialState, { + + [t.SET_PLAN_SUBSCRIPTIONS_LIST]: (state, action) => { + const { subscriptions } = action.payload; + const _data = {}; + + subscriptions.forEach((subscription) => { + _data[subscription.id] = subscription; + }); + state.data = _data; + }, +}); diff --git a/client/src/store/subscription/subscription.selectors.js b/client/src/store/subscription/subscription.selectors.js new file mode 100644 index 000000000..eb59631db --- /dev/null +++ b/client/src/store/subscription/subscription.selectors.js @@ -0,0 +1,23 @@ +import { createSelector } from '@reduxjs/toolkit'; + +const subscriptionSelector = (slug) => (state, props) => { + const subscriptions = Object.values(state.subscriptions.data); + return subscriptions.find((subscription) => subscription.slug === slug); +}; + +export const isSubscriptionOnTrialFactory = (slug) => createSelector( + subscriptionSelector(slug), + (subscription) => !!subscription?.on_trial, +); + +export const isSubscriptionActiveFactory = (slug) => createSelector( + subscriptionSelector(slug), + (subscription) => { + return !!subscription?.active; + } +); + +export const isSubscriptionInactiveFactory = (slug) => createSelector( + subscriptionSelector(slug), + (subscription) => !!subscription?.inactive, +); \ No newline at end of file diff --git a/client/src/store/subscription/subscription.types.js b/client/src/store/subscription/subscription.types.js new file mode 100644 index 000000000..6a9692684 --- /dev/null +++ b/client/src/store/subscription/subscription.types.js @@ -0,0 +1,4 @@ + +export default { + SET_PLAN_SUBSCRIPTIONS_LIST: 'SET_PLAN_SUBSCRIPTIONS_LIST', +}; \ No newline at end of file diff --git a/client/src/store/types.js b/client/src/store/types.js index 755bad8dc..3e4a32ed8 100644 --- a/client/src/store/types.js +++ b/client/src/store/types.js @@ -25,6 +25,7 @@ import vendors from './vendors/vendors.types'; import paymentReceives from './PaymentReceive/paymentReceive.type'; import paymentMades from './PaymentMades/paymentMade.type'; import organizations from './organizations/organizations.types'; +import subscription from './subscription/subscription.types'; export default { ...authentication, @@ -54,4 +55,5 @@ export default { ...paymentReceives, ...paymentMades, ...organizations, + ...subscription, }; diff --git a/client/src/style/pages/register-wizard-page.scss b/client/src/style/pages/register-wizard-page.scss index 26844cd32..598ed3462 100644 --- a/client/src/style/pages/register-wizard-page.scss +++ b/client/src/style/pages/register-wizard-page.scss @@ -20,13 +20,17 @@ h1{ font-size: 22px; + } + h1, + h3{ font-weight: 500; - color: #6d6d6d; + color: #6b7382; } } &__content{ width: 70%; + padding-bottom: 40px; } &__left-section { @@ -68,7 +72,7 @@ &__text { font-size: 16px; opacity: 0.75; - margin-bottom: 18px; + margin-bottom: 10px; } &__organization { @@ -87,7 +91,7 @@ height: 3px; width: 100px; background: rgba(255, 255, 255, 0.15); - margin: 20px 0; + margin: 10px 0; } &__footer{ @@ -190,7 +194,54 @@ } } -//Register Subscription form -.register-subscription-form { - -} +.setup-organization { + width: 580px; + margin: 0 auto; + padding: 45px 0 20px; + + &__title-wrap{ + margin-bottom: 20px; + + h1 { + margin-top: 0; + margin-bottom: 10px; + color: #565e6c; + } + } + + &__form{ + h3 { + margin-bottom: 1rem; + } + } + + .bp3-form-group { + .bp3-input-group { + .bp3-input { + height: 38px; + } + } + } + + .bp3-button:not([class*='bp3-intent-']):not(.bp3-minimal) { + width: 100%; + height: 38px; + } + + .register-org-note{ + font-size: 13px; + padding-bottom: 10px; + border-bottom: 1px solid #e1e1e1; + margin-bottom: 1.75rem; + color: #666; + } + + .register-org-button { + .bp3-button { + background-color: #0052cc; + min-width: 175px; + height: 40px; + font-size: 15px; + } + } +} \ No newline at end of file diff --git a/server/src/api/controllers/Subscription/index.ts b/server/src/api/controllers/Subscription/index.ts index 1154de6a7..1485e7249 100644 --- a/server/src/api/controllers/Subscription/index.ts +++ b/server/src/api/controllers/Subscription/index.ts @@ -1,12 +1,17 @@ -import { Router } from 'express' -import { Container, Service } from 'typedi'; +import { Router, Request, Response, NextFunction } from 'express' +import { Container, Service, Inject } from 'typedi'; import JWTAuth from 'api/middleware/jwtAuth'; import TenancyMiddleware from 'api/middleware/TenancyMiddleware'; import AttachCurrentTenantUser from 'api/middleware/AttachCurrentTenantUser'; import PaymentViaLicenseController from 'api/controllers/Subscription/PaymentViaLicense'; +import SubscriptionService from 'services/Subscription/SubscriptionService'; +import asyncMiddleware from 'api/middleware/asyncMiddleware'; @Service() -export default class SubscriptionController { +export default class SubscriptionController { + @Inject() + subscriptionService: SubscriptionService; + /** * Router constructor. */ @@ -19,6 +24,26 @@ export default class SubscriptionController { router.use('/license', Container.get(PaymentViaLicenseController).router()); + router.get('/', + asyncMiddleware(this.getSubscriptions.bind(this)) + ); return router; } + + /** + * Retrieve all subscriptions of the authenticated user's tenant. + * @param {Request} req + * @param {Response} res + * @param {NextFunction} next + */ + async getSubscriptions(req: Request, res: Response, next: NextFunction) { + const { tenantId } = req; + + try { + const subscriptions = await this.subscriptionService.getSubscriptions(tenantId); + return res.status(200).send({ subscriptions }); + } catch (error) { + next(error); + } + } } diff --git a/server/src/data/options.js b/server/src/data/options.js index e10fee599..727bce956 100644 --- a/server/src/data/options.js +++ b/server/src/data/options.js @@ -25,6 +25,10 @@ export default { type: 'string', // config: true, }, + { + key: 'financial_date_start', + type: 'string', + }, { key: 'language', type: 'string', diff --git a/server/src/services/Organization/index.ts b/server/src/services/Organization/index.ts index 48fde80b3..a50d67930 100644 --- a/server/src/services/Organization/index.ts +++ b/server/src/services/Organization/index.ts @@ -100,7 +100,7 @@ export default class OrganizationService { this.logger.info('[organization] trying to list all organizations.', { user }); const { tenantRepository } = this.sysRepositories; - const tenant = await tenantRepository.getByIdWithSubscriptions(user.tenantId); + const tenant = await tenantRepository.getById(user.tenantId); return [tenant]; } diff --git a/server/src/services/Subscription/SubscriptionService.ts b/server/src/services/Subscription/SubscriptionService.ts index 695a0687c..8508b5746 100644 --- a/server/src/services/Subscription/SubscriptionService.ts +++ b/server/src/services/Subscription/SubscriptionService.ts @@ -1,5 +1,5 @@ import { Service, Inject } from 'typedi'; -import { Plan, Tenant } from 'system/models'; +import { Plan, PlanSubscription } from 'system/models'; import Subscription from 'services/Subscription/Subscription'; import LicensePaymentMethod from 'services/Payment/LicensePaymentMethod'; import PaymentContext from 'services/Payment'; @@ -29,7 +29,7 @@ export default class SubscriptionService { * @param {string} licenseCode * @return {Promise} */ - async subscriptionViaLicense( + public async subscriptionViaLicense( tenantId: number, planSlug: string, paymentModel?: ILicensePaymentModel, @@ -53,4 +53,15 @@ export default class SubscriptionService { tenantId, paymentModel }); } + + /** + * Retrieve all subscription of the given tenant. + * @param {number} tenantId + */ + public async getSubscriptions(tenantId: number) { + this.logger.info('[subscription] trying to get tenant subscriptions.', { tenantId }); + const subscriptions = await PlanSubscription.query().where('tenant_id', tenantId); + + return subscriptions; + } } \ No newline at end of file