mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 05:10:31 +00:00
Compare commits
4 Commits
fix-gettin
...
v0.19.13
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a79b9caff6 | ||
|
|
2227cead66 | ||
|
|
410c4ea3e2 | ||
|
|
ee2d8d3065 |
@@ -1,6 +1,8 @@
|
|||||||
import { Container } from 'typedi';
|
import { Container } from 'typedi';
|
||||||
import { Request, Response, NextFunction } from 'express';
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
|
||||||
|
const SupportedMethods = ['POST', 'PUT'];
|
||||||
|
|
||||||
export default (subscriptionSlug = 'main') =>
|
export default (subscriptionSlug = 'main') =>
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const { tenant, tenantId } = req;
|
const { tenant, tenantId } = req;
|
||||||
@@ -19,8 +21,10 @@ export default (subscriptionSlug = 'main') =>
|
|||||||
errors: [{ type: 'TENANT.HAS.NO.SUBSCRIPTION' }],
|
errors: [{ type: 'TENANT.HAS.NO.SUBSCRIPTION' }],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Validate in case the subscription is inactive.
|
const isMethodSupported = SupportedMethods.includes(req.method);
|
||||||
else if (subscription.inactive()) {
|
const isSubscriptionInactive = subscription.inactive();
|
||||||
|
|
||||||
|
if (isMethodSupported && isSubscriptionInactive) {
|
||||||
return res.boom.badRequest(null, {
|
return res.boom.badRequest(null, {
|
||||||
errors: [{ type: 'ORGANIZATION.SUBSCRIPTION.INACTIVE' }],
|
errors: [{ type: 'ORGANIZATION.SUBSCRIPTION.INACTIVE' }],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Model, mixin } from 'objection';
|
|||||||
import SystemModel from '@/system/models/SystemModel';
|
import SystemModel from '@/system/models/SystemModel';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import SubscriptionPeriod from '@/services/Subscription/SubscriptionPeriod';
|
import SubscriptionPeriod from '@/services/Subscription/SubscriptionPeriod';
|
||||||
|
import { SubscriptionPaymentStatus } from '@/interfaces';
|
||||||
|
|
||||||
export default class PlanSubscription extends mixin(SystemModel) {
|
export default class PlanSubscription extends mixin(SystemModel) {
|
||||||
public lemonSubscriptionId: number;
|
public lemonSubscriptionId: number;
|
||||||
@@ -13,6 +14,8 @@ export default class PlanSubscription extends mixin(SystemModel) {
|
|||||||
|
|
||||||
public trialEndsAt: Date;
|
public trialEndsAt: Date;
|
||||||
|
|
||||||
|
public paymentStatus: SubscriptionPaymentStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name.
|
* Table name.
|
||||||
*/
|
*/
|
||||||
@@ -31,7 +34,16 @@ export default class PlanSubscription extends mixin(SystemModel) {
|
|||||||
* Defined virtual attributes.
|
* Defined virtual attributes.
|
||||||
*/
|
*/
|
||||||
static get virtualAttributes() {
|
static get virtualAttributes() {
|
||||||
return ['active', 'inactive', 'ended', 'canceled', 'onTrial', 'status'];
|
return [
|
||||||
|
'active',
|
||||||
|
'inactive',
|
||||||
|
'ended',
|
||||||
|
'canceled',
|
||||||
|
'onTrial',
|
||||||
|
'status',
|
||||||
|
'isPaymentFailed',
|
||||||
|
'isPaymentSucceed',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,6 +81,22 @@ export default class PlanSubscription extends mixin(SystemModel) {
|
|||||||
|
|
||||||
builder.where('trial_ends_at', '<=', endDate);
|
builder.where('trial_ends_at', '<=', endDate);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the failed payment.
|
||||||
|
* @param builder
|
||||||
|
*/
|
||||||
|
failedPayment(builder) {
|
||||||
|
builder.where('payment_status', SubscriptionPaymentStatus.Failed);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the succeed payment.
|
||||||
|
* @param builder
|
||||||
|
*/
|
||||||
|
succeedPayment(builder) {
|
||||||
|
builder.where('payment_status', SubscriptionPaymentStatus.Succeed);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,10 +136,13 @@ export default class PlanSubscription extends mixin(SystemModel) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the subscription is active.
|
* Check if the subscription is active.
|
||||||
|
* Crtiria should be active:
|
||||||
|
* - During the trial period should NOT be canceled.
|
||||||
|
* - Out of trial period should NOT be ended.
|
||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
*/
|
*/
|
||||||
public active() {
|
public active() {
|
||||||
return this.onTrial() || !this.ended();
|
return this.onTrial() ? !this.canceled() : !this.ended();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -200,4 +231,20 @@ export default class PlanSubscription extends mixin(SystemModel) {
|
|||||||
);
|
);
|
||||||
return this.$query().update({ startsAt, endsAt });
|
return this.$query().update({ startsAt, endsAt });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines the subscription payment whether is failed.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public isPaymentFailed() {
|
||||||
|
return this.paymentStatus === SubscriptionPaymentStatus.Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines the subscription payment whether is succeed.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
public isPaymentSucceed() {
|
||||||
|
return this.paymentStatus === SubscriptionPaymentStatus.Succeed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,8 @@ export default class SubscriptionRepository extends SystemRepository {
|
|||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
*/
|
*/
|
||||||
getBySlugInTenant(slug: string, tenantId: number) {
|
getBySlugInTenant(slug: string, tenantId: number) {
|
||||||
const cacheKey = this.getCacheKey('getBySlugInTenant', slug, tenantId);
|
return PlanSubscription.query()
|
||||||
|
.findOne('slug', slug)
|
||||||
return this.cache.get(cacheKey, () => {
|
.where('tenant_id', tenantId);
|
||||||
return PlanSubscription.query()
|
|
||||||
.findOne('slug', slug)
|
|
||||||
.where('tenant_id', tenantId);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,15 @@ function GlobalErrors({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (globalErrors.subscriptionInactive) {
|
||||||
|
AppToaster.show({
|
||||||
|
message: `You can't add new data to Bigcapital because your subscription is inactive. Make sure your billing information is up-to-date from Preferences > Billing page.`,
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
onDismiss: () => {
|
||||||
|
globalErrorsSet({ subscriptionInactive: false });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
if (globalErrors.userInactive) {
|
if (globalErrors.userInactive) {
|
||||||
AppToaster.show({
|
AppToaster.show({
|
||||||
message: intl.get('global_error.authorized_user_inactive'),
|
message: intl.get('global_error.authorized_user_inactive'),
|
||||||
|
|||||||
@@ -64,12 +64,20 @@ export default function useApiRequest() {
|
|||||||
setGlobalErrors({ too_many_requests: true });
|
setGlobalErrors({ too_many_requests: true });
|
||||||
}
|
}
|
||||||
if (status === 400) {
|
if (status === 400) {
|
||||||
const lockedError = data.errors.find(
|
if (
|
||||||
(error) => error.type === 'TRANSACTIONS_DATE_LOCKED',
|
data.errors.find(
|
||||||
);
|
(error) => error.type === 'TRANSACTIONS_DATE_LOCKED',
|
||||||
if (lockedError) {
|
)
|
||||||
|
) {
|
||||||
setGlobalErrors({ transactionsLocked: { ...lockedError.data } });
|
setGlobalErrors({ transactionsLocked: { ...lockedError.data } });
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
data.errors.find(
|
||||||
|
(e) => e.type === 'ORGANIZATION.SUBSCRIPTION.INACTIVE',
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
setGlobalErrors({ subscriptionInactive: true });
|
||||||
|
}
|
||||||
if (data.errors.find((e) => e.type === 'USER_INACTIVE')) {
|
if (data.errors.find((e) => e.type === 'USER_INACTIVE')) {
|
||||||
setGlobalErrors({ userInactive: true });
|
setGlobalErrors({ userInactive: true });
|
||||||
setLogout();
|
setLogout();
|
||||||
|
|||||||
Reference in New Issue
Block a user