mirror of
https://github.com/documenso/documenso.git
synced 2026-08-24 23:32:29 +10:00
feat: rejected and expired recipient filters (#2889)
This commit is contained in:
@@ -8,6 +8,7 @@ import { DateTime } from 'luxon';
|
||||
|
||||
import { STATS_COUNT_CAP } from '../../constants/document';
|
||||
import { TEAM_DOCUMENT_VISIBILITY_MAP } from '../../constants/teams';
|
||||
import { hasExpiredRecipient } from '../envelope/query-helpers';
|
||||
import { getTeamById } from '../team/get-team';
|
||||
|
||||
// Kysely query builder type for Envelope queries.
|
||||
@@ -253,6 +254,19 @@ export const getStats = async ({ userId, teamId, period, search = '', folderId,
|
||||
return eb.and([teamDeletedFilter(eb), visibilityFilter(eb), eb.or(accessBranches)]);
|
||||
});
|
||||
|
||||
// EXPIRED: docs visible to the team/user with at least one expired, unsigned recipient.
|
||||
// Access control mirrors the EXPIRED branch in findDocuments so the count matches the listing.
|
||||
const expiredQuery = buildBaseQuery().where((eb) => {
|
||||
const accessBranches = [eb('Envelope.teamId', '=', team.id)];
|
||||
|
||||
if (teamEmail) {
|
||||
accessBranches.push(senderEmailIs(eb, teamEmail));
|
||||
accessBranches.push(recipientExists(eb, teamEmail));
|
||||
}
|
||||
|
||||
return eb.and([teamDeletedFilter(eb), visibilityFilter(eb), hasExpiredRecipient(eb), eb.or(accessBranches)]);
|
||||
});
|
||||
|
||||
// INBOX: non-draft docs where team email is a NOT_SIGNED, non-CC recipient
|
||||
// Returns 0 if the team has no team email.
|
||||
const inboxQuery = teamEmail
|
||||
@@ -274,15 +288,17 @@ export const getStats = async ({ userId, teamId, period, search = '', folderId,
|
||||
|
||||
// ─── Execute all counts in parallel ──────────────────────────────────
|
||||
|
||||
const [draft, pending, completed, rejected, cancelled, inbox] = await Promise.all([
|
||||
const [draft, pending, completed, rejected, cancelled, expired, inbox] = await Promise.all([
|
||||
cappedCount(draftQuery),
|
||||
cappedCount(pendingQuery),
|
||||
cappedCount(completedQuery),
|
||||
cappedCount(rejectedQuery),
|
||||
cappedCount(cancelledQuery),
|
||||
cappedCount(expiredQuery),
|
||||
inboxQuery ? cappedCount(inboxQuery) : Promise.resolve(0),
|
||||
]);
|
||||
|
||||
// `expired` is intentionally excluded from `all` — it overlaps PENDING.
|
||||
const all = Math.min(draft + pending + completed + rejected + cancelled + inbox, STATS_COUNT_CAP);
|
||||
|
||||
const stats: Record<ExtendedDocumentStatus, number> = {
|
||||
@@ -291,6 +307,7 @@ export const getStats = async ({ userId, teamId, period, search = '', folderId,
|
||||
[ExtendedDocumentStatus.COMPLETED]: completed,
|
||||
[ExtendedDocumentStatus.REJECTED]: rejected,
|
||||
[ExtendedDocumentStatus.CANCELLED]: cancelled,
|
||||
[ExtendedDocumentStatus.EXPIRED]: expired,
|
||||
[ExtendedDocumentStatus.INBOX]: inbox,
|
||||
[ExtendedDocumentStatus.ALL]: all,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user