evo360-types 1.3.512 → 1.3.514

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.
@@ -7,12 +7,35 @@ export interface SearchThreadsParams {
7
7
  department_ids?: string[];
8
8
  attendant_type?: SearchAttendantType;
9
9
  assigned_user_id?: string;
10
+ /** Atendente que ENCERROU algum ticket da conversa na janela. */
11
+ closed_by_user_id?: string;
12
+ close_codes?: string[];
10
13
  tag_ids?: string[];
11
14
  /** Free-text contains-match against contact_name (case-insensitive) OR contact_address (digits/email/etc). */
12
15
  search?: string;
13
16
  cursor?: string;
14
17
  limit?: number;
15
18
  }
19
+ /**
20
+ * Janela de datas efetivamente usada na consulta.
21
+ *
22
+ * Existe porque o backend aplica um default quando o cliente nao manda datas —
23
+ * e ate a feat-127 nao contava isso a ninguem. O usuario procurava uma conversa
24
+ * fora da janela, recebia lista vazia e concluia que ela tinha sumido.
25
+ *
26
+ * `default_window_days` vem junto para o cliente rotular ("ultimos 30 dias") sem
27
+ * duplicar a constante: a regra tem UM dono, que e' o backend.
28
+ */
29
+ export interface AppliedWindow {
30
+ /** ISO. Inicio da janela consultada. */
31
+ date_from: string;
32
+ /** ISO. Fim da janela consultada. */
33
+ date_to: string;
34
+ /** true = o cliente nao mandou datas e o backend aplicou o default. */
35
+ defaulted: boolean;
36
+ /** Tamanho do default, em dias. */
37
+ default_window_days: number;
38
+ }
16
39
  export interface SearchThreadCursor {
17
40
  last_activity_ms: number;
18
41
  contact_id: string;
@@ -66,8 +89,58 @@ export interface SearchThreadsResponse {
66
89
  ok: true;
67
90
  threads: ThreadAggregate[];
68
91
  nextCursor?: string;
92
+ /** Janela realmente aplicada — mandada pelo cliente ou default do backend. */
93
+ applied_window: AppliedWindow;
94
+ /**
95
+ * Total de CONVERSAS (contatos distintos) que casam com os filtros na janela.
96
+ *
97
+ * Independente de paginacao: e' o mesmo valor em todas as paginas. Sai da
98
+ * propria query da lista (`COUNT(*) OVER ()`), sem query extra e sem bytes
99
+ * adicionais — o agregado por contato ja e' materializado inteiro antes do
100
+ * LIMIT.
101
+ */
102
+ total: number;
69
103
  stats: SearchThreadsStats;
70
104
  }
105
+ /**
106
+ * Dimensoes com contagem na busca avancada.
107
+ *
108
+ * `tag_ids` NAO esta aqui de proposito: tags nao existem no BigQuery — o filtro
109
+ * por tag resolve os contatos no Firestore ANTES da query. Facetar exigiria
110
+ * varrer leads por tag a cada mudanca de filtro, no caminho quente da tela.
111
+ */
112
+ export type SearchFacetDimension = 'status' | 'department_id' | 'attendant_type' | 'assigned_user_id' | 'closed_by_user_id' | 'close_code';
113
+ export interface SearchFacetBucket {
114
+ value: string;
115
+ /** Contagem em CONVERSAS distintas (contatos), NAO em tickets. */
116
+ count: number;
117
+ /**
118
+ * So' preenchido em `closed_by_user_id`. Hub-omni e' cross-tenant: quem
119
+ * encerra um ticket do tenant X nem sempre consta em `tenants/X/users`, entao
120
+ * o cliente nao tem como resolver esse rotulo sozinho. Nas demais dimensoes o
121
+ * cliente ja carrega o dicionario correspondente.
122
+ */
123
+ label?: string;
124
+ }
125
+ export interface SearchFacetsStats {
126
+ bq_query_id?: string;
127
+ bq_bytes_processed?: number;
128
+ duration_ms: number;
129
+ }
130
+ export interface SearchFacetsResponse {
131
+ ok: true;
132
+ /**
133
+ * Contagem por dimensao. Cada dimensao aplica TODOS os filtros ativos MENOS o
134
+ * dela propria (faceting classico) — senao marcar uma opcao zeraria todas as
135
+ * outras da mesma lista.
136
+ *
137
+ * Valor ausente = zero. O cliente que renderiza a lista de opcoes a partir de
138
+ * um dicionario deve tratar ausencia como `(0)`.
139
+ */
140
+ facets: Record<SearchFacetDimension, SearchFacetBucket[]>;
141
+ applied_window: AppliedWindow;
142
+ stats: SearchFacetsStats;
143
+ }
71
144
  export type SearchThreadsErrorCode = 'invalid_filter' | 'tag_filter_too_broad' | 'forbidden' | 'bq_error' | 'fs_error';
72
145
  export interface SearchThreadsErrorResponse {
73
146
  ok: false;
@@ -135,5 +208,7 @@ export interface TimelineResponse {
135
208
  ok: true;
136
209
  timeline: TimelineEntry[];
137
210
  nextCursor?: string;
211
+ /** Mesma janela default silenciosa da lista — ver `AppliedWindow`. */
212
+ applied_window: AppliedWindow;
138
213
  stats: TimelineStats;
139
214
  }
@@ -14,6 +14,9 @@ export interface SearchThreadsParams {
14
14
  department_ids?: string[];
15
15
  attendant_type?: SearchAttendantType;
16
16
  assigned_user_id?: string;
17
+ /** Atendente que ENCERROU algum ticket da conversa na janela. */
18
+ closed_by_user_id?: string;
19
+ close_codes?: string[];
17
20
  tag_ids?: string[];
18
21
  /** Free-text contains-match against contact_name (case-insensitive) OR contact_address (digits/email/etc). */
19
22
  search?: string;
@@ -21,6 +24,27 @@ export interface SearchThreadsParams {
21
24
  limit?: number;
22
25
  }
23
26
 
27
+ /**
28
+ * Janela de datas efetivamente usada na consulta.
29
+ *
30
+ * Existe porque o backend aplica um default quando o cliente nao manda datas —
31
+ * e ate a feat-127 nao contava isso a ninguem. O usuario procurava uma conversa
32
+ * fora da janela, recebia lista vazia e concluia que ela tinha sumido.
33
+ *
34
+ * `default_window_days` vem junto para o cliente rotular ("ultimos 30 dias") sem
35
+ * duplicar a constante: a regra tem UM dono, que e' o backend.
36
+ */
37
+ export interface AppliedWindow {
38
+ /** ISO. Inicio da janela consultada. */
39
+ date_from: string;
40
+ /** ISO. Fim da janela consultada. */
41
+ date_to: string;
42
+ /** true = o cliente nao mandou datas e o backend aplicou o default. */
43
+ defaulted: boolean;
44
+ /** Tamanho do default, em dias. */
45
+ default_window_days: number;
46
+ }
47
+
24
48
  export interface SearchThreadCursor {
25
49
  last_activity_ms: number;
26
50
  contact_id: string;
@@ -80,9 +104,71 @@ export interface SearchThreadsResponse {
80
104
  ok: true;
81
105
  threads: ThreadAggregate[];
82
106
  nextCursor?: string;
107
+ /** Janela realmente aplicada — mandada pelo cliente ou default do backend. */
108
+ applied_window: AppliedWindow;
109
+ /**
110
+ * Total de CONVERSAS (contatos distintos) que casam com os filtros na janela.
111
+ *
112
+ * Independente de paginacao: e' o mesmo valor em todas as paginas. Sai da
113
+ * propria query da lista (`COUNT(*) OVER ()`), sem query extra e sem bytes
114
+ * adicionais — o agregado por contato ja e' materializado inteiro antes do
115
+ * LIMIT.
116
+ */
117
+ total: number;
83
118
  stats: SearchThreadsStats;
84
119
  }
85
120
 
121
+ // ── Facets ──
122
+
123
+ /**
124
+ * Dimensoes com contagem na busca avancada.
125
+ *
126
+ * `tag_ids` NAO esta aqui de proposito: tags nao existem no BigQuery — o filtro
127
+ * por tag resolve os contatos no Firestore ANTES da query. Facetar exigiria
128
+ * varrer leads por tag a cada mudanca de filtro, no caminho quente da tela.
129
+ */
130
+ export type SearchFacetDimension =
131
+ | 'status'
132
+ | 'department_id'
133
+ | 'attendant_type'
134
+ | 'assigned_user_id'
135
+ | 'closed_by_user_id'
136
+ | 'close_code';
137
+
138
+ export interface SearchFacetBucket {
139
+ value: string;
140
+ /** Contagem em CONVERSAS distintas (contatos), NAO em tickets. */
141
+ count: number;
142
+ /**
143
+ * So' preenchido em `closed_by_user_id`. Hub-omni e' cross-tenant: quem
144
+ * encerra um ticket do tenant X nem sempre consta em `tenants/X/users`, entao
145
+ * o cliente nao tem como resolver esse rotulo sozinho. Nas demais dimensoes o
146
+ * cliente ja carrega o dicionario correspondente.
147
+ */
148
+ label?: string;
149
+ }
150
+
151
+ export interface SearchFacetsStats {
152
+ bq_query_id?: string;
153
+ bq_bytes_processed?: number;
154
+ duration_ms: number;
155
+ }
156
+
157
+ export interface SearchFacetsResponse {
158
+ ok: true;
159
+ /**
160
+ * Contagem por dimensao. Cada dimensao aplica TODOS os filtros ativos MENOS o
161
+ * dela propria (faceting classico) — senao marcar uma opcao zeraria todas as
162
+ * outras da mesma lista.
163
+ *
164
+ * Valor ausente = zero. O cliente que renderiza a lista de opcoes a partir de
165
+ * um dicionario deve tratar ausencia como `(0)`.
166
+ */
167
+ facets: Record<SearchFacetDimension, SearchFacetBucket[]>;
168
+ applied_window: AppliedWindow;
169
+ stats: SearchFacetsStats;
170
+ }
171
+
86
172
  export type SearchThreadsErrorCode =
87
173
  | 'invalid_filter'
88
174
  | 'tag_filter_too_broad'
@@ -178,5 +264,7 @@ export interface TimelineResponse {
178
264
  ok: true;
179
265
  timeline: TimelineEntry[];
180
266
  nextCursor?: string;
267
+ /** Mesma janela default silenciosa da lista — ver `AppliedWindow`. */
268
+ applied_window: AppliedWindow;
181
269
  stats: TimelineStats;
182
270
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evo360-types",
3
- "version": "1.3.512",
3
+ "version": "1.3.514",
4
4
  "description": "HREVO360 Shared Types",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",