@muni-sanfer/types-gestor-documental 0.0.1-beta.14 → 0.0.1-beta.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,7 +33,7 @@ export declare const DocumentParticipantStatus: {
33
33
  Resolved: "Resolved";
34
34
  Rejected: "Rejected";
35
35
  };
36
- export type DocumentTrackingAction = 'Created' | 'Updated' | 'Submitted' | 'Visaed' | 'Signed' | 'Rejected' | 'Finished' | 'Discarded' | 'Numbered' | 'NumberAnnulled' | 'Annulled' | 'Delivered' | 'Derived' | 'Reassigned' | 'Dispatched' | 'DispatchReturned' | 'Received';
36
+ export type DocumentTrackingAction = 'Created' | 'Updated' | 'Submitted' | 'Visaed' | 'Signed' | 'Rejected' | 'Finished' | 'Discarded' | 'Numbered' | 'NumberAnnulled' | 'Annulled' | 'Delivered' | 'Derived' | 'Reassigned' | 'Dispatched' | 'DispatchReturned' | 'Received' | 'EmailCopySent' | 'EmailCopyOpened';
37
37
  export declare const DocumentTrackingAction: {
38
38
  Created: "Created";
39
39
  Updated: "Updated";
@@ -52,6 +52,8 @@ export declare const DocumentTrackingAction: {
52
52
  Dispatched: "Dispatched";
53
53
  DispatchReturned: "DispatchReturned";
54
54
  Received: "Received";
55
+ EmailCopySent: "EmailCopySent";
56
+ EmailCopyOpened: "EmailCopyOpened";
55
57
  };
56
58
  export type DocumentOrigin = 'Internal' | 'DocDigital';
57
59
  export declare const DocumentOrigin: {
@@ -144,7 +146,7 @@ export declare const CaseFileActorType: {
144
146
  PrivateInstitution: "PrivateInstitution";
145
147
  Official: "Official";
146
148
  };
147
- export type CaseFileTrackingAction = 'Created' | 'Updated' | 'EntryAdded' | 'EntryVoided' | 'EntryMoved' | 'ParticipantAdded' | 'ParticipantRemoved' | 'Closed' | 'Exported';
149
+ export type CaseFileTrackingAction = 'Created' | 'Updated' | 'EntryAdded' | 'EntryVoided' | 'EntryMoved' | 'ParticipantAdded' | 'ParticipantRemoved' | 'Closed' | 'Exported' | 'ShareLinkCreated' | 'ShareLinkRevoked';
148
150
  export declare const CaseFileTrackingAction: {
149
151
  Created: "Created";
150
152
  Updated: "Updated";
@@ -155,6 +157,8 @@ export declare const CaseFileTrackingAction: {
155
157
  ParticipantRemoved: "ParticipantRemoved";
156
158
  Closed: "Closed";
157
159
  Exported: "Exported";
160
+ ShareLinkCreated: "ShareLinkCreated";
161
+ ShareLinkRevoked: "ShareLinkRevoked";
158
162
  };
159
163
  export type CaseFileAccessAction = 'Viewed' | 'FileDownloaded' | 'Exported';
160
164
  export declare const CaseFileAccessAction: {
@@ -242,6 +246,7 @@ export interface DocumentEntity {
242
246
  caseFileEntries?: CaseFileEntryEntity[];
243
247
  workFolderItems?: WorkFolderItemEntity[];
244
248
  externalRecipients?: DocumentExternalRecipientEntity[];
249
+ emailCopies?: DocumentEmailCopyEntity[];
245
250
  dispatch?: DocumentDispatchEntity | null;
246
251
  docDigitalInbound?: DocDigitalInboundEntity | null;
247
252
  deleted: boolean;
@@ -403,6 +408,7 @@ export interface CaseFileEntity {
403
408
  trackings?: CaseFileTrackingEntity[];
404
409
  metadataChanges?: CaseFileMetadataChangeEntity[];
405
410
  accesses?: CaseFileAccessEntity[];
411
+ shareLinks?: CaseFileShareLinkEntity[];
406
412
  createdAt: string;
407
413
  updatedAt: string;
408
414
  workFolder?: WorkFolderEntity | null;
@@ -488,10 +494,43 @@ export interface CaseFileAccessEntity {
488
494
  id: string;
489
495
  action: CaseFileAccessAction;
490
496
  entryId?: string | null;
491
- employeeId: string;
497
+ employeeId?: string | null;
492
498
  employeeFullName: string;
499
+ shareLink?: CaseFileShareLinkEntity | null;
500
+ shareLinkId?: string | null;
501
+ caseFile?: CaseFileEntity;
502
+ caseFileId: string;
503
+ createdAt: string;
504
+ }
505
+ export interface CaseFileShareLinkEntity {
506
+ id: string;
507
+ tokenHash: string;
508
+ recipient: string;
509
+ recipientEmail?: string | null;
510
+ purpose?: string | null;
511
+ allowExport: boolean;
512
+ expiresAt: string;
513
+ createdByEmployeeId: string;
514
+ createdByFullName: string;
515
+ revokedAt?: string | null;
516
+ revokedByEmployeeId?: string | null;
517
+ revokedByFullName?: string | null;
493
518
  caseFile?: CaseFileEntity;
494
519
  caseFileId: string;
520
+ accesses?: CaseFileAccessEntity[];
521
+ createdAt: string;
522
+ }
523
+ export interface DocumentEmailCopyEntity {
524
+ id: string;
525
+ name: string;
526
+ email: string;
527
+ tokenHash?: string | null;
528
+ expiresAt?: string | null;
529
+ issuedAt?: string | null;
530
+ openedAt?: string | null;
531
+ downloadCount: number;
532
+ document?: DocumentEntity;
533
+ documentId: string;
495
534
  createdAt: string;
496
535
  }
497
536
  export interface DocumentExternalRecipientEntity {
@@ -50,6 +50,8 @@ exports.DocumentTrackingAction = {
50
50
  Dispatched: 'Dispatched',
51
51
  DispatchReturned: 'DispatchReturned',
52
52
  Received: 'Received',
53
+ EmailCopySent: 'EmailCopySent',
54
+ EmailCopyOpened: 'EmailCopyOpened',
53
55
  };
54
56
  exports.DocumentOrigin = {
55
57
  Internal: 'Internal',
@@ -138,6 +140,8 @@ exports.CaseFileTrackingAction = {
138
140
  ParticipantRemoved: 'ParticipantRemoved',
139
141
  Closed: 'Closed',
140
142
  Exported: 'Exported',
143
+ ShareLinkCreated: 'ShareLinkCreated',
144
+ ShareLinkRevoked: 'ShareLinkRevoked',
141
145
  };
142
146
  exports.CaseFileAccessAction = {
143
147
  Viewed: 'Viewed',
@@ -1,5 +1,5 @@
1
1
  import { type CaseFileActorRelation, type CaseFileActorType, type CaseFileActuationType, type CaseFileEntity, type CaseFileStatus, type DocumentAccessLevel } from '../base/entities';
2
- import { type CaseFileAddBatchResponseEntity, type CaseFileAddEntryResponseEntity, type CaseFileCreateResponseEntity, type CaseFileEntryFileResponseEntity, type CaseFileExportResponseEntity, type CaseFileGetAllResponseEntity, type CaseFileGetByIdResponseEntity, type CaseFileUpdateResponseEntity } from '../entities';
2
+ import { type CaseFileAddBatchResponseEntity, type CaseFileAddEntryResponseEntity, type CaseFileCreateResponseEntity, type CaseFileEntryFileResponseEntity, type CaseFileExportResponseEntity, type CaseFileGetAllResponseEntity, type CaseFileGetByIdResponseEntity, type CaseFileShareLinkCreateResponseEntity, type CaseFileShareLinkResponseEntity, type CaseFileSharedResponseEntity, type CaseFileUpdateResponseEntity } from '../entities';
3
3
  import { type RpcPage } from './contract';
4
4
  import { type DocumentActor } from './document.contract';
5
5
  /** Patrones NATS de `caseFile`: `<servicio>.<recurso>.<acción>`. */
@@ -17,7 +17,25 @@ export declare const CaseFilePatterns: {
17
17
  readonly close: "gestorDocumental.caseFile.close";
18
18
  readonly getEntryFile: "gestorDocumental.caseFile.getEntryFile";
19
19
  readonly getExport: "gestorDocumental.caseFile.getExport";
20
+ readonly createShareLink: "gestorDocumental.caseFile.createShareLink";
21
+ readonly getShareLinks: "gestorDocumental.caseFile.getShareLinks";
22
+ readonly revokeShareLink: "gestorDocumental.caseFile.revokeShareLink";
23
+ readonly getShared: "gestorDocumental.caseFile.getShared";
24
+ readonly getSharedEntryFile: "gestorDocumental.caseFile.getSharedEntryFile";
25
+ readonly getSharedExport: "gestorDocumental.caseFile.getSharedExport";
20
26
  };
27
+ /** Enlace temporal para que alguien de fuera consulte el expediente sin sesión. */
28
+ export interface CaseFileShareLinkPayload {
29
+ /** A quién se entrega. Ej: «Contraloría Regional». */
30
+ recipient: string;
31
+ /** Si se indica, el gateway le envía el enlace por correo. */
32
+ recipientEmail?: string | null;
33
+ purpose?: string | null;
34
+ /** Cuántos días dura: de 1 a 30. */
35
+ days: number;
36
+ /** Puede descargar el expediente completo (ZIP). Por omisión, sí. */
37
+ allowExport?: boolean;
38
+ }
21
39
  /** Persona u organización relacionada con el expediente (MGDEE54). */
22
40
  export interface CaseFileActorInput {
23
41
  relation: CaseFileActorRelation;
@@ -181,5 +199,45 @@ export interface CaseFileContract {
181
199
  payload: Pick<CaseFileEntity, 'id'> & CaseFileActorPayload;
182
200
  response: CaseFileExportResponseEntity;
183
201
  };
202
+ /** Crea un enlace temporal: solo su responsable. El token viaja solo en esta respuesta. */
203
+ [CaseFilePatterns.createShareLink]: {
204
+ payload: Pick<CaseFileEntity, 'id'> & CaseFileShareLinkPayload & {
205
+ actor: DocumentActor;
206
+ };
207
+ response: CaseFileShareLinkCreateResponseEntity;
208
+ };
209
+ /** Enlaces del expediente, vigentes o no, con cuántas veces se usaron: su responsable o quien ve todos. */
210
+ [CaseFilePatterns.getShareLinks]: {
211
+ payload: Pick<CaseFileEntity, 'id'> & CaseFileActorPayload;
212
+ response: CaseFileShareLinkResponseEntity[];
213
+ };
214
+ [CaseFilePatterns.revokeShareLink]: {
215
+ payload: Pick<CaseFileEntity, 'id'> & {
216
+ linkId: string;
217
+ actor: DocumentActor;
218
+ };
219
+ response: CaseFileUpdateResponseEntity;
220
+ };
221
+ /** Sin sesión, con el token del enlace: metadatos e índice. Queda en el registro de accesos. */
222
+ [CaseFilePatterns.getShared]: {
223
+ payload: {
224
+ token: string;
225
+ };
226
+ response: CaseFileSharedResponseEntity;
227
+ };
228
+ [CaseFilePatterns.getSharedEntryFile]: {
229
+ payload: {
230
+ token: string;
231
+ entryId: string;
232
+ };
233
+ response: CaseFileEntryFileResponseEntity;
234
+ };
235
+ /** El expediente completo, si el enlace lo permite. Queda en la trazabilidad y en el registro de accesos. */
236
+ [CaseFilePatterns.getSharedExport]: {
237
+ payload: {
238
+ token: string;
239
+ };
240
+ response: CaseFileExportResponseEntity;
241
+ };
184
242
  }
185
243
  export {};
@@ -16,4 +16,10 @@ exports.CaseFilePatterns = {
16
16
  close: 'gestorDocumental.caseFile.close',
17
17
  getEntryFile: 'gestorDocumental.caseFile.getEntryFile',
18
18
  getExport: 'gestorDocumental.caseFile.getExport',
19
+ createShareLink: 'gestorDocumental.caseFile.createShareLink',
20
+ getShareLinks: 'gestorDocumental.caseFile.getShareLinks',
21
+ revokeShareLink: 'gestorDocumental.caseFile.revokeShareLink',
22
+ getShared: 'gestorDocumental.caseFile.getShared',
23
+ getSharedEntryFile: 'gestorDocumental.caseFile.getSharedEntryFile',
24
+ getSharedExport: 'gestorDocumental.caseFile.getSharedExport',
19
25
  };
@@ -1,5 +1,5 @@
1
1
  import { type DocumentAccessLevel, type DocumentAttachmentEntity, type DocumentDeliveryEntity, type DocumentEntity, type DocumentInstruction, type DocumentParticipantEntity, type DocumentStatus } from '../base/entities';
2
- import { type DocumentAnnulResponseEntity, type DocumentCloseDeliveryResponseEntity, type DocumentCreateResponseEntity, type DocumentDeriveResponseEntity, type DocumentDiscardResponseEntity, type DocumentGetAllResponseEntity, type DocumentGetByIdResponseEntity, type DocumentGetSummaryResponseEntity, type DocumentInboxItemEntity, type DocumentPublicFileResponseEntity, type DocumentReassignResponseEntity, type DocumentReviewResponseEntity, type DocumentSignManyResponseEntity, type DocumentAgendaResponseEntity, type DocumentComposeResponseEntity, type DocumentComposition, type DocumentTrailExportEntity, type DocumentUpdateResponseEntity, type DocumentVerifyResponseEntity } from '../entities';
2
+ import { type DocumentAnnulResponseEntity, type DocumentCloseDeliveryResponseEntity, type DocumentCreateResponseEntity, type DocumentDeriveResponseEntity, type DocumentDiscardResponseEntity, type DocumentEmailCopyIssuedEntity, type DocumentEmailCopyViewEntity, type DocumentGetAllResponseEntity, type DocumentGetByIdResponseEntity, type DocumentGetSummaryResponseEntity, type DocumentInboxItemEntity, type DocumentPublicFileResponseEntity, type DocumentReassignResponseEntity, type DocumentReviewResponseEntity, type DocumentSignManyResponseEntity, type DocumentAgendaResponseEntity, type DocumentComposeResponseEntity, type DocumentComposition, type DocumentTrailExportEntity, type DocumentUpdateResponseEntity, type DocumentVerifyResponseEntity } from '../entities';
3
3
  import { type RpcPage } from './contract';
4
4
  /** Patrones NATS de `document`: `<servicio>.<recurso>.<acción>`. */
5
5
  export declare const DocumentPatterns: {
@@ -22,6 +22,9 @@ export declare const DocumentPatterns: {
22
22
  readonly getAgenda: "gestorDocumental.document.getAgenda";
23
23
  readonly exportTrail: "gestorDocumental.document.exportTrail";
24
24
  readonly compose: "gestorDocumental.document.compose";
25
+ readonly issueEmailCopies: "gestorDocumental.document.issueEmailCopies";
26
+ readonly getEmailCopy: "gestorDocumental.document.getEmailCopy";
27
+ readonly getEmailCopyFile: "gestorDocumental.document.getEmailCopyFile";
25
28
  };
26
29
  /**
27
30
  * Funcionario que hace la operación y sus áreas (direcciones y departamentos a los que pertenece o que dirige). Lo
@@ -81,9 +84,15 @@ export interface DocumentWritePayload extends Pick<DocumentEntity, 'subject' | '
81
84
  responseDueAt?: string | null;
82
85
  replyToDocumentId?: string | null;
83
86
  externalRecipients?: DocumentExternalRecipientInput[];
87
+ emailCopies?: DocumentEmailCopyInput[];
84
88
  action?: 'Submit';
85
89
  actor: DocumentActor;
86
90
  }
91
+ /** Persona u organización fuera del Estado que recibe una copia por correo. */
92
+ export interface DocumentEmailCopyInput {
93
+ name: string;
94
+ email: string;
95
+ }
87
96
  /** Destinatario externo: una institución de DocDigital y, si se indica, uno de sus usuarios. */
88
97
  export interface DocumentExternalRecipientInput {
89
98
  entityId: number;
@@ -295,6 +304,29 @@ export interface DocumentContract {
295
304
  };
296
305
  response: DocumentPublicFileResponseEntity;
297
306
  };
307
+ /**
308
+ * Emite las copias por correo pendientes de estos documentos, si ya corresponde (finalizado y, si va por DocDigital,
309
+ * despachado): genera el enlace de cada una. Se puede pedir de más: lo ya emitido no se repite.
310
+ */
311
+ [DocumentPatterns.issueEmailCopies]: {
312
+ payload: {
313
+ documentIds: string[];
314
+ };
315
+ response: DocumentEmailCopyIssuedEntity[];
316
+ };
317
+ /** Sin sesión, con el token de la copia: el documento y quién lo emitió. */
318
+ [DocumentPatterns.getEmailCopy]: {
319
+ payload: {
320
+ token: string;
321
+ };
322
+ response: DocumentEmailCopyViewEntity;
323
+ };
324
+ [DocumentPatterns.getEmailCopyFile]: {
325
+ payload: {
326
+ token: string;
327
+ };
328
+ response: DocumentPublicFileResponseEntity;
329
+ };
298
330
  /** Carpeta de Drive de los documentos y sus anexos: el gateway la pide antes de subir cada archivo. */
299
331
  [DocumentPatterns.getFilesFolder]: {
300
332
  payload: Record<string, never>;
@@ -22,4 +22,7 @@ exports.DocumentPatterns = {
22
22
  getAgenda: 'gestorDocumental.document.getAgenda',
23
23
  exportTrail: 'gestorDocumental.document.exportTrail',
24
24
  compose: 'gestorDocumental.document.compose',
25
+ issueEmailCopies: 'gestorDocumental.document.issueEmailCopies',
26
+ getEmailCopy: 'gestorDocumental.document.getEmailCopy',
27
+ getEmailCopyFile: 'gestorDocumental.document.getEmailCopyFile',
25
28
  };
@@ -46,6 +46,9 @@ export declare const GestorDocumentalPatterns: {
46
46
  readonly getAgenda: "gestorDocumental.document.getAgenda";
47
47
  readonly exportTrail: "gestorDocumental.document.exportTrail";
48
48
  readonly compose: "gestorDocumental.document.compose";
49
+ readonly issueEmailCopies: "gestorDocumental.document.issueEmailCopies";
50
+ readonly getEmailCopy: "gestorDocumental.document.getEmailCopy";
51
+ readonly getEmailCopyFile: "gestorDocumental.document.getEmailCopyFile";
49
52
  };
50
53
  readonly procedure: {
51
54
  readonly getAll: "gestorDocumental.procedure.getAll";
@@ -75,6 +78,12 @@ export declare const GestorDocumentalPatterns: {
75
78
  readonly close: "gestorDocumental.caseFile.close";
76
79
  readonly getEntryFile: "gestorDocumental.caseFile.getEntryFile";
77
80
  readonly getExport: "gestorDocumental.caseFile.getExport";
81
+ readonly createShareLink: "gestorDocumental.caseFile.createShareLink";
82
+ readonly getShareLinks: "gestorDocumental.caseFile.getShareLinks";
83
+ readonly revokeShareLink: "gestorDocumental.caseFile.revokeShareLink";
84
+ readonly getShared: "gestorDocumental.caseFile.getShared";
85
+ readonly getSharedEntryFile: "gestorDocumental.caseFile.getSharedEntryFile";
86
+ readonly getSharedExport: "gestorDocumental.caseFile.getSharedExport";
78
87
  };
79
88
  readonly partsOffice: {
80
89
  readonly getStatus: "gestorDocumental.partsOffice.getStatus";
@@ -102,7 +102,10 @@ export interface CaseFileAccessResponseEntity {
102
102
  entryId: CaseFileAccessEntity['entryId'];
103
103
  /** Título del documento que se abrió, si el acceso fue a uno. */
104
104
  entryTitle: string | null;
105
+ /** El funcionario o, si fue por un enlace temporal, su destinatario externo. */
105
106
  employeeFullName: CaseFileAccessEntity['employeeFullName'];
107
+ /** Fue por un enlace temporal, sin sesión. */
108
+ external: boolean;
106
109
  createdAt: CaseFileAccessEntity['createdAt'];
107
110
  }
108
111
  export interface CaseFileGetByIdResponseEntity extends CaseFileGetAllResponseEntity {
@@ -182,3 +185,77 @@ export interface CaseFileExportResponseEntity {
182
185
  }
183
186
  /** Expediente en que está incorporado un documento, visto desde el documento. */
184
187
  export type DocumentCaseFileEntity = CaseFileLinkEntity;
188
+ /** Estado de un enlace temporal: vigente, vencido o revocado. */
189
+ export type CaseFileShareLinkStatus = 'Active' | 'Expired' | 'Revoked';
190
+ /** Enlace temporal de un expediente, como lo ve su responsable. El token no se vuelve a mostrar. */
191
+ export interface CaseFileShareLinkResponseEntity {
192
+ id: string;
193
+ recipient: string;
194
+ recipientEmail: string | null;
195
+ purpose: string | null;
196
+ allowExport: boolean;
197
+ expiresAt: string;
198
+ status: CaseFileShareLinkStatus;
199
+ createdByFullName: string;
200
+ createdAt: string;
201
+ revokedAt: string | null;
202
+ revokedByFullName: string | null;
203
+ /** Cuántas consultas, descargas y exportaciones se hicieron con él. */
204
+ accessCount: number;
205
+ lastAccessAt: string | null;
206
+ }
207
+ /** Enlace recién creado: el token va solo aquí; la dirección la arma quien lo muestra. */
208
+ export interface CaseFileShareLinkCreateResponseEntity {
209
+ id: string;
210
+ token: string;
211
+ recipient: string;
212
+ recipientEmail: string | null;
213
+ purpose: string | null;
214
+ expiresAt: string;
215
+ /** Para avisarle al destinatario: qué expediente, de qué órgano y quién se lo comparte. */
216
+ caseFile: {
217
+ code: string;
218
+ title: string;
219
+ };
220
+ organName: string;
221
+ createdByFullName: string;
222
+ }
223
+ /** Actuación del índice como la ve el destinatario externo. */
224
+ export interface CaseFileSharedEntryEntity {
225
+ id: string;
226
+ sequence: number;
227
+ folder: string | null;
228
+ kind: CaseFileEntryEntity['kind'];
229
+ actuationType: CaseFileEntryEntity['actuationType'];
230
+ title: string;
231
+ /** Tipo y número del documento («D.E. N° 590/2026») o el tipo declarado del archivo. */
232
+ reference: string | null;
233
+ originDate: string | null;
234
+ createdAt: string;
235
+ hasFile: boolean;
236
+ sha256: string | null;
237
+ hasAdvancedSignature: boolean;
238
+ physicalLocation: string | null;
239
+ pageCount: number | null;
240
+ voidedAt: string | null;
241
+ voidReason: string | null;
242
+ }
243
+ /** Expediente abierto con un enlace temporal: metadatos e índice, sin participantes ni registros internos. */
244
+ export interface CaseFileSharedResponseEntity {
245
+ code: string;
246
+ title: string;
247
+ subject: string;
248
+ summary: string | null;
249
+ procedureName: string;
250
+ status: CaseFileEntity['status'];
251
+ organName: string;
252
+ responsibleFullName: string;
253
+ responsiblePosition: string | null;
254
+ createdAt: string;
255
+ closedAt: string | null;
256
+ recipient: string;
257
+ purpose: string | null;
258
+ expiresAt: string;
259
+ allowExport: boolean;
260
+ entries: CaseFileSharedEntryEntity[];
261
+ }
@@ -174,6 +174,7 @@ export interface DocumentGetByIdResponseEntity {
174
174
  /** Instituciones de DocDigital a quienes va dirigido, y su despacho por Oficina de Partes. */
175
175
  externalRecipients: DocumentExternalRecipientResponseEntity[];
176
176
  dispatch: DocumentDispatchResponseEntity | null;
177
+ emailCopies: DocumentEmailCopyResponseEntity[];
177
178
  documentType: DocumentTypeSummaryEntity;
178
179
  participants: DocumentParticipantResponseEntity[];
179
180
  attachments: {
@@ -403,3 +404,43 @@ export interface DocumentComposeResponseEntity {
403
404
  fileId?: string;
404
405
  contentBase64?: string;
405
406
  }
407
+ /** Copia por correo de un documento, como la ve quien lo consulta en el gestor. */
408
+ export interface DocumentEmailCopyResponseEntity {
409
+ id: string;
410
+ name: string;
411
+ email: string;
412
+ /** Cuándo se envió (sin valor: aún no corresponde). */
413
+ issuedAt: string | null;
414
+ expiresAt: string | null;
415
+ openedAt: string | null;
416
+ downloadCount: number;
417
+ }
418
+ /** Copia recién emitida: el gateway le envía el enlace a su destinatario. El token viaja solo aquí. */
419
+ export interface DocumentEmailCopyIssuedEntity {
420
+ copyId: string;
421
+ documentId: string;
422
+ name: string;
423
+ email: string;
424
+ token: string;
425
+ expiresAt: string;
426
+ /** Cómo se cita: «D.E. N° 590/2026», o el tipo si no lleva número. */
427
+ folio: string;
428
+ subject: string;
429
+ issuerName: string;
430
+ }
431
+ /** El documento como lo ve quien abre su copia por correo. */
432
+ export interface DocumentEmailCopyViewEntity {
433
+ recipientName: string;
434
+ expiresAt: string;
435
+ documentTypeName: string;
436
+ folio: string;
437
+ subject: string;
438
+ issuerName: string;
439
+ finishedAt: string | null;
440
+ verificationCode: string | null;
441
+ signers: {
442
+ fullName: string;
443
+ position: string | null;
444
+ signedAt: string | null;
445
+ }[];
446
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@muni-sanfer/types-gestor-documental",
3
- "version": "0.0.1-beta.14",
3
+ "version": "0.0.1-beta.15",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {
@@ -63,7 +63,9 @@ export type DocumentTrackingAction =
63
63
  | 'Reassigned'
64
64
  | 'Dispatched'
65
65
  | 'DispatchReturned'
66
- | 'Received';
66
+ | 'Received'
67
+ | 'EmailCopySent'
68
+ | 'EmailCopyOpened';
67
69
 
68
70
  export const DocumentTrackingAction = {
69
71
  Created: 'Created',
@@ -83,6 +85,8 @@ export const DocumentTrackingAction = {
83
85
  Dispatched: 'Dispatched',
84
86
  DispatchReturned: 'DispatchReturned',
85
87
  Received: 'Received',
88
+ EmailCopySent: 'EmailCopySent',
89
+ EmailCopyOpened: 'EmailCopyOpened',
86
90
  } satisfies Record<string, DocumentTrackingAction>;
87
91
 
88
92
  export type DocumentOrigin = 'Internal' | 'DocDigital';
@@ -222,7 +226,9 @@ export type CaseFileTrackingAction =
222
226
  | 'ParticipantAdded'
223
227
  | 'ParticipantRemoved'
224
228
  | 'Closed'
225
- | 'Exported';
229
+ | 'Exported'
230
+ | 'ShareLinkCreated'
231
+ | 'ShareLinkRevoked';
226
232
 
227
233
  export const CaseFileTrackingAction = {
228
234
  Created: 'Created',
@@ -234,6 +240,8 @@ export const CaseFileTrackingAction = {
234
240
  ParticipantRemoved: 'ParticipantRemoved',
235
241
  Closed: 'Closed',
236
242
  Exported: 'Exported',
243
+ ShareLinkCreated: 'ShareLinkCreated',
244
+ ShareLinkRevoked: 'ShareLinkRevoked',
237
245
  } satisfies Record<string, CaseFileTrackingAction>;
238
246
 
239
247
  export type CaseFileAccessAction = 'Viewed' | 'FileDownloaded' | 'Exported';
@@ -327,6 +335,7 @@ export interface DocumentEntity {
327
335
  caseFileEntries?: CaseFileEntryEntity[];
328
336
  workFolderItems?: WorkFolderItemEntity[];
329
337
  externalRecipients?: DocumentExternalRecipientEntity[];
338
+ emailCopies?: DocumentEmailCopyEntity[];
330
339
  dispatch?: DocumentDispatchEntity | null;
331
340
  docDigitalInbound?: DocDigitalInboundEntity | null;
332
341
  deleted: boolean;
@@ -499,6 +508,7 @@ export interface CaseFileEntity {
499
508
  trackings?: CaseFileTrackingEntity[];
500
509
  metadataChanges?: CaseFileMetadataChangeEntity[];
501
510
  accesses?: CaseFileAccessEntity[];
511
+ shareLinks?: CaseFileShareLinkEntity[];
502
512
  createdAt: string;
503
513
  updatedAt: string;
504
514
  workFolder?: WorkFolderEntity | null;
@@ -590,10 +600,45 @@ export interface CaseFileAccessEntity {
590
600
  id: string;
591
601
  action: CaseFileAccessAction;
592
602
  entryId?: string | null;
593
- employeeId: string;
603
+ employeeId?: string | null;
594
604
  employeeFullName: string;
605
+ shareLink?: CaseFileShareLinkEntity | null;
606
+ shareLinkId?: string | null;
607
+ caseFile?: CaseFileEntity;
608
+ caseFileId: string;
609
+ createdAt: string;
610
+ }
611
+
612
+ export interface CaseFileShareLinkEntity {
613
+ id: string;
614
+ tokenHash: string;
615
+ recipient: string;
616
+ recipientEmail?: string | null;
617
+ purpose?: string | null;
618
+ allowExport: boolean;
619
+ expiresAt: string;
620
+ createdByEmployeeId: string;
621
+ createdByFullName: string;
622
+ revokedAt?: string | null;
623
+ revokedByEmployeeId?: string | null;
624
+ revokedByFullName?: string | null;
595
625
  caseFile?: CaseFileEntity;
596
626
  caseFileId: string;
627
+ accesses?: CaseFileAccessEntity[];
628
+ createdAt: string;
629
+ }
630
+
631
+ export interface DocumentEmailCopyEntity {
632
+ id: string;
633
+ name: string;
634
+ email: string;
635
+ tokenHash?: string | null;
636
+ expiresAt?: string | null;
637
+ issuedAt?: string | null;
638
+ openedAt?: string | null;
639
+ downloadCount: number;
640
+ document?: DocumentEntity;
641
+ documentId: string;
597
642
  createdAt: string;
598
643
  }
599
644
 
@@ -14,6 +14,9 @@ import {
14
14
  type CaseFileExportResponseEntity,
15
15
  type CaseFileGetAllResponseEntity,
16
16
  type CaseFileGetByIdResponseEntity,
17
+ type CaseFileShareLinkCreateResponseEntity,
18
+ type CaseFileShareLinkResponseEntity,
19
+ type CaseFileSharedResponseEntity,
17
20
  type CaseFileUpdateResponseEntity,
18
21
  } from '../entities';
19
22
  import { type RpcPage } from './contract';
@@ -34,8 +37,27 @@ export const CaseFilePatterns = {
34
37
  close: 'gestorDocumental.caseFile.close',
35
38
  getEntryFile: 'gestorDocumental.caseFile.getEntryFile',
36
39
  getExport: 'gestorDocumental.caseFile.getExport',
40
+ createShareLink: 'gestorDocumental.caseFile.createShareLink',
41
+ getShareLinks: 'gestorDocumental.caseFile.getShareLinks',
42
+ revokeShareLink: 'gestorDocumental.caseFile.revokeShareLink',
43
+ getShared: 'gestorDocumental.caseFile.getShared',
44
+ getSharedEntryFile: 'gestorDocumental.caseFile.getSharedEntryFile',
45
+ getSharedExport: 'gestorDocumental.caseFile.getSharedExport',
37
46
  } as const;
38
47
 
48
+ /** Enlace temporal para que alguien de fuera consulte el expediente sin sesión. */
49
+ export interface CaseFileShareLinkPayload {
50
+ /** A quién se entrega. Ej: «Contraloría Regional». */
51
+ recipient: string;
52
+ /** Si se indica, el gateway le envía el enlace por correo. */
53
+ recipientEmail?: string | null;
54
+ purpose?: string | null;
55
+ /** Cuántos días dura: de 1 a 30. */
56
+ days: number;
57
+ /** Puede descargar el expediente completo (ZIP). Por omisión, sí. */
58
+ allowExport?: boolean;
59
+ }
60
+
39
61
  /** Persona u organización relacionada con el expediente (MGDEE54). */
40
62
  export interface CaseFileActorInput {
41
63
  relation: CaseFileActorRelation;
@@ -161,4 +183,32 @@ export interface CaseFileContract {
161
183
  payload: Pick<CaseFileEntity, 'id'> & CaseFileActorPayload;
162
184
  response: CaseFileExportResponseEntity;
163
185
  };
186
+ /** Crea un enlace temporal: solo su responsable. El token viaja solo en esta respuesta. */
187
+ [CaseFilePatterns.createShareLink]: {
188
+ payload: Pick<CaseFileEntity, 'id'> & CaseFileShareLinkPayload & { actor: DocumentActor };
189
+ response: CaseFileShareLinkCreateResponseEntity;
190
+ };
191
+ /** Enlaces del expediente, vigentes o no, con cuántas veces se usaron: su responsable o quien ve todos. */
192
+ [CaseFilePatterns.getShareLinks]: {
193
+ payload: Pick<CaseFileEntity, 'id'> & CaseFileActorPayload;
194
+ response: CaseFileShareLinkResponseEntity[];
195
+ };
196
+ [CaseFilePatterns.revokeShareLink]: {
197
+ payload: Pick<CaseFileEntity, 'id'> & { linkId: string; actor: DocumentActor };
198
+ response: CaseFileUpdateResponseEntity;
199
+ };
200
+ /** Sin sesión, con el token del enlace: metadatos e índice. Queda en el registro de accesos. */
201
+ [CaseFilePatterns.getShared]: {
202
+ payload: { token: string };
203
+ response: CaseFileSharedResponseEntity;
204
+ };
205
+ [CaseFilePatterns.getSharedEntryFile]: {
206
+ payload: { token: string; entryId: string };
207
+ response: CaseFileEntryFileResponseEntity;
208
+ };
209
+ /** El expediente completo, si el enlace lo permite. Queda en la trazabilidad y en el registro de accesos. */
210
+ [CaseFilePatterns.getSharedExport]: {
211
+ payload: { token: string };
212
+ response: CaseFileExportResponseEntity;
213
+ };
164
214
  }
@@ -13,6 +13,8 @@ import {
13
13
  type DocumentCreateResponseEntity,
14
14
  type DocumentDeriveResponseEntity,
15
15
  type DocumentDiscardResponseEntity,
16
+ type DocumentEmailCopyIssuedEntity,
17
+ type DocumentEmailCopyViewEntity,
16
18
  type DocumentGetAllResponseEntity,
17
19
  type DocumentGetByIdResponseEntity,
18
20
  type DocumentGetSummaryResponseEntity,
@@ -51,6 +53,9 @@ export const DocumentPatterns = {
51
53
  getAgenda: 'gestorDocumental.document.getAgenda',
52
54
  exportTrail: 'gestorDocumental.document.exportTrail',
53
55
  compose: 'gestorDocumental.document.compose',
56
+ issueEmailCopies: 'gestorDocumental.document.issueEmailCopies',
57
+ getEmailCopy: 'gestorDocumental.document.getEmailCopy',
58
+ getEmailCopyFile: 'gestorDocumental.document.getEmailCopyFile',
54
59
  } as const;
55
60
 
56
61
  /**
@@ -119,10 +124,18 @@ export interface DocumentWritePayload extends Pick<DocumentEntity, 'subject' | '
119
124
  replyToDocumentId?: string | null;
120
125
  // Instituciones (y usuarios) de DocDigital a quienes va: al terminar la firma pasa a Oficina de Partes.
121
126
  externalRecipients?: DocumentExternalRecipientInput[];
127
+ // Copia por correo a quienes están fuera del Estado: sale al finalizar o, si también va por DocDigital, al despacharlo.
128
+ emailCopies?: DocumentEmailCopyInput[];
122
129
  action?: 'Submit';
123
130
  actor: DocumentActor;
124
131
  }
125
132
 
133
+ /** Persona u organización fuera del Estado que recibe una copia por correo. */
134
+ export interface DocumentEmailCopyInput {
135
+ name: string;
136
+ email: string;
137
+ }
138
+
126
139
  /** Destinatario externo: una institución de DocDigital y, si se indica, uno de sus usuarios. */
127
140
  export interface DocumentExternalRecipientInput {
128
141
  entityId: number;
@@ -303,6 +316,23 @@ export interface DocumentContract {
303
316
  payload: { code: string };
304
317
  response: DocumentPublicFileResponseEntity;
305
318
  };
319
+ /**
320
+ * Emite las copias por correo pendientes de estos documentos, si ya corresponde (finalizado y, si va por DocDigital,
321
+ * despachado): genera el enlace de cada una. Se puede pedir de más: lo ya emitido no se repite.
322
+ */
323
+ [DocumentPatterns.issueEmailCopies]: {
324
+ payload: { documentIds: string[] };
325
+ response: DocumentEmailCopyIssuedEntity[];
326
+ };
327
+ /** Sin sesión, con el token de la copia: el documento y quién lo emitió. */
328
+ [DocumentPatterns.getEmailCopy]: {
329
+ payload: { token: string };
330
+ response: DocumentEmailCopyViewEntity;
331
+ };
332
+ [DocumentPatterns.getEmailCopyFile]: {
333
+ payload: { token: string };
334
+ response: DocumentPublicFileResponseEntity;
335
+ };
306
336
  /** Carpeta de Drive de los documentos y sus anexos: el gateway la pide antes de subir cada archivo. */
307
337
  [DocumentPatterns.getFilesFolder]: {
308
338
  payload: Record<string, never>;
@@ -121,7 +121,10 @@ export interface CaseFileAccessResponseEntity {
121
121
  entryId: CaseFileAccessEntity['entryId'];
122
122
  /** Título del documento que se abrió, si el acceso fue a uno. */
123
123
  entryTitle: string | null;
124
+ /** El funcionario o, si fue por un enlace temporal, su destinatario externo. */
124
125
  employeeFullName: CaseFileAccessEntity['employeeFullName'];
126
+ /** Fue por un enlace temporal, sin sesión. */
127
+ external: boolean;
125
128
  createdAt: CaseFileAccessEntity['createdAt'];
126
129
  }
127
130
 
@@ -210,3 +213,79 @@ export interface CaseFileExportResponseEntity {
210
213
 
211
214
  /** Expediente en que está incorporado un documento, visto desde el documento. */
212
215
  export type DocumentCaseFileEntity = CaseFileLinkEntity;
216
+
217
+ /** Estado de un enlace temporal: vigente, vencido o revocado. */
218
+ export type CaseFileShareLinkStatus = 'Active' | 'Expired' | 'Revoked';
219
+
220
+ /** Enlace temporal de un expediente, como lo ve su responsable. El token no se vuelve a mostrar. */
221
+ export interface CaseFileShareLinkResponseEntity {
222
+ id: string;
223
+ recipient: string;
224
+ recipientEmail: string | null;
225
+ purpose: string | null;
226
+ allowExport: boolean;
227
+ expiresAt: string;
228
+ status: CaseFileShareLinkStatus;
229
+ createdByFullName: string;
230
+ createdAt: string;
231
+ revokedAt: string | null;
232
+ revokedByFullName: string | null;
233
+ /** Cuántas consultas, descargas y exportaciones se hicieron con él. */
234
+ accessCount: number;
235
+ lastAccessAt: string | null;
236
+ }
237
+
238
+ /** Enlace recién creado: el token va solo aquí; la dirección la arma quien lo muestra. */
239
+ export interface CaseFileShareLinkCreateResponseEntity {
240
+ id: string;
241
+ token: string;
242
+ recipient: string;
243
+ recipientEmail: string | null;
244
+ purpose: string | null;
245
+ expiresAt: string;
246
+ /** Para avisarle al destinatario: qué expediente, de qué órgano y quién se lo comparte. */
247
+ caseFile: { code: string; title: string };
248
+ organName: string;
249
+ createdByFullName: string;
250
+ }
251
+
252
+ /** Actuación del índice como la ve el destinatario externo. */
253
+ export interface CaseFileSharedEntryEntity {
254
+ id: string;
255
+ sequence: number;
256
+ folder: string | null;
257
+ kind: CaseFileEntryEntity['kind'];
258
+ actuationType: CaseFileEntryEntity['actuationType'];
259
+ title: string;
260
+ /** Tipo y número del documento («D.E. N° 590/2026») o el tipo declarado del archivo. */
261
+ reference: string | null;
262
+ originDate: string | null;
263
+ createdAt: string;
264
+ hasFile: boolean;
265
+ sha256: string | null;
266
+ hasAdvancedSignature: boolean;
267
+ physicalLocation: string | null;
268
+ pageCount: number | null;
269
+ voidedAt: string | null;
270
+ voidReason: string | null;
271
+ }
272
+
273
+ /** Expediente abierto con un enlace temporal: metadatos e índice, sin participantes ni registros internos. */
274
+ export interface CaseFileSharedResponseEntity {
275
+ code: string;
276
+ title: string;
277
+ subject: string;
278
+ summary: string | null;
279
+ procedureName: string;
280
+ status: CaseFileEntity['status'];
281
+ organName: string;
282
+ responsibleFullName: string;
283
+ responsiblePosition: string | null;
284
+ createdAt: string;
285
+ closedAt: string | null;
286
+ recipient: string;
287
+ purpose: string | null;
288
+ expiresAt: string;
289
+ allowExport: boolean;
290
+ entries: CaseFileSharedEntryEntity[];
291
+ }
@@ -199,6 +199,8 @@ export interface DocumentGetByIdResponseEntity {
199
199
  /** Instituciones de DocDigital a quienes va dirigido, y su despacho por Oficina de Partes. */
200
200
  externalRecipients: DocumentExternalRecipientResponseEntity[];
201
201
  dispatch: DocumentDispatchResponseEntity | null;
202
+ // Copias por correo a quienes están fuera del Estado, con su envío y apertura.
203
+ emailCopies: DocumentEmailCopyResponseEntity[];
202
204
  documentType: DocumentTypeSummaryEntity;
203
205
  participants: DocumentParticipantResponseEntity[];
204
206
  attachments: {
@@ -450,3 +452,42 @@ export interface DocumentComposeResponseEntity {
450
452
  fileId?: string;
451
453
  contentBase64?: string;
452
454
  }
455
+
456
+ /** Copia por correo de un documento, como la ve quien lo consulta en el gestor. */
457
+ export interface DocumentEmailCopyResponseEntity {
458
+ id: string;
459
+ name: string;
460
+ email: string;
461
+ /** Cuándo se envió (sin valor: aún no corresponde). */
462
+ issuedAt: string | null;
463
+ expiresAt: string | null;
464
+ openedAt: string | null;
465
+ downloadCount: number;
466
+ }
467
+
468
+ /** Copia recién emitida: el gateway le envía el enlace a su destinatario. El token viaja solo aquí. */
469
+ export interface DocumentEmailCopyIssuedEntity {
470
+ copyId: string;
471
+ documentId: string;
472
+ name: string;
473
+ email: string;
474
+ token: string;
475
+ expiresAt: string;
476
+ /** Cómo se cita: «D.E. N° 590/2026», o el tipo si no lleva número. */
477
+ folio: string;
478
+ subject: string;
479
+ issuerName: string;
480
+ }
481
+
482
+ /** El documento como lo ve quien abre su copia por correo. */
483
+ export interface DocumentEmailCopyViewEntity {
484
+ recipientName: string;
485
+ expiresAt: string;
486
+ documentTypeName: string;
487
+ folio: string;
488
+ subject: string;
489
+ issuerName: string;
490
+ finishedAt: string | null;
491
+ verificationCode: string | null;
492
+ signers: { fullName: string; position: string | null; signedAt: string | null }[];
493
+ }