fix: get stats query

This commit is contained in:
Ephraim Atta-Duncan
2024-12-10 23:33:14 +00:00
parent 2b3ab9a3b7
commit b19b57dbc9
3 changed files with 187 additions and 96 deletions

View File

@ -4,8 +4,8 @@ import { Trans } from '@lingui/macro';
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session'; import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session';
import { findDocuments } from '@documenso/lib/server-only/document/find-documents';
import type { PeriodSelectorValue } from '@documenso/lib/server-only/document/find-documents'; import type { PeriodSelectorValue } from '@documenso/lib/server-only/document/find-documents';
import { findDocuments } from '@documenso/lib/server-only/document/find-documents';
import type { GetStatsInput } from '@documenso/lib/server-only/document/get-stats'; import type { GetStatsInput } from '@documenso/lib/server-only/document/get-stats';
import { getStats } from '@documenso/lib/server-only/document/get-stats'; import { getStats } from '@documenso/lib/server-only/document/get-stats';
import { parseToIntegerArray } from '@documenso/lib/utils/params'; import { parseToIntegerArray } from '@documenso/lib/utils/params';

View File

@ -16,8 +16,8 @@ ENV_FILES.forEach((file) => {
export default defineConfig({ export default defineConfig({
testDir: './e2e', testDir: './e2e',
/* Run tests in files in parallel */ /* Run tests in files in parallel */
fullyParallel: true, fullyParallel: false,
workers: '50%', workers: 1,
/* Fail the build on CI if you accidentally left test.only in the source code. */ /* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI, forbidOnly: !!process.env.CI,
/* Retry on CI only */ /* Retry on CI only */

View File

@ -1,12 +1,16 @@
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { match } from 'ts-pattern'; import { match } from 'ts-pattern';
// eslint-disable-next-line import/no-extraneous-dependencies
import type { PeriodSelectorValue } from '@documenso/lib/server-only/document/find-documents'; import type { PeriodSelectorValue } from '@documenso/lib/server-only/document/find-documents';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import { TeamMemberRole } from '@documenso/prisma/client';
import type { Prisma, User } from '@documenso/prisma/client'; import type { Prisma, User } from '@documenso/prisma/client';
import { SigningStatus } from '@documenso/prisma/client'; import {
import { DocumentVisibility } from '@documenso/prisma/client'; DocumentVisibility,
RecipientRole,
SigningStatus,
TeamMemberRole,
} from '@documenso/prisma/client';
import { isExtendedDocumentStatus } from '@documenso/prisma/guards/is-extended-document-status'; import { isExtendedDocumentStatus } from '@documenso/prisma/guards/is-extended-document-status';
import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status'; import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status';
@ -103,25 +107,52 @@ const getCounts = async ({ user, createdAt, search }: GetCountsOption) => {
_all: true, _all: true,
}, },
where: { where: {
userId: user.id, OR: [
{
userId: user.id,
teamId: null,
deletedAt: null,
},
{
status: ExtendedDocumentStatus.COMPLETED,
Recipient: {
some: {
email: user.email,
documentDeletedAt: null,
},
},
},
{
status: ExtendedDocumentStatus.PENDING,
Recipient: {
some: {
email: user.email,
documentDeletedAt: null,
},
},
},
],
createdAt, createdAt,
teamId: null,
deletedAt: null,
AND: [searchFilter], AND: [searchFilter],
}, },
}), }),
// Not signed counts. // Not signed counts (Inbox).
prisma.document.groupBy({ prisma.document.groupBy({
by: ['status'], by: ['status'],
_count: { _count: {
_all: true, _all: true,
}, },
where: { where: {
status: ExtendedDocumentStatus.PENDING, status: {
not: ExtendedDocumentStatus.DRAFT,
},
Recipient: { Recipient: {
some: { some: {
email: user.email, email: user.email,
signingStatus: SigningStatus.NOT_SIGNED, signingStatus: SigningStatus.NOT_SIGNED,
role: {
not: 'CC',
},
documentDeletedAt: null, documentDeletedAt: null,
}, },
}, },
@ -136,34 +167,43 @@ const getCounts = async ({ user, createdAt, search }: GetCountsOption) => {
_all: true, _all: true,
}, },
where: { where: {
createdAt,
User: {
email: {
not: user.email,
},
},
OR: [ OR: [
{
userId: user.id,
teamId: null,
status: ExtendedDocumentStatus.PENDING,
deletedAt: null,
},
{ {
status: ExtendedDocumentStatus.PENDING, status: ExtendedDocumentStatus.PENDING,
Recipient: { Recipient: {
some: { some: {
email: user.email, email: user.email,
signingStatus: SigningStatus.SIGNED, signingStatus: SigningStatus.SIGNED,
role: {
not: 'CC',
},
documentDeletedAt: null, documentDeletedAt: null,
}, },
}, },
}, },
{
userId: user.id,
teamId: null,
status: ExtendedDocumentStatus.COMPLETED,
deletedAt: null,
},
{ {
status: ExtendedDocumentStatus.COMPLETED, status: ExtendedDocumentStatus.COMPLETED,
Recipient: { Recipient: {
some: { some: {
email: user.email, email: user.email,
signingStatus: SigningStatus.SIGNED,
documentDeletedAt: null, documentDeletedAt: null,
}, },
}, },
}, },
], ],
createdAt,
AND: [searchFilter], AND: [searchFilter],
}, },
}), }),
@ -199,7 +239,6 @@ const getCounts = async ({ user, createdAt, search }: GetCountsOption) => {
Recipient: { Recipient: {
some: { some: {
email: user.email, email: user.email,
signingStatus: SigningStatus.SIGNED,
documentDeletedAt: { documentDeletedAt: {
gte: DateTime.now().minus({ days: 30 }).startOf('day').toJSDate(), gte: DateTime.now().minus({ days: 30 }).startOf('day').toJSDate(),
}, },
@ -207,6 +246,7 @@ const getCounts = async ({ user, createdAt, search }: GetCountsOption) => {
}, },
}, },
], ],
AND: [searchFilter],
}, },
}), }),
]); ]);
@ -224,15 +264,7 @@ type GetTeamCountsOption = {
}; };
const getTeamCounts = async (options: GetTeamCountsOption) => { const getTeamCounts = async (options: GetTeamCountsOption) => {
const { const { createdAt, teamId, teamEmail, senderIds = [], currentTeamMemberRole, search } = options;
createdAt,
teamId,
teamEmail,
senderIds = [],
currentUserEmail,
currentTeamMemberRole,
search,
} = options;
const userIdWhereClause: Prisma.DocumentWhereInput['userId'] = const userIdWhereClause: Prisma.DocumentWhereInput['userId'] =
senderIds.length > 0 senderIds.length > 0
@ -241,113 +273,171 @@ const getTeamCounts = async (options: GetTeamCountsOption) => {
} }
: undefined; : undefined;
const searchFilter: Prisma.DocumentWhereInput = { const searchFilter: Prisma.DocumentWhereInput = search
OR: [ ? {
{ title: { contains: search, mode: 'insensitive' } }, OR: [
{ Recipient: { some: { name: { contains: search, mode: 'insensitive' } } } }, { title: { contains: search, mode: 'insensitive' } },
{ Recipient: { some: { email: { contains: search, mode: 'insensitive' } } } }, { Recipient: { some: { name: { contains: search, mode: 'insensitive' } } } },
], { Recipient: { some: { email: { contains: search, mode: 'insensitive' } } } },
}; ],
}
: {};
const visibilityFilters = [ const visibilityFilters = [
...match(currentTeamMemberRole) match(currentTeamMemberRole)
.with(TeamMemberRole.ADMIN, () => [ .with(TeamMemberRole.ADMIN, () => ({
{ visibility: DocumentVisibility.EVERYONE }, visibility: {
{ visibility: DocumentVisibility.MANAGER_AND_ABOVE }, in: [
{ visibility: DocumentVisibility.ADMIN }, DocumentVisibility.EVERYONE,
]) DocumentVisibility.MANAGER_AND_ABOVE,
.with(TeamMemberRole.MANAGER, () => [ DocumentVisibility.ADMIN,
{ visibility: DocumentVisibility.EVERYONE }, ],
{ visibility: DocumentVisibility.MANAGER_AND_ABOVE }, },
]) }))
.otherwise(() => [{ visibility: DocumentVisibility.EVERYONE }]), .with(TeamMemberRole.MANAGER, () => ({
visibility: {
in: [DocumentVisibility.EVERYONE, DocumentVisibility.MANAGER_AND_ABOVE],
},
}))
.otherwise(() => ({ visibility: DocumentVisibility.EVERYONE })),
]; ];
// Owner counts (ALL)
const ownerCountsWhereInput: Prisma.DocumentWhereInput = { const ownerCountsWhereInput: Prisma.DocumentWhereInput = {
userId: userIdWhereClause, userId: userIdWhereClause,
createdAt, createdAt,
OR: [ OR: [
{ teamId },
...(teamEmail ? [{ User: { email: teamEmail } }] : []),
{ {
AND: [ teamId,
{ deletedAt: null,
visibility: { OR: visibilityFilters,
in: visibilityFilters.map((filter) => filter.visibility),
},
},
{
Recipient: {
none: {
email: currentUserEmail,
},
},
},
],
}, },
{
Recipient: {
some: {
email: currentUserEmail,
},
},
},
],
deletedAt: null,
...searchFilter,
};
const notSignedCountsWhereInput: Prisma.DocumentWhereInput = {
userId: userIdWhereClause,
createdAt,
status: ExtendedDocumentStatus.PENDING,
OR: [
{ teamId },
...(teamEmail ...(teamEmail
? [ ? [
{ {
status: {
not: ExtendedDocumentStatus.DRAFT,
},
Recipient: { Recipient: {
some: { some: {
email: teamEmail, email: teamEmail,
signingStatus: SigningStatus.NOT_SIGNED,
documentDeletedAt: null,
}, },
}, },
deletedAt: null,
OR: visibilityFilters,
},
{
User: {
email: teamEmail,
},
deletedAt: null,
OR: visibilityFilters,
}, },
] ]
: []), : []),
], ],
deletedAt: null, ...searchFilter,
}; };
// Not signed counts (INBOX)
const notSignedCountsWhereInput: Prisma.DocumentWhereInput = teamEmail
? {
userId: userIdWhereClause,
createdAt,
status: {
not: ExtendedDocumentStatus.DRAFT,
},
Recipient: {
some: {
email: teamEmail,
signingStatus: SigningStatus.NOT_SIGNED,
role: {
not: RecipientRole.CC,
},
},
},
deletedAt: null,
OR: visibilityFilters,
...searchFilter,
}
: {
userId: userIdWhereClause,
createdAt,
AND: [
{
OR: [{ id: -1 }], // Empty set if no team email
},
searchFilter,
],
};
// Has signed counts (PENDING + COMPLETED)
const hasSignedCountsWhereInput: Prisma.DocumentWhereInput = { const hasSignedCountsWhereInput: Prisma.DocumentWhereInput = {
userId: userIdWhereClause, userId: userIdWhereClause,
createdAt, createdAt,
OR: [ OR: [
{ {
teamId, teamId,
status: { status: ExtendedDocumentStatus.PENDING,
in: [ExtendedDocumentStatus.PENDING, ExtendedDocumentStatus.COMPLETED], deletedAt: null,
}, OR: visibilityFilters,
},
{
teamId,
status: ExtendedDocumentStatus.COMPLETED,
deletedAt: null,
OR: visibilityFilters,
}, },
...(teamEmail ...(teamEmail
? [ ? [
{ {
Recipient: { status: ExtendedDocumentStatus.PENDING,
some: { OR: [
email: teamEmail, {
signingStatus: SigningStatus.SIGNED, Recipient: {
documentDeletedAt: null, some: {
email: teamEmail,
signingStatus: SigningStatus.SIGNED,
role: {
not: RecipientRole.CC,
},
},
},
OR: visibilityFilters,
}, },
}, {
status: { User: {
in: [ExtendedDocumentStatus.PENDING, ExtendedDocumentStatus.COMPLETED], email: teamEmail,
}, },
OR: visibilityFilters,
},
],
deletedAt: null,
},
{
status: ExtendedDocumentStatus.COMPLETED,
OR: [
{
Recipient: {
some: {
email: teamEmail,
},
},
OR: visibilityFilters,
},
{
User: {
email: teamEmail,
},
OR: visibilityFilters,
},
],
deletedAt: null,
}, },
] ]
: []), : []),
], ],
deletedAt: null, ...searchFilter,
}; };
const deletedCountsWhereInput: Prisma.DocumentWhereInput = { const deletedCountsWhereInput: Prisma.DocumentWhereInput = {
@ -373,6 +463,7 @@ const getTeamCounts = async (options: GetTeamCountsOption) => {
] ]
: []), : []),
], ],
...searchFilter,
}; };
return Promise.all([ return Promise.all([