evo360-types 1.3.574 → 1.3.578

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.
@@ -90,6 +90,7 @@ export declare const zContactSchema: z.ZodObject<{
90
90
  type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
91
91
  instagram: z.ZodOptional<z.ZodNullable<z.ZodString>>;
92
92
  instagram_username: z.ZodOptional<z.ZodNullable<z.ZodString>>;
93
+ bsuid: z.ZodOptional<z.ZodNullable<z.ZodString>>;
93
94
  }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
94
95
  email: z.ZodDefault<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
95
96
  phone: z.ZodDefault<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
@@ -97,6 +98,7 @@ export declare const zContactSchema: z.ZodObject<{
97
98
  type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
98
99
  instagram: z.ZodOptional<z.ZodNullable<z.ZodString>>;
99
100
  instagram_username: z.ZodOptional<z.ZodNullable<z.ZodString>>;
101
+ bsuid: z.ZodOptional<z.ZodNullable<z.ZodString>>;
100
102
  }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
101
103
  email: z.ZodDefault<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
102
104
  phone: z.ZodDefault<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
@@ -104,4 +106,5 @@ export declare const zContactSchema: z.ZodObject<{
104
106
  type: z.ZodOptional<z.ZodNullable<z.ZodString>>;
105
107
  instagram: z.ZodOptional<z.ZodNullable<z.ZodString>>;
106
108
  instagram_username: z.ZodOptional<z.ZodNullable<z.ZodString>>;
109
+ bsuid: z.ZodOptional<z.ZodNullable<z.ZodString>>;
107
110
  }, z.ZodTypeAny, "passthrough">>;
@@ -89,4 +89,6 @@ exports.zContactSchema = zod_1.z.object({
89
89
  type: zod_1.z.string().nullable().optional(),
90
90
  instagram: zod_1.z.string().nullable().optional(),
91
91
  instagram_username: zod_1.z.string().nullable().optional(),
92
+ // WhatsApp BSUID (Business-Scoped User ID) — contato que a Meta entrega sem telefone
93
+ bsuid: zod_1.z.string().nullable().optional(),
92
94
  }).passthrough();
@@ -104,4 +104,6 @@ export const zContactSchema = z.object({
104
104
  type: z.string().nullable().optional(),
105
105
  instagram: z.string().nullable().optional(),
106
106
  instagram_username: z.string().nullable().optional(),
107
+ // WhatsApp BSUID (Business-Scoped User ID) — contato que a Meta entrega sem telefone
108
+ bsuid: z.string().nullable().optional(),
107
109
  }).passthrough();
@@ -76,6 +76,14 @@ export declare const NexFinopsMetricCatalog: {
76
76
  readonly label: "E-mails enviados";
77
77
  readonly unit: "mensagens";
78
78
  };
79
+ readonly teleconsultations_unrecorded: {
80
+ readonly label: "Teleconsultas sem gravação";
81
+ readonly unit: "consultas";
82
+ };
83
+ readonly teleconsultations_recorded: {
84
+ readonly label: "Teleconsultas com gravação";
85
+ readonly unit: "consultas";
86
+ };
79
87
  };
80
88
  /**
81
89
  * Chaves conhecidas do catálogo — para iterar e para tipar escolha de métrica
@@ -11,6 +11,13 @@ exports.NexFinopsMetricCatalog = {
11
11
  attendances: { label: 'Atendimentos', unit: 'contatos' },
12
12
  sms: { label: 'SMS enviados', unit: 'mensagens' },
13
13
  email: { label: 'E-mails enviados', unit: 'mensagens' },
14
+ // feat-160 F18 (D33) — DISJUNTAS: uma teleconsulta realizada consome
15
+ // exatamente UMA das duas. `_recorded` NAO e subconjunto de um total; o total
16
+ // e derivado na tela. A transcricao esta dentro de `_recorded`, nao tem
17
+ // franquia propria. Ler uma como subconjunto da outra cobra o mesmo encontro
18
+ // duas vezes.
19
+ teleconsultations_unrecorded: { label: 'Teleconsultas sem gravação', unit: 'consultas' },
20
+ teleconsultations_recorded: { label: 'Teleconsultas com gravação', unit: 'consultas' },
14
21
  };
15
22
  /** Doc de config global dos alertas de consumo (convenção `/platform/<app>`). */
