evo360-types 1.3.610 → 1.3.614
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.
- package/dist/apps/evo-med/calendar/zod-schemas.js +13 -0
- package/dist/apps/evo-med/calendar/zod-schemas.ts +13 -0
- package/dist/types/evo-med/calendar/index.d.ts +32 -3
- package/dist/types/evo-med/calendar/index.js +23 -2
- package/dist/types/evo-med/calendar/index.ts +32 -3
- package/dist/types/nex-vendas/journey.d.ts +96 -0
- package/dist/types/nex-vendas/journey.ts +116 -0
- package/package.json +1 -1
|
@@ -105,6 +105,10 @@ exports.zMedCalendarNotificationConfigSchema = zod_1.z
|
|
|
105
105
|
// Os únicos limites que o zod IMPÕE são os que a decisão declarou: retenção
|
|
106
106
|
// 7..730 (D32) e duração 15..480 (plan §12). Os demais têm só teto de sanidade
|
|
107
107
|
// — recusar um valor que a spec não proibiu seria inventar regra de negócio.
|
|
108
|
+
//
|
|
109
|
+
// O teto de 480 da duração NÃO acompanhou o teto de plataforma de 1h30 de
|
|
110
|
+
// 2026-09-25, e a razão está no comentário do campo: escrita permissiva,
|
|
111
|
+
// leitura clampada.
|
|
108
112
|
exports.zMedCalendarVirtualCareRecordingSchema = zod_1.z
|
|
109
113
|
.object({
|
|
110
114
|
mode: zod_1.z
|
|
@@ -137,6 +141,15 @@ exports.zMedCalendarVirtualCareConfigSchema = zod_1.z
|
|
|
137
141
|
.nullable()
|
|
138
142
|
.optional(),
|
|
139
143
|
allow_late_end: zod_1.z.boolean().nullable().optional(),
|
|
144
|
+
// `.max(480)` e NÃO 90 (o teto de plataforma de 1h30, 2026-09-25). Este é
|
|
145
|
+
// limite de ESCRITA, e baixá-lo quebraria o save de agenda já gravada:
|
|
146
|
+
// `CalendarModel.setProperties` relê o doc com `parseDoc` e valida o MERGE
|
|
147
|
+
// de doc + input com este schema, então uma agenda com 120 (o default
|
|
148
|
+
// publicado) ou 480 passaria a recusar o save de QUALQUER campo — o nome da
|
|
149
|
+
// agenda, a cor, o horário — por causa de um campo de telemedicina que o
|
|
150
|
+
// usuário nem abriu. Quem aplica o teto é a LEITURA
|
|
151
|
+
// (`VIRTUAL_CARE_PLATFORM_MAX_DURATION_MINUTES` em `packages/model`), que
|
|
152
|
+
// clampa e registra; a tela usa `VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX`.
|
|
140
153
|
max_duration_minutes: zod_1.z.number().int().min(15).max(480).nullable().optional(),
|
|
141
154
|
end_warning_minutes: zod_1.z.number().int().min(0).max(1440).nullable().optional(),
|
|
142
155
|
// feat-160 R6 (D38): provider sugerido ao agendar telemedicina nesta agenda.
|
|
@@ -109,6 +109,10 @@ export const zMedCalendarNotificationConfigSchema = z
|
|
|
109
109
|
// Os únicos limites que o zod IMPÕE são os que a decisão declarou: retenção
|
|
110
110
|
// 7..730 (D32) e duração 15..480 (plan §12). Os demais têm só teto de sanidade
|
|
111
111
|
// — recusar um valor que a spec não proibiu seria inventar regra de negócio.
|
|
112
|
+
//
|
|
113
|
+
// O teto de 480 da duração NÃO acompanhou o teto de plataforma de 1h30 de
|
|
114
|
+
// 2026-09-25, e a razão está no comentário do campo: escrita permissiva,
|
|
115
|
+
// leitura clampada.
|
|
112
116
|
export const zMedCalendarVirtualCareRecordingSchema = z
|
|
113
117
|
.object({
|
|
114
118
|
mode: z
|
|
@@ -144,6 +148,15 @@ export const zMedCalendarVirtualCareConfigSchema = z
|
|
|
144
148
|
.nullable()
|
|
145
149
|
.optional(),
|
|
146
150
|
allow_late_end: z.boolean().nullable().optional(),
|
|
151
|
+
// `.max(480)` e NÃO 90 (o teto de plataforma de 1h30, 2026-09-25). Este é
|
|
152
|
+
// limite de ESCRITA, e baixá-lo quebraria o save de agenda já gravada:
|
|
153
|
+
// `CalendarModel.setProperties` relê o doc com `parseDoc` e valida o MERGE
|
|
154
|
+
// de doc + input com este schema, então uma agenda com 120 (o default
|
|
155
|
+
// publicado) ou 480 passaria a recusar o save de QUALQUER campo — o nome da
|
|
156
|
+
// agenda, a cor, o horário — por causa de um campo de telemedicina que o
|
|
157
|
+
// usuário nem abriu. Quem aplica o teto é a LEITURA
|
|
158
|
+
// (`VIRTUAL_CARE_PLATFORM_MAX_DURATION_MINUTES` em `packages/model`), que
|
|
159
|
+
// clampa e registra; a tela usa `VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX`.
|
|
147
160
|
max_duration_minutes: z.number().int().min(15).max(480).nullable().optional(),
|
|
148
161
|
end_warning_minutes: z.number().int().min(0).max(1440).nullable().optional(),
|
|
149
162
|
// feat-160 R6 (D38): provider sugerido ao agendar telemedicina nesta agenda.
|
|
@@ -172,9 +172,30 @@ export type VirtualCareRecordingMode = (typeof VirtualCareRecordingModeEnum)[key
|
|
|
172
172
|
/** Limites de `recording.retention_days` (D32; D13 mantém 7 como default). */
|
|
173
173
|
export declare const VIRTUAL_CARE_RETENTION_DAYS_MIN = 7;
|
|
174
174
|
export declare const VIRTUAL_CARE_RETENTION_DAYS_MAX = 730;
|
|
175
|
-
/**
|
|
175
|
+
/**
|
|
176
|
+
* Limites de `max_duration_minutes`.
|
|
177
|
+
*
|
|
178
|
+
* O teto desceu de 480 (8 h) para **90 (1h30)** em 2026-09-25, por pedido do
|
|
179
|
+
* dono do produto: sem teto a consulta "fica em curso indefinidamente" e nós
|
|
180
|
+
* pagamos minuto de sala, minuto de gravação e depois o processamento da
|
|
181
|
+
* transcrição.
|
|
182
|
+
*
|
|
183
|
+
* Duas coisas que este par de constantes NÃO é:
|
|
184
|
+
*
|
|
185
|
+
* - **não é a autoridade.** Quem garante o teto é o backend
|
|
186
|
+
* (`VIRTUAL_CARE_PLATFORM_MAX_DURATION_MINUTES`, em
|
|
187
|
+
* `packages/model/src/evo-telemedicine/virtual-care-policy.ts`), que clampa
|
|
188
|
+
* na LEITURA da agenda. Tem de ser lá porque o que roda em produção é a
|
|
189
|
+
* versão PUBLICADA deste pacote — um teto que só exista aqui não existe em
|
|
190
|
+
* produção até o publish chegar ao deploy;
|
|
191
|
+
* - **não é limite de escrita.** O `.max()` do zod continua em 480 de
|
|
192
|
+
* propósito — ver o comentário em `zMedCalendarVirtualCareConfigSchema`.
|
|
193
|
+
*
|
|
194
|
+
* O uso legítimo daqui é a TELA: é este número que o editor da agenda usa como
|
|
195
|
+
* `max` do campo e para avisar que o valor gravado está fora da faixa.
|
|
196
|
+
*/
|
|
176
197
|
export declare const VIRTUAL_CARE_MAX_DURATION_MINUTES_MIN = 15;
|
|
177
|
-
export declare const VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX =
|
|
198
|
+
export declare const VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX = 90;
|
|
178
199
|
/** O que está GRAVADO no doc da agenda — tudo parcial (ausente = default). */
|
|
179
200
|
export interface IMedCalendarVirtualCareConfig {
|
|
180
201
|
/**
|
|
@@ -209,7 +230,15 @@ export interface IMedCalendarVirtualCareConfig {
|
|
|
209
230
|
} | null;
|
|
210
231
|
/** `true` = passar do fim previsto não encerra a consulta (comportamento atual). */
|
|
211
232
|
allow_late_end?: boolean | null;
|
|
212
|
-
/**
|
|
233
|
+
/**
|
|
234
|
+
* Teto absoluto; o sweep encerra ao exceder (`reason: max_duration`).
|
|
235
|
+
*
|
|
236
|
+
* Faixa da TELA: 15..90 (1h30, desde 2026-09-25). Doc gravado antes disso
|
|
237
|
+
* pode ter 120 (o default) ou 480, e continua salvável: o backend clampa na
|
|
238
|
+
* leitura e o zod não recusa. O default de
|
|
239
|
+
* `CALENDAR_VIRTUAL_CARE_DEFAULTS` segue 120 e também é clampado — o teto é
|
|
240
|
+
* da plataforma, não da agenda.
|
|
241
|
+
*/
|
|
213
242
|
max_duration_minutes?: number | null;
|
|
214
243
|
/** Aviso ao médico no SPA quando faltar N min para o fim. 0 = sem aviso. */
|
|
215
244
|
end_warning_minutes?: number | null;
|
|
@@ -94,9 +94,30 @@ exports.VirtualCareRecordingModeEnum = {
|
|
|
94
94
|
/** Limites de `recording.retention_days` (D32; D13 mantém 7 como default). */
|
|
95
95
|
exports.VIRTUAL_CARE_RETENTION_DAYS_MIN = 7;
|
|
96
96
|
exports.VIRTUAL_CARE_RETENTION_DAYS_MAX = 730;
|
|
97
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* Limites de `max_duration_minutes`.
|
|
99
|
+
*
|
|
100
|
+
* O teto desceu de 480 (8 h) para **90 (1h30)** em 2026-09-25, por pedido do
|
|
101
|
+
* dono do produto: sem teto a consulta "fica em curso indefinidamente" e nós
|
|
102
|
+
* pagamos minuto de sala, minuto de gravação e depois o processamento da
|
|
103
|
+
* transcrição.
|
|
104
|
+
*
|
|
105
|
+
* Duas coisas que este par de constantes NÃO é:
|
|
106
|
+
*
|
|
107
|
+
* - **não é a autoridade.** Quem garante o teto é o backend
|
|
108
|
+
* (`VIRTUAL_CARE_PLATFORM_MAX_DURATION_MINUTES`, em
|
|
109
|
+
* `packages/model/src/evo-telemedicine/virtual-care-policy.ts`), que clampa
|
|
110
|
+
* na LEITURA da agenda. Tem de ser lá porque o que roda em produção é a
|
|
111
|
+
* versão PUBLICADA deste pacote — um teto que só exista aqui não existe em
|
|
112
|
+
* produção até o publish chegar ao deploy;
|
|
113
|
+
* - **não é limite de escrita.** O `.max()` do zod continua em 480 de
|
|
114
|
+
* propósito — ver o comentário em `zMedCalendarVirtualCareConfigSchema`.
|
|
115
|
+
*
|
|
116
|
+
* O uso legítimo daqui é a TELA: é este número que o editor da agenda usa como
|
|
117
|
+
* `max` do campo e para avisar que o valor gravado está fora da faixa.
|
|
118
|
+
*/
|
|
98
119
|
exports.VIRTUAL_CARE_MAX_DURATION_MINUTES_MIN = 15;
|
|
99
|
-
exports.VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX =
|
|
120
|
+
exports.VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX = 90;
|
|
100
121
|
/**
|
|
101
122
|
* Defaults da spec (plan §12 / D13 / D32). Agenda sem `virtual_care` vale
|
|
102
123
|
* exatamente isto — é o que faz "sem migração de dado" ser verdade.
|
|
@@ -213,9 +213,30 @@ export type VirtualCareRecordingMode =
|
|
|
213
213
|
export const VIRTUAL_CARE_RETENTION_DAYS_MIN = 7;
|
|
214
214
|
export const VIRTUAL_CARE_RETENTION_DAYS_MAX = 730;
|
|
215
215
|
|
|
216
|
-
/**
|
|
216
|
+
/**
|
|
217
|
+
* Limites de `max_duration_minutes`.
|
|
218
|
+
*
|
|
219
|
+
* O teto desceu de 480 (8 h) para **90 (1h30)** em 2026-09-25, por pedido do
|
|
220
|
+
* dono do produto: sem teto a consulta "fica em curso indefinidamente" e nós
|
|
221
|
+
* pagamos minuto de sala, minuto de gravação e depois o processamento da
|
|
222
|
+
* transcrição.
|
|
223
|
+
*
|
|
224
|
+
* Duas coisas que este par de constantes NÃO é:
|
|
225
|
+
*
|
|
226
|
+
* - **não é a autoridade.** Quem garante o teto é o backend
|
|
227
|
+
* (`VIRTUAL_CARE_PLATFORM_MAX_DURATION_MINUTES`, em
|
|
228
|
+
* `packages/model/src/evo-telemedicine/virtual-care-policy.ts`), que clampa
|
|
229
|
+
* na LEITURA da agenda. Tem de ser lá porque o que roda em produção é a
|
|
230
|
+
* versão PUBLICADA deste pacote — um teto que só exista aqui não existe em
|
|
231
|
+
* produção até o publish chegar ao deploy;
|
|
232
|
+
* - **não é limite de escrita.** O `.max()` do zod continua em 480 de
|
|
233
|
+
* propósito — ver o comentário em `zMedCalendarVirtualCareConfigSchema`.
|
|
234
|
+
*
|
|
235
|
+
* O uso legítimo daqui é a TELA: é este número que o editor da agenda usa como
|
|
236
|
+
* `max` do campo e para avisar que o valor gravado está fora da faixa.
|
|
237
|
+
*/
|
|
217
238
|
export const VIRTUAL_CARE_MAX_DURATION_MINUTES_MIN = 15;
|
|
218
|
-
export const VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX =
|
|
239
|
+
export const VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX = 90;
|
|
219
240
|
|
|
220
241
|
/** O que está GRAVADO no doc da agenda — tudo parcial (ausente = default). */
|
|
221
242
|
export interface IMedCalendarVirtualCareConfig {
|
|
@@ -251,7 +272,15 @@ export interface IMedCalendarVirtualCareConfig {
|
|
|
251
272
|
} | null;
|
|
252
273
|
/** `true` = passar do fim previsto não encerra a consulta (comportamento atual). */
|
|
253
274
|
allow_late_end?: boolean | null;
|
|
254
|
-
/**
|
|
275
|
+
/**
|
|
276
|
+
* Teto absoluto; o sweep encerra ao exceder (`reason: max_duration`).
|
|
277
|
+
*
|
|
278
|
+
* Faixa da TELA: 15..90 (1h30, desde 2026-09-25). Doc gravado antes disso
|
|
279
|
+
* pode ter 120 (o default) ou 480, e continua salvável: o backend clampa na
|
|
280
|
+
* leitura e o zod não recusa. O default de
|
|
281
|
+
* `CALENDAR_VIRTUAL_CARE_DEFAULTS` segue 120 e também é clampado — o teto é
|
|
282
|
+
* da plataforma, não da agenda.
|
|
283
|
+
*/
|
|
255
284
|
max_duration_minutes?: number | null;
|
|
256
285
|
/** Aviso ao médico no SPA quando faltar N min para o fim. 0 = sem aviso. */
|
|
257
286
|
end_warning_minutes?: number | null;
|
|
@@ -38,6 +38,60 @@ export interface INexVendasJourneySignature {
|
|
|
38
38
|
requested_at?: Date | null;
|
|
39
39
|
signed_at?: Date | null;
|
|
40
40
|
last_error?: string | null;
|
|
41
|
+
/**
|
|
42
|
+
* Consultas ao provider feitas pelo `POST /journeys/:code/signature/check`
|
|
43
|
+
* (feat-203), podadas a 1 h. É o contador do throttle por jornada (mínimo 90 s
|
|
44
|
+
* entre consultas, no máximo 5 por hora): a cota da D4Sign é 10 req/h na
|
|
45
|
+
* conta inteira. A re-checagem do webhook não entra aqui.
|
|
46
|
+
*/
|
|
47
|
+
checks_at?: Date[] | null;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Por onde a assinatura foi confirmada no provider (feat-203). Vai em
|
|
51
|
+
* `data.via` do evento `contract_signed`: `webhook` é o POSTback da D4Sign,
|
|
52
|
+
* `check` é o "Verificar agora" do shop (caminho de destrave quando o webhook
|
|
53
|
+
* se perde).
|
|
54
|
+
*/
|
|
55
|
+
export type NexVendasJourneySignatureConfirmVia = 'webhook' | 'check';
|
|
56
|
+
/**
|
|
57
|
+
* Resultado do `POST /journeys/:code/signature/check` (feat-203 D4):
|
|
58
|
+
* - `signed`: o provider confirmou e ESTA chamada avançou a jornada;
|
|
59
|
+
* - `already_signed`: já estava assinada (ou o webhook venceu a corrida);
|
|
60
|
+
* - `pending`: o provider ainda não tem a assinatura;
|
|
61
|
+
* - `not_confirmed`: o provider respondeu outro status (recusado, cancelado…);
|
|
62
|
+
* - `not_applicable`: a jornada não está esperando assinatura — nada consultado;
|
|
63
|
+
* - `provider_unavailable`: sem provider configurado ou a consulta falhou.
|
|
64
|
+
*
|
|
65
|
+
* O throttle NÃO é um outcome: sai como 429 `too_many_checks` com `retry_after_s`.
|
|
66
|
+
*/
|
|
67
|
+
export type NexVendasJourneySignatureCheckOutcome = 'signed' | 'already_signed' | 'pending' | 'not_confirmed' | 'not_applicable' | 'provider_unavailable';
|
|
68
|
+
export interface INexVendasJourneySignatureCheckResult {
|
|
69
|
+
outcome: NexVendasJourneySignatureCheckOutcome;
|
|
70
|
+
/** Segundos até a próxima consulta ao provider ser aceita; ausente quando não se aplica. */
|
|
71
|
+
retry_after_s?: number | null;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Envelope substituído por correção de dados antes da assinatura (feat-200).
|
|
75
|
+
*
|
|
76
|
+
* `canceled_at` null com `cancel_error` preenchido = o cancelamento no provider
|
|
77
|
+
* falhou e o documento ficou órfão no cofre: é a lista de limpeza manual.
|
|
78
|
+
*/
|
|
79
|
+
export interface INexVendasJourneySignatureHistoryEntry {
|
|
80
|
+
envelope_id: string;
|
|
81
|
+
provider?: string | null;
|
|
82
|
+
requested_at?: Date | null;
|
|
83
|
+
canceled_at?: Date | null;
|
|
84
|
+
reason: 'customer_data_corrected' | (string & {});
|
|
85
|
+
cancel_error?: string | null;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Correção aplicada ao `customer_data` na janela antes da assinatura. Cada uma
|
|
89
|
+
* gera um envelope novo, e é o contador do teto por hora (feat-200 D3).
|
|
90
|
+
*/
|
|
91
|
+
export interface INexVendasJourneyCorrection {
|
|
92
|
+
at: Date;
|
|
93
|
+
/** Só os NOMES dos campos alterados (ex.: `email`, `company.zip`). */
|
|
94
|
+
fields: string[];
|
|
41
95
|
}
|
|
42
96
|
/**
|
|
43
97
|
* PDF da proposta comercial já persistido no bucket, pronto para virar anexo do
|
|
@@ -202,6 +256,29 @@ export interface INexVendasJourneyNotification {
|
|
|
202
256
|
sent_at: Date;
|
|
203
257
|
error?: string | null;
|
|
204
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* Como o lead foi achado. `contact_index` = índice de contatos do chat pelo
|
|
261
|
+
* telefone (com e sem o 9º dígito); `phone` = telefone exato no lead;
|
|
262
|
+
* `algolia` = busca por dígitos no índice de leads; `email` = e-mail exato;
|
|
263
|
+
* `created` = nada casou e a jornada criou o lead.
|
|
264
|
+
*/
|
|
265
|
+
export type NexVendasJourneyLeadResolvedBy = 'contact_index' | 'phone' | 'algolia' | 'email' | 'created';
|
|
266
|
+
/**
|
|
267
|
+
* Lead do CRM do tenant das notificações da jornada. É a âncora que as
|
|
268
|
+
* notificações levam em `externalLinks` (`crm_lead`): sem ela o hub-omni
|
|
269
|
+
* descarta o e-mail, que não cria contato sozinho.
|
|
270
|
+
*
|
|
271
|
+
* Re-resolução por correção de telefone/e-mail que devolve OUTRO lead
|
|
272
|
+
* sobrescreve este bloco e registra o evento `lead_relinked`; falha do
|
|
273
|
+
* resolvedor registra `lead_resolve_failed` e não bloqueia a jornada.
|
|
274
|
+
*/
|
|
275
|
+
export interface INexVendasJourneyLeadRef {
|
|
276
|
+
/** Tenant dono do lead — o do canal resolvido para as notificações. */
|
|
277
|
+
tenant: string;
|
|
278
|
+
lead_id: string;
|
|
279
|
+
resolved_by: NexVendasJourneyLeadResolvedBy;
|
|
280
|
+
resolved_at: Date;
|
|
281
|
+
}
|
|
205
282
|
/**
|
|
206
283
|
* Slots que disparam efeito externo NÃO-idempotente e por isso precisam de
|
|
207
284
|
* reserva transacional: criar o contrato, criar o envelope de assinatura,
|
|
@@ -246,8 +323,20 @@ export interface INexVendasJourney extends IFireGlobalDoc {
|
|
|
246
323
|
contract_ref?: string | null;
|
|
247
324
|
tenant_ref?: string | null;
|
|
248
325
|
customer_id?: string | null;
|
|
326
|
+
/** Lead do CRM no tenant das notificações (feat-202). Ausente = ainda não resolvido. */
|
|
327
|
+
lead_ref?: INexVendasJourneyLeadRef | null;
|
|
249
328
|
customer_data?: INexVendasJourneyCustomerData | null;
|
|
250
329
|
signature?: INexVendasJourneySignature | null;
|
|
330
|
+
/** Envelopes substituídos por correção de dados (feat-200). */
|
|
331
|
+
signature_history?: INexVendasJourneySignatureHistoryEntry[] | null;
|
|
332
|
+
/** Correções de dados antes da assinatura (feat-200), com timestamp. */
|
|
333
|
+
corrections?: INexVendasJourneyCorrection[] | null;
|
|
334
|
+
/**
|
|
335
|
+
* `true` quando o cliente Nexus em `customer_id` foi CRIADO por esta jornada —
|
|
336
|
+
* só então a correção atualiza o cadastro. Ausente = pré-existente
|
|
337
|
+
* (LINK-ONLY) ou jornada anterior à feat-200.
|
|
338
|
+
*/
|
|
339
|
+
customer_created_by_journey?: boolean | null;
|
|
251
340
|
payment?: INexVendasJourneyPayment | null;
|
|
252
341
|
/**
|
|
253
342
|
* PDF da proposta pronto para anexar ao envelope (feat-136). Ausente = ainda
|
|
@@ -316,6 +405,13 @@ export interface INexVendasJourneyPublic {
|
|
|
316
405
|
proposal: INexFinopsProposalPublic;
|
|
317
406
|
data_submitted: boolean;
|
|
318
407
|
customer_masked: INexVendasJourneyCustomerMasked | null;
|
|
408
|
+
/**
|
|
409
|
+
* `customer_data` COMPLETO, só na janela de correção (`dados_coletados` sem
|
|
410
|
+
* assinatura concluída); fora dela `null`. É o que o próprio lead digitou,
|
|
411
|
+
* devolvido a quem tem o `short_code`, para reabrir o formulário preenchido.
|
|
412
|
+
* Ausente em backend anterior à feat-200.
|
|
413
|
+
*/
|
|
414
|
+
editable_customer_data?: INexVendasJourneyCustomerData | null;
|
|
319
415
|
signature: {
|
|
320
416
|
status: NexVendasJourneySignatureStatus;
|
|
321
417
|
sign_url: string | null;
|
|
@@ -91,6 +91,71 @@ export interface INexVendasJourneySignature {
|
|
|
91
91
|
requested_at?: Date | null;
|
|
92
92
|
signed_at?: Date | null;
|
|
93
93
|
last_error?: string | null;
|
|
94
|
+
/**
|
|
95
|
+
* Consultas ao provider feitas pelo `POST /journeys/:code/signature/check`
|
|
96
|
+
* (feat-203), podadas a 1 h. É o contador do throttle por jornada (mínimo 90 s
|
|
97
|
+
* entre consultas, no máximo 5 por hora): a cota da D4Sign é 10 req/h na
|
|
98
|
+
* conta inteira. A re-checagem do webhook não entra aqui.
|
|
99
|
+
*/
|
|
100
|
+
checks_at?: Date[] | null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Por onde a assinatura foi confirmada no provider (feat-203). Vai em
|
|
105
|
+
* `data.via` do evento `contract_signed`: `webhook` é o POSTback da D4Sign,
|
|
106
|
+
* `check` é o "Verificar agora" do shop (caminho de destrave quando o webhook
|
|
107
|
+
* se perde).
|
|
108
|
+
*/
|
|
109
|
+
export type NexVendasJourneySignatureConfirmVia = 'webhook' | 'check';
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Resultado do `POST /journeys/:code/signature/check` (feat-203 D4):
|
|
113
|
+
* - `signed`: o provider confirmou e ESTA chamada avançou a jornada;
|
|
114
|
+
* - `already_signed`: já estava assinada (ou o webhook venceu a corrida);
|
|
115
|
+
* - `pending`: o provider ainda não tem a assinatura;
|
|
116
|
+
* - `not_confirmed`: o provider respondeu outro status (recusado, cancelado…);
|
|
117
|
+
* - `not_applicable`: a jornada não está esperando assinatura — nada consultado;
|
|
118
|
+
* - `provider_unavailable`: sem provider configurado ou a consulta falhou.
|
|
119
|
+
*
|
|
120
|
+
* O throttle NÃO é um outcome: sai como 429 `too_many_checks` com `retry_after_s`.
|
|
121
|
+
*/
|
|
122
|
+
export type NexVendasJourneySignatureCheckOutcome =
|
|
123
|
+
| 'signed'
|
|
124
|
+
| 'already_signed'
|
|
125
|
+
| 'pending'
|
|
126
|
+
| 'not_confirmed'
|
|
127
|
+
| 'not_applicable'
|
|
128
|
+
| 'provider_unavailable';
|
|
129
|
+
|
|
130
|
+
export interface INexVendasJourneySignatureCheckResult {
|
|
131
|
+
outcome: NexVendasJourneySignatureCheckOutcome;
|
|
132
|
+
/** Segundos até a próxima consulta ao provider ser aceita; ausente quando não se aplica. */
|
|
133
|
+
retry_after_s?: number | null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Envelope substituído por correção de dados antes da assinatura (feat-200).
|
|
138
|
+
*
|
|
139
|
+
* `canceled_at` null com `cancel_error` preenchido = o cancelamento no provider
|
|
140
|
+
* falhou e o documento ficou órfão no cofre: é a lista de limpeza manual.
|
|
141
|
+
*/
|
|
142
|
+
export interface INexVendasJourneySignatureHistoryEntry {
|
|
143
|
+
envelope_id: string;
|
|
144
|
+
provider?: string | null;
|
|
145
|
+
requested_at?: Date | null;
|
|
146
|
+
canceled_at?: Date | null;
|
|
147
|
+
reason: 'customer_data_corrected' | (string & {});
|
|
148
|
+
cancel_error?: string | null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Correção aplicada ao `customer_data` na janela antes da assinatura. Cada uma
|
|
153
|
+
* gera um envelope novo, e é o contador do teto por hora (feat-200 D3).
|
|
154
|
+
*/
|
|
155
|
+
export interface INexVendasJourneyCorrection {
|
|
156
|
+
at: Date;
|
|
157
|
+
/** Só os NOMES dos campos alterados (ex.: `email`, `company.zip`). */
|
|
158
|
+
fields: string[];
|
|
94
159
|
}
|
|
95
160
|
|
|
96
161
|
// ── PDF da proposta (anexo do envelope) ──
|
|
@@ -291,6 +356,38 @@ export interface INexVendasJourneyNotification {
|
|
|
291
356
|
error?: string | null;
|
|
292
357
|
}
|
|
293
358
|
|
|
359
|
+
// ── Lead do CRM (feat-202) ──
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Como o lead foi achado. `contact_index` = índice de contatos do chat pelo
|
|
363
|
+
* telefone (com e sem o 9º dígito); `phone` = telefone exato no lead;
|
|
364
|
+
* `algolia` = busca por dígitos no índice de leads; `email` = e-mail exato;
|
|
365
|
+
* `created` = nada casou e a jornada criou o lead.
|
|
366
|
+
*/
|
|
367
|
+
export type NexVendasJourneyLeadResolvedBy =
|
|
368
|
+
| 'contact_index'
|
|
369
|
+
| 'phone'
|
|
370
|
+
| 'algolia'
|
|
371
|
+
| 'email'
|
|
372
|
+
| 'created';
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Lead do CRM do tenant das notificações da jornada. É a âncora que as
|
|
376
|
+
* notificações levam em `externalLinks` (`crm_lead`): sem ela o hub-omni
|
|
377
|
+
* descarta o e-mail, que não cria contato sozinho.
|
|
378
|
+
*
|
|
379
|
+
* Re-resolução por correção de telefone/e-mail que devolve OUTRO lead
|
|
380
|
+
* sobrescreve este bloco e registra o evento `lead_relinked`; falha do
|
|
381
|
+
* resolvedor registra `lead_resolve_failed` e não bloqueia a jornada.
|
|
382
|
+
*/
|
|
383
|
+
export interface INexVendasJourneyLeadRef {
|
|
384
|
+
/** Tenant dono do lead — o do canal resolvido para as notificações. */
|
|
385
|
+
tenant: string;
|
|
386
|
+
lead_id: string;
|
|
387
|
+
resolved_by: NexVendasJourneyLeadResolvedBy;
|
|
388
|
+
resolved_at: Date;
|
|
389
|
+
}
|
|
390
|
+
|
|
294
391
|
// ── Reserva de efeito externo ──
|
|
295
392
|
|
|
296
393
|
/**
|
|
@@ -343,9 +440,21 @@ export interface INexVendasJourney extends IFireGlobalDoc {
|
|
|
343
440
|
contract_ref?: string | null;
|
|
344
441
|
tenant_ref?: string | null;
|
|
345
442
|
customer_id?: string | null;
|
|
443
|
+
/** Lead do CRM no tenant das notificações (feat-202). Ausente = ainda não resolvido. */
|
|
444
|
+
lead_ref?: INexVendasJourneyLeadRef | null;
|
|
346
445
|
|
|
347
446
|
customer_data?: INexVendasJourneyCustomerData | null;
|
|
348
447
|
signature?: INexVendasJourneySignature | null;
|
|
448
|
+
/** Envelopes substituídos por correção de dados (feat-200). */
|
|
449
|
+
signature_history?: INexVendasJourneySignatureHistoryEntry[] | null;
|
|
450
|
+
/** Correções de dados antes da assinatura (feat-200), com timestamp. */
|
|
451
|
+
corrections?: INexVendasJourneyCorrection[] | null;
|
|
452
|
+
/**
|
|
453
|
+
* `true` quando o cliente Nexus em `customer_id` foi CRIADO por esta jornada —
|
|
454
|
+
* só então a correção atualiza o cadastro. Ausente = pré-existente
|
|
455
|
+
* (LINK-ONLY) ou jornada anterior à feat-200.
|
|
456
|
+
*/
|
|
457
|
+
customer_created_by_journey?: boolean | null;
|
|
349
458
|
payment?: INexVendasJourneyPayment | null;
|
|
350
459
|
|
|
351
460
|
/**
|
|
@@ -425,6 +534,13 @@ export interface INexVendasJourneyPublic {
|
|
|
425
534
|
proposal: INexFinopsProposalPublic;
|
|
426
535
|
data_submitted: boolean;
|
|
427
536
|
customer_masked: INexVendasJourneyCustomerMasked | null;
|
|
537
|
+
/**
|
|
538
|
+
* `customer_data` COMPLETO, só na janela de correção (`dados_coletados` sem
|
|
539
|
+
* assinatura concluída); fora dela `null`. É o que o próprio lead digitou,
|
|
540
|
+
* devolvido a quem tem o `short_code`, para reabrir o formulário preenchido.
|
|
541
|
+
* Ausente em backend anterior à feat-200.
|
|
542
|
+
*/
|
|
543
|
+
editable_customer_data?: INexVendasJourneyCustomerData | null;
|
|
428
544
|
signature: {
|
|
429
545
|
status: NexVendasJourneySignatureStatus;
|
|
430
546
|
sign_url: string | null;
|