feat(documents): entity-aggregated query params + signing-details API

GET /api/v1/files?entityType=client&entityId=… and the same params on
the documents route return the owner-aggregated projection
{ groups: [{ label, source, files|workflows, total }] }. folderId
remains for direct-folder listing; the two modes are mutually
exclusive (zod refine).

GET /api/v1/documents/[id]/signing-details returns
{ workflow, signers, events } for the "view signing details" dialog
on signed-PDF rows.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-11 12:06:49 +02:00
parent d2b0d42e84
commit dec54806cb
6 changed files with 357 additions and 29 deletions

View File

@@ -18,14 +18,24 @@ export const updateFileSchema = z.object({
category: z.string().optional(),
});
export const listFilesSchema = baseListQuerySchema.extend({
clientId: z.string().optional(),
yachtId: z.string().optional(),
companyId: z.string().optional(),
category: z.string().optional(),
entityType: z.string().optional(),
entityId: z.string().optional(),
});
export const listFilesSchema = baseListQuerySchema
.extend({
clientId: z.string().optional(),
yachtId: z.string().optional(),
companyId: z.string().optional(),
category: z.string().optional(),
folderId: z.string().uuid().optional(),
/** Entity-aggregated projection params — mutually exclusive with folderId. */
entityType: z.enum(['client', 'company', 'yacht']).optional(),
entityId: z.string().uuid().optional(),
})
.refine(
(q) => !(q.folderId !== undefined && (q.entityType !== undefined || q.entityId !== undefined)),
{ message: 'folderId is mutually exclusive with entityType/entityId' },
)
.refine((q) => Boolean(q.entityType) === Boolean(q.entityId), {
message: 'entityType and entityId must be provided together',
});
export type UploadFileInput = z.infer<typeof uploadFileSchema>;
export type UpdateFileInput = z.infer<typeof updateFileSchema>;