16
23
  exports.EVO_BILLING_USAGE_ALERTS_CONFIG_PATH = 'platform/evo-billing/usage-alerts/config';
@@ -80,6 +80,13 @@ export const NexFinopsMetricCatalog = {
80
80
  attendances: { label: 'Atendimentos', unit: 'contatos' },
81
81
  sms: { label: 'SMS enviados', unit: 'mensagens' },
82
82
  email: { label: 'E-mails enviados', unit: 'mensagens' },
83
+ // feat-160 F18 (D33) — DISJUNTAS: uma teleconsulta realizada consome
84
+ // exatamente UMA das duas. `_recorded` NAO e subconjunto de um total; o total
85
+ // e derivado na tela. A transcricao esta dentro de `_recorded`, nao tem
86
+ // franquia propria. Ler uma como subconjunto da outra cobra o mesmo encontro
87
+ // duas vezes.
88
+ teleconsultations_unrecorded: { label: 'Teleconsultas sem gravação', unit: 'consultas' },
89
+ teleconsultations_recorded: { label: 'Teleconsultas com gravação', unit: 'consultas' },
83
90
  } as const;
84
91
 
85
92
  /**
@@ -131,6 +131,93 @@ export declare const MedCalendarNotificationConfigKeys: {
131
131
  readonly TelemedicineJoinReminder: "telemedicine_join_reminder";
132
132
  };
133
133
  export type MedCalendarNotificationConfigKey = (typeof MedCalendarNotificationConfigKeys)[keyof typeof MedCalendarNotificationConfigKeys];
134
+ /** `recording.mode` da agenda (feat-160 F15). `off` esconde "Solicitar gravação". */
135
+ export declare const VirtualCareRecordingModeEnum: {
136
+ /** Gravação indisponível nesta agenda. */
137
+ readonly Off: "off";
138
+ /** Médico solicita em sala e o paciente aceita ali (comportamento do MVP). */
139
+ readonly Manual: "manual";
140
+ /** Inicia sozinha, só áudio; o aceite é colhido ANTES de o paciente entrar. */
141
+ readonly AutoAudio: "auto_audio";
142
+ /** Idem, com vídeo. */
143
+ readonly AutoVideo: "auto_video";
144
+ };
145
+ export type VirtualCareRecordingMode = (typeof VirtualCareRecordingModeEnum)[keyof typeof VirtualCareRecordingModeEnum];
146
+ /** Limites de `recording.retention_days` (D32; D13 mantém 7 como default). */
147
+ export declare const VIRTUAL_CARE_RETENTION_DAYS_MIN = 7;
148
+ export declare const VIRTUAL_CARE_RETENTION_DAYS_MAX = 730;
149
+ /** Limites de `max_duration_minutes`. */
150
+ export declare const VIRTUAL_CARE_MAX_DURATION_MINUTES_MIN = 15;
151
+ export declare const VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX = 480;
152
+ /** O que está GRAVADO no doc da agenda — tudo parcial (ausente = default). */
153
+ export interface IMedCalendarVirtualCareConfig {
154
+ /**
155
+ * Admite o paciente sozinho quando o médico já está em sala
156
+ * (`waiting_policy` default `auto_when_doctor_present`). Exige a capability
157
+ * `auto_admit` do entitlement e NUNCA vale sem identidade verificada (D9).
158
+ */
159
+ auto_admit?: boolean | null;
160
+ recording?: {
161
+ mode?: VirtualCareRecordingMode | null;
162
+ /** Transcrição da gravação. Gate D12 + capability `transcription`. */
163
+ transcription?: boolean | null;
164
+ /**
165
+ * Retenção de gravação/transcrição em dias, 7..730 (D32). O sweep é a
166
+ * verdade (`artifact.expires_at` = fim + N dias); o lifecycle do bucket é
167
+ * só defesa de último caso. O prazo escolhido entra no texto de gravação
168
+ * mostrado ao paciente (`{{retention}}`).
169
+ */
170
+ retention_days?: number | null;
171
+ } | null;
172
+ identity?: {
173
+ require_name?: boolean | null;
174
+ /** Só é exigível quando o cadastro TEM data de nascimento (spec §8.3). */
175
+ require_birth_date?: boolean | null;
176
+ /** `true` ⇒ `identity_level: 'weak'`; nunca habilita auto-admit (D9). */
177
+ skip?: boolean | null;
178
+ } | null;
179
+ /** Antecedência de acesso à sala, por papel, em minutos. */
180
+ allow_early_start_minutes?: {
181
+ doctor?: number | null;
182
+ patient?: number | null;
183
+ } | null;
184
+ /** `true` = passar do fim previsto não encerra a consulta (comportamento atual). */
185
+ allow_late_end?: boolean | null;
186
+ /** Teto absoluto; o sweep encerra ao exceder (`reason: max_duration`). 15..480. */
187
+ max_duration_minutes?: number | null;
188
+ /** Aviso ao médico no SPA quando faltar N min para o fim. 0 = sem aviso. */
189
+ end_warning_minutes?: number | null;
190
+ }
191
+ /** Config já RESOLVIDA (doc + defaults) — é com isto que o backend decide. */
192
+ export interface IMedCalendarVirtualCareSettings {
193
+ auto_admit: boolean;
194
+ recording: {
195
+ mode: VirtualCareRecordingMode;
196
+ transcription: boolean;
197
+ retention_days: number;
198
+ };
199
+ identity: {
200
+ require_name: boolean;
201
+ require_birth_date: boolean;
202
+ skip: boolean;
203
+ };
204
+ allow_early_start_minutes: {
205
+ doctor: number;
206
+ patient: number;
207
+ };
208
+ allow_late_end: boolean;
209
+ max_duration_minutes: number;
210
+ end_warning_minutes: number;
211
+ }
212
+ /**
213
+ * Defaults da spec (plan §12 / D13 / D32). Agenda sem `virtual_care` vale
214
+ * exatamente isto — é o que faz "sem migração de dado" ser verdade.
215
+ *
216
+ * Congelado (`as const` + `Readonly`) de propósito: é referência compartilhada,
217
+ * e um consumidor que mutasse um nível aninhado mudaria o default de todos.
218
+ * Para resolver, faça merge por nível (`{ ...DEFAULTS.recording, ...cfg.recording }`).
219
+ */
220
+ export declare const CALENDAR_VIRTUAL_CARE_DEFAULTS: IMedCalendarVirtualCareSettings;
134
221
  export interface IMedCalendar extends IFireDoc {
135
222
  calendarId: string;
136
223
  color?: string;
@@ -160,5 +247,16 @@ export interface IMedCalendar extends IFireDoc {
160
247
  available_for_hubia?: boolean | null;
161
248
  integration?: IMedCalendarIntegration | null;
162
249
  notification_config?: IMedCalendarNotificationConfig | null;
250
+ /**
251
+ * Config de telemedicina por-agenda (feat-160 F16). Ausente = defaults de
252
+ * `CALENDAR_VIRTUAL_CARE_DEFAULTS`; só tem efeito com `modules.telemedicine`.
253
+ */
254
+ virtual_care?: IMedCalendarVirtualCareConfig | null;
255
+ /**
256
+ * Profissional (médico) padrão da agenda — feat-160 F16, fora do módulo de
257
+ * telemedicina (pedido do usuário, mesmo editor). Ref para
258
+ * `tenants/{t}/apps/evo-med/professionals/{id}`; `null` = sem padrão.
259
+ */
260
+ default_professional_ref?: FirestoreDocumentReference | null;
163
261
  [key: string]: unknown;
164
262
  }
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.MedCalendarNotificationConfigKeys = exports.EvoMedCalendarPermissions = void 0;
17
+ exports.CALENDAR_VIRTUAL_CARE_DEFAULTS = exports.VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX = exports.VIRTUAL_CARE_MAX_DURATION_MINUTES_MIN = exports.VIRTUAL_CARE_RETENTION_DAYS_MAX = exports.VIRTUAL_CARE_RETENTION_DAYS_MIN = exports.VirtualCareRecordingModeEnum = exports.MedCalendarNotificationConfigKeys = exports.EvoMedCalendarPermissions = void 0;
18
18
  __exportStar(require("../../evo-people/fb_collections"), exports);
19
19
  // Permissões para o calendário
20
20
  exports.EvoMedCalendarPermissions = {
@@ -66,3 +66,62 @@ exports.MedCalendarNotificationConfigKeys = {
66
66
  */
67
67
  TelemedicineJoinReminder: "telemedicine_join_reminder",
68
68
  };
69
+ // ----- Virtual Care (inline no calendar doc) — feat-160 F16
70
+ // Config por-agenda do módulo de telemedicina ("Hub Médica Virtual Care"), lida
71
+ // pelo backend no `join`/`admit`/sweep e editada na seção própria do Calendar V2
72
+ // (visível só com o entitlement `modules.telemedicine`).
73
+ //
74
+ // Bloco e campos são TODOS opcionais: agenda sem o bloco (a maioria) vale
75
+ // exatamente `CALENDAR_VIRTUAL_CARE_DEFAULTS`, sem migração de dado (plan §12).
76
+ // Por isso existem DOIS tipos: `IMedCalendarVirtualCareConfig` é o que está
77
+ // gravado (parcial), e `IMedCalendarVirtualCareSettings` é o resultado de
78
+ // aplicar os defaults sobre ele — o que o backend efetivamente decide com.
79
+ //
80
+ // `| null` em todo campo, como no `notification_config`: o editor do FE grava
81
+ // "não escolhido" como `null` explícito e `.passthrough()` não cobre null em
82
+ // chave declarada — sem `.nullable()` o doc inteiro do calendário reprovaria.
83
+ /** `recording.mode` da agenda (feat-160 F15). `off` esconde "Solicitar gravação". */
84
+ exports.VirtualCareRecordingModeEnum = {
85
+ /** Gravação indisponível nesta agenda. */
86
+ Off: "off",
87
+ /** Médico solicita em sala e o paciente aceita ali (comportamento do MVP). */
88
+ Manual: "manual",
89
+ /** Inicia sozinha, só áudio; o aceite é colhido ANTES de o paciente entrar. */
90
+ AutoAudio: "auto_audio",
91
+ /** Idem, com vídeo. */
92
+ AutoVideo: "auto_video",
93
+ };
94
+ /** Limites de `recording.retention_days` (D32; D13 mantém 7 como default). */
95
+ exports.VIRTUAL_CARE_RETENTION_DAYS_MIN = 7;
96
+ exports.VIRTUAL_CARE_RETENTION_DAYS_MAX = 730;
97
+ /** Limites de `max_duration_minutes`. */
98
+ exports.VIRTUAL_CARE_MAX_DURATION_MINUTES_MIN = 15;
99
+ exports.VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX = 480;
100
+ /**
101
+ * Defaults da spec (plan §12 / D13 / D32). Agenda sem `virtual_care` vale
102
+ * exatamente isto — é o que faz "sem migração de dado" ser verdade.
103
+ *
104
+ * Congelado (`as const` + `Readonly`) de propósito: é referência compartilhada,
105
+ * e um consumidor que mutasse um nível aninhado mudaria o default de todos.
106
+ * Para resolver, faça merge por nível (`{ ...DEFAULTS.recording, ...cfg.recording }`).
107
+ */
108
+ exports.CALENDAR_VIRTUAL_CARE_DEFAULTS = {
109
+ auto_admit: false,
110
+ recording: {
111
+ mode: exports.VirtualCareRecordingModeEnum.Manual,
112
+ transcription: false,
113
+ retention_days: exports.VIRTUAL_CARE_RETENTION_DAYS_MIN,
114
+ },
115
+ identity: {
116
+ require_name: true,
117
+ require_birth_date: true,
118
+ skip: false,
119
+ },
120
+ allow_early_start_minutes: {
121
+ doctor: 30,
122
+ patient: 15,
123
+ },
124
+ allow_late_end: true,
125
+ max_duration_minutes: 120,
126
+ end_warning_minutes: 5,
127
+ };
@@ -152,6 +152,135 @@ export const MedCalendarNotificationConfigKeys = {
152
152
  export type MedCalendarNotificationConfigKey =
153
153
  (typeof MedCalendarNotificationConfigKeys)[keyof typeof MedCalendarNotificationConfigKeys];
154
154
 
155
+ // ----- Virtual Care (inline no calendar doc) — feat-160 F16
156
+ // Config por-agenda do módulo de telemedicina ("Hub Médica Virtual Care"), lida
157
+ // pelo backend no `join`/`admit`/sweep e editada na seção própria do Calendar V2
158
+ // (visível só com o entitlement `modules.telemedicine`).
159
+ //
160
+ // Bloco e campos são TODOS opcionais: agenda sem o bloco (a maioria) vale
161
+ // exatamente `CALENDAR_VIRTUAL_CARE_DEFAULTS`, sem migração de dado (plan §12).
162
+ // Por isso existem DOIS tipos: `IMedCalendarVirtualCareConfig` é o que está
163
+ // gravado (parcial), e `IMedCalendarVirtualCareSettings` é o resultado de
164
+ // aplicar os defaults sobre ele — o que o backend efetivamente decide com.
165
+ //
166
+ // `| null` em todo campo, como no `notification_config`: o editor do FE grava
167
+ // "não escolhido" como `null` explícito e `.passthrough()` não cobre null em
168
+ // chave declarada — sem `.nullable()` o doc inteiro do calendário reprovaria.
169
+
170
+ /** `recording.mode` da agenda (feat-160 F15). `off` esconde "Solicitar gravação". */
171
+ export const VirtualCareRecordingModeEnum = {
172
+ /** Gravação indisponível nesta agenda. */
173
+ Off: "off",
174
+ /** Médico solicita em sala e o paciente aceita ali (comportamento do MVP). */
175
+ Manual: "manual",
176
+ /** Inicia sozinha, só áudio; o aceite é colhido ANTES de o paciente entrar. */
177
+ AutoAudio: "auto_audio",
178
+ /** Idem, com vídeo. */
179
+ AutoVideo: "auto_video",
180
+ } as const;
181
+
182
+ export type VirtualCareRecordingMode =
183
+ (typeof VirtualCareRecordingModeEnum)[keyof typeof VirtualCareRecordingModeEnum];
184
+
185
+ /** Limites de `recording.retention_days` (D32; D13 mantém 7 como default). */
186
+ export const VIRTUAL_CARE_RETENTION_DAYS_MIN = 7;
187
+ export const VIRTUAL_CARE_RETENTION_DAYS_MAX = 730;
188
+
189
+ /** Limites de `max_duration_minutes`. */
190
+ export const VIRTUAL_CARE_MAX_DURATION_MINUTES_MIN = 15;
191
+ export const VIRTUAL_CARE_MAX_DURATION_MINUTES_MAX = 480;
192
+
193
+ /** O que está GRAVADO no doc da agenda — tudo parcial (ausente = default). */
194
+ export interface IMedCalendarVirtualCareConfig {
195
+ /**
196
+ * Admite o paciente sozinho quando o médico já está em sala
197
+ * (`waiting_policy` default `auto_when_doctor_present`). Exige a capability
198
+ * `auto_admit` do entitlement e NUNCA vale sem identidade verificada (D9).
199
+ */
200
+ auto_admit?: boolean | null;
201
+ recording?: {
202
+ mode?: VirtualCareRecordingMode | null;
203
+ /** Transcrição da gravação. Gate D12 + capability `transcription`. */
204
+ transcription?: boolean | null;
205
+ /**
206
+ * Retenção de gravação/transcrição em dias, 7..730 (D32). O sweep é a
207
+ * verdade (`artifact.expires_at` = fim + N dias); o lifecycle do bucket é
208
+ * só defesa de último caso. O prazo escolhido entra no texto de gravação
209
+ * mostrado ao paciente (`{{retention}}`).
210
+ */
211
+ retention_days?: number | null;
212
+ } | null;
213
+ identity?: {
214
+ require_name?: boolean | null;
215
+ /** Só é exigível quando o cadastro TEM data de nascimento (spec §8.3). */
216
+ require_birth_date?: boolean | null;
217
+ /** `true` ⇒ `identity_level: 'weak'`; nunca habilita auto-admit (D9). */
218
+ skip?: boolean | null;
219
+ } | null;
220
+ /** Antecedência de acesso à sala, por papel, em minutos. */
221
+ allow_early_start_minutes?: {
222
+ doctor?: number | null;
223
+ patient?: number | null;
224
+ } | null;
225
+ /** `true` = passar do fim previsto não encerra a consulta (comportamento atual). */
226
+ allow_late_end?: boolean | null;
227
+ /** Teto absoluto; o sweep encerra ao exceder (`reason: max_duration`). 15..480. */
228
+ max_duration_minutes?: number | null;
229
+ /** Aviso ao médico no SPA quando faltar N min para o fim. 0 = sem aviso. */
230
+ end_warning_minutes?: number | null;
231
+ }
232
+
233
+ /** Config já RESOLVIDA (doc + defaults) — é com isto que o backend decide. */
234
+ export interface IMedCalendarVirtualCareSettings {
235
+ auto_admit: boolean;
236
+ recording: {
237
+ mode: VirtualCareRecordingMode;
238
+ transcription: boolean;
239
+ retention_days: number;
240
+ };
241
+ identity: {
242
+ require_name: boolean;
243
+ require_birth_date: boolean;
244
+ skip: boolean;
245
+ };
246
+ allow_early_start_minutes: {
247
+ doctor: number;
248
+ patient: number;
249
+ };
250
+ allow_late_end: boolean;
251
+ max_duration_minutes: number;
252
+ end_warning_minutes: number;
253
+ }
254
+
255
+ /**
256
+ * Defaults da spec (plan §12 / D13 / D32). Agenda sem `virtual_care` vale
257
+ * exatamente isto — é o que faz "sem migração de dado" ser verdade.
258
+ *
259
+ * Congelado (`as const` + `Readonly`) de propósito: é referência compartilhada,
260
+ * e um consumidor que mutasse um nível aninhado mudaria o default de todos.
261
+ * Para resolver, faça merge por nível (`{ ...DEFAULTS.recording, ...cfg.recording }`).
262
+ */
263
+ export const CALENDAR_VIRTUAL_CARE_DEFAULTS: IMedCalendarVirtualCareSettings = {
264
+ auto_admit: false,
265
+ recording: {
266
+ mode: VirtualCareRecordingModeEnum.Manual,
267
+ transcription: false,
268
+ retention_days: VIRTUAL_CARE_RETENTION_DAYS_MIN,
269
+ },
270
+ identity: {
271
+ require_name: true,
272
+ require_birth_date: true,
273
+ skip: false,
274
+ },
275
+ allow_early_start_minutes: {
276
+ doctor: 30,
277
+ patient: 15,
278
+ },
279
+ allow_late_end: true,
280
+ max_duration_minutes: 120,
281
+ end_warning_minutes: 5,
282
+ } as const;
283
+
155
284
  // ----- MedCalendarTypes
156
285
  export interface IMedCalendar extends IFireDoc {
157
286
  calendarId: string;
@@ -187,5 +316,16 @@ export interface IMedCalendar extends IFireDoc {
187
316
  integration?: IMedCalendarIntegration | null;
188
317
  // Config de notificações por-agenda (feat-048). Opcional — agendas sem lembrete não têm o bloco.
189
318
  notification_config?: IMedCalendarNotificationConfig | null;
319
+ /**
320
+ * Config de telemedicina por-agenda (feat-160 F16). Ausente = defaults de
321
+ * `CALENDAR_VIRTUAL_CARE_DEFAULTS`; só tem efeito com `modules.telemedicine`.
322
+ */
323
+ virtual_care?: IMedCalendarVirtualCareConfig | null;
324
+ /**
325
+ * Profissional (médico) padrão da agenda — feat-160 F16, fora do módulo de
326
+ * telemedicina (pedido do usuário, mesmo editor). Ref para
327
+ * `tenants/{t}/apps/evo-med/professionals/{id}`; `null` = sem padrão.
328
+ */
329
+ default_professional_ref?: FirestoreDocumentReference | null;
190
330
  [key: string]: unknown; // index signature
191
331
  }
@@ -21,6 +21,17 @@ export interface IUsageCapabilities {
21
21
  * antes dessa data: ausência de medição não é consumo zero.
22
22
  */
23
23
  llm_since: string | null;
24
+ /**
25
+ * feat-160 F18 — entitlement `modules.telemedicine` ativo OU uso de
26
+ * teleconsulta medido na janela.
27
+ */
28
+ telemedicine: boolean;
29
+ /**
30
+ * Data (`YYYY-MM-DD`) a partir da qual existe medição de teleconsulta — o
31
+ * emissor não tem backfill. `null` antes do deploy dele; a série não é
32
+ * desenhada antes dessa data, porque ausência de medição não é consumo zero.
33
+ */
34
+ telemedicine_since: string | null;
24
35
  }
25
36
  /**
26
37
  * Uma linha da abertura por departamento dentro de um mês.
@@ -84,6 +95,21 @@ export interface IUsageLlm {
84
95
  tokens_cache_write: number;
85
96
  tokens_cache_read: number;
86
97
  }
98
+ /**
99
+ * Teleconsultas REALIZADAS no mês (feat-160 F18 / D33). Realizada = a consulta
100
+ * começou (`started_at`) E o paciente esteve conectado (`connected_at`): médico
101
+ * entrando em sala vazia não conta.
102
+ *
103
+ * Os dois campos são DISJUNTOS — uma consulta cai em exatamente um. O total é a
104
+ * soma; não há campo de total, para não haver duas verdades.
105
+ *
106
+ * `com_gravacao` = teve ao menos um artifact `recording_*` em `ready`. Bloco
107
+ * inteiro `null` = capability desligada (não é consumo zero).
108
+ */
109
+ export interface IUsageTelemedicine {
110
+ realizadas_sem_gravacao: number;
111
+ realizadas_com_gravacao: number;
112
+ }
87
113
  export interface IMonthlyUsageRow {
88
114
  /** Primeiro dia do mês em UTC, `YYYY-MM-DD`. */
89
115
  mes: string;
@@ -92,6 +118,7 @@ export interface IMonthlyUsageRow {
92
118
  contatos: IUsageContacts;
93
119
  notificacoes: IUsageNotifications;
94
120
  ia: IUsageLlm | null;
121
+ telemedicina: IUsageTelemedicine | null;
95
122
  }
96
123
  export interface IMonthlyUsageResponse {
97
124
  ok: true;
@@ -37,6 +37,17 @@ export interface IUsageCapabilities {
37
37
  * antes dessa data: ausência de medição não é consumo zero.
38
38
  */
39
39
  llm_since: string | null;
40
+ /**
41
+ * feat-160 F18 — entitlement `modules.telemedicine` ativo OU uso de
42
+ * teleconsulta medido na janela.
43
+ */
44
+ telemedicine: boolean;
45
+ /**
46
+ * Data (`YYYY-MM-DD`) a partir da qual existe medição de teleconsulta — o
47
+ * emissor não tem backfill. `null` antes do deploy dele; a série não é
48
+ * desenhada antes dessa data, porque ausência de medição não é consumo zero.
49
+ */
50
+ telemedicine_since: string | null;
40
51
  }
41
52
 
42
53
  /**
@@ -105,6 +116,22 @@ export interface IUsageLlm {
105
116
  tokens_cache_read: number;
106
117
  }
107
118
 
119
+ /**
120
+ * Teleconsultas REALIZADAS no mês (feat-160 F18 / D33). Realizada = a consulta
121
+ * começou (`started_at`) E o paciente esteve conectado (`connected_at`): médico
122
+ * entrando em sala vazia não conta.
123
+ *
124
+ * Os dois campos são DISJUNTOS — uma consulta cai em exatamente um. O total é a
125
+ * soma; não há campo de total, para não haver duas verdades.
126
+ *
127
+ * `com_gravacao` = teve ao menos um artifact `recording_*` em `ready`. Bloco
128
+ * inteiro `null` = capability desligada (não é consumo zero).
129
+ */
130
+ export interface IUsageTelemedicine {
131
+ realizadas_sem_gravacao: number;
132
+ realizadas_com_gravacao: number;
133
+ }
134
+
108
135
  export interface IMonthlyUsageRow {
109
136
  /** Primeiro dia do mês em UTC, `YYYY-MM-DD`. */
110
137
  mes: string;
@@ -113,6 +140,7 @@ export interface IMonthlyUsageRow {
113
140
  contatos: IUsageContacts;
114
141
  notificacoes: IUsageNotifications;
115
142
  ia: IUsageLlm | null;
143
+ telemedicina: IUsageTelemedicine | null;
116
144
  }
117
145
 
118
146
  export interface IMonthlyUsageResponse {