mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 16:23:06 +10:00
This PR is handles the changes required to support envelopes. The new envelope editor/signing page will be hidden during release. The core changes here is to migrate the documents and templates model to a centralized envelopes model. Even though Documents and Templates are removed, from the user perspective they will still exist as we remap envelopes to documents and templates.
122 lines
2.9 KiB
TypeScript
122 lines
2.9 KiB
TypeScript
import { DocumentSource, EnvelopeType, SubscriptionStatus } from '@prisma/client';
|
|
import { DateTime } from 'luxon';
|
|
|
|
import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app';
|
|
import { INTERNAL_CLAIM_ID } from '@documenso/lib/types/subscription';
|
|
import { prisma } from '@documenso/prisma';
|
|
|
|
import {
|
|
FREE_PLAN_LIMITS,
|
|
INACTIVE_PLAN_LIMITS,
|
|
PAID_PLAN_LIMITS,
|
|
SELFHOSTED_PLAN_LIMITS,
|
|
} from './constants';
|
|
import { ERROR_CODES } from './errors';
|
|
import type { TLimitsResponseSchema } from './schema';
|
|
|
|
export type GetServerLimitsOptions = {
|
|
userId: number;
|
|
teamId: number;
|
|
};
|
|
|
|
export const getServerLimits = async ({
|
|
userId,
|
|
teamId,
|
|
}: GetServerLimitsOptions): Promise<TLimitsResponseSchema> => {
|
|
if (!IS_BILLING_ENABLED()) {
|
|
return {
|
|
quota: SELFHOSTED_PLAN_LIMITS,
|
|
remaining: SELFHOSTED_PLAN_LIMITS,
|
|
};
|
|
}
|
|
|
|
const organisation = await prisma.organisation.findFirst({
|
|
where: {
|
|
teams: {
|
|
some: {
|
|
id: teamId,
|
|
},
|
|
},
|
|
members: {
|
|
some: {
|
|
userId,
|
|
},
|
|
},
|
|
},
|
|
include: {
|
|
subscription: true,
|
|
organisationClaim: true,
|
|
},
|
|
});
|
|
|
|
if (!organisation) {
|
|
throw new Error(ERROR_CODES.USER_FETCH_FAILED);
|
|
}
|
|
|
|
const quota = structuredClone(FREE_PLAN_LIMITS);
|
|
const remaining = structuredClone(FREE_PLAN_LIMITS);
|
|
|
|
const subscription = organisation.subscription;
|
|
|
|
// Bypass all limits even if plan expired for ENTERPRISE.
|
|
if (organisation.organisationClaimId === INTERNAL_CLAIM_ID.ENTERPRISE) {
|
|
return {
|
|
quota: PAID_PLAN_LIMITS,
|
|
remaining: PAID_PLAN_LIMITS,
|
|
};
|
|
}
|
|
|
|
// Early return for users with an expired subscription.
|
|
if (subscription && subscription.status !== SubscriptionStatus.ACTIVE) {
|
|
return {
|
|
quota: INACTIVE_PLAN_LIMITS,
|
|
remaining: INACTIVE_PLAN_LIMITS,
|
|
};
|
|
}
|
|
|
|
// Allow unlimited documents for users with an unlimited documents claim.
|
|
// This also allows "free" claim users without subscriptions if they have this flag.
|
|
if (organisation.organisationClaim.flags.unlimitedDocuments) {
|
|
return {
|
|
quota: PAID_PLAN_LIMITS,
|
|
remaining: PAID_PLAN_LIMITS,
|
|
};
|
|
}
|
|
|
|
const [documents, directTemplates] = await Promise.all([
|
|
prisma.envelope.count({
|
|
where: {
|
|
type: EnvelopeType.DOCUMENT,
|
|
team: {
|
|
organisationId: organisation.id,
|
|
},
|
|
createdAt: {
|
|
gte: DateTime.utc().startOf('month').toJSDate(),
|
|
},
|
|
source: {
|
|
not: DocumentSource.TEMPLATE_DIRECT_LINK,
|
|
},
|
|
},
|
|
}),
|
|
prisma.envelope.count({
|
|
where: {
|
|
type: EnvelopeType.TEMPLATE,
|
|
team: {
|
|
organisationId: organisation.id,
|
|
},
|
|
directLink: {
|
|
isNot: null,
|
|
},
|
|
},
|
|
}),
|
|
]);
|
|
|
|
remaining.documents = Math.max(remaining.documents - documents, 0);
|
|
remaining.directTemplates = Math.max(remaining.directTemplates - directTemplates, 0);
|
|
|
|
return {
|
|
quota,
|
|
remaining,
|
|
};
|
|
};
|