@greatapps/greatagents 0.1.10 → 0.1.12
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/package.json +1 -1
- package/src/modules/{channels → contacts}/index.js +1 -1
- package/src/modules/{tags → contacts}/properties.js +49 -17
- package/src/modules/conversations/index.js +1 -1
- package/src/modules/conversations/properties.js +35 -80
- package/src/modules/objectives/index.js +1 -1
- package/src/modules/objectives/properties.js +8 -7
- package/src/product.js +4 -24
- package/docs/ERD_GAGents_Database.mmd +0 -331
- package/scripts/MIGRATION_COMPLETE_DOCUMENTATION.md +0 -672
- package/scripts/README.md +0 -165
- package/scripts/constraints.sql +0 -585
- package/scripts/indexes.sql +0 -661
- package/scripts/migrate_v1.sql +0 -1225
- package/scripts/tables/001_accounts.sql +0 -51
- package/scripts/tables/002_users.sql +0 -69
- package/scripts/tables/003_people.sql +0 -70
- package/scripts/tables/004_tags.sql +0 -62
- package/scripts/tables/005_credentials.sql +0 -79
- package/scripts/tables/006_agents.sql +0 -70
- package/scripts/tables/007_tools.sql +0 -68
- package/scripts/tables/008_channels.sql +0 -75
- package/scripts/tables/009_leads.sql +0 -85
- package/scripts/tables/010_missions.sql +0 -62
- package/scripts/tables/011_objectives.sql +0 -68
- package/scripts/tables/012_conversations.sql +0 -80
- package/scripts/tables/013_objectives_tools.sql +0 -66
- package/scripts/tables/014_messages.sql +0 -78
- package/scripts/tables/015_companies.sql +0 -77
- package/scripts/tables/016_conversations_tags.sql +0 -64
- package/scripts/tables/017_leads_tags.sql +0 -64
- package/scripts/triggers.sql +0 -497
- package/src/modules/channels/properties.js +0 -150
- package/src/modules/companies/index.js +0 -10
- package/src/modules/companies/properties.js +0 -168
- package/src/modules/conversations_tags/index.js +0 -10
- package/src/modules/conversations_tags/properties.js +0 -84
- package/src/modules/credentials/index.js +0 -10
- package/src/modules/credentials/properties.js +0 -271
- package/src/modules/leads/index.js +0 -10
- package/src/modules/leads/properties.js +0 -193
- package/src/modules/leads_tags/index.js +0 -10
- package/src/modules/leads_tags/properties.js +0 -84
- package/src/modules/messages/index.js +0 -10
- package/src/modules/messages/properties.js +0 -152
- package/src/modules/missions/index.js +0 -10
- package/src/modules/missions/properties.js +0 -101
- package/src/modules/objectives_tools/index.js +0 -10
- package/src/modules/objectives_tools/properties.js +0 -109
- package/src/modules/people/index.js +0 -10
- package/src/modules/people/properties.js +0 -161
- package/src/modules/tags/index.js +0 -10
- package/src/modules/tools/index.js +0 -10
- package/src/modules/tools/properties.js +0 -121
package/scripts/triggers.sql
DELETED
|
@@ -1,497 +0,0 @@
|
|
|
1
|
-
-- ============================================================================
|
|
2
|
-
-- Script: triggers.sql
|
|
3
|
-
-- Descrição: Triggers e functions para automação do banco GAgents
|
|
4
|
-
-- Versão: 1.0
|
|
5
|
-
-- Dependências: Todas as tabelas, indexes.sql e constraints.sql
|
|
6
|
-
-- Autor: Sistema de Migração GAgents
|
|
7
|
-
-- Data: 2025-09-20
|
|
8
|
-
-- ============================================================================
|
|
9
|
-
|
|
10
|
-
-- Verificação de pré-requisitos
|
|
11
|
-
DO $$
|
|
12
|
-
BEGIN
|
|
13
|
-
-- Verificar versão PostgreSQL
|
|
14
|
-
IF current_setting('server_version_num')::integer < 140000 THEN
|
|
15
|
-
RAISE EXCEPTION 'PostgreSQL versão 14+ é obrigatória. Versão atual: %', version();
|
|
16
|
-
END IF;
|
|
17
|
-
|
|
18
|
-
-- Verificar se todas as tabelas existem
|
|
19
|
-
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'accounts') THEN
|
|
20
|
-
RAISE EXCEPTION 'Tabela accounts não encontrada. Execute tables.sql primeiro.';
|
|
21
|
-
END IF;
|
|
22
|
-
|
|
23
|
-
RAISE NOTICE '[%] Iniciando criação de triggers e functions', now();
|
|
24
|
-
END $$;
|
|
25
|
-
|
|
26
|
-
-- ============================================================================
|
|
27
|
-
-- SEÇÃO 1: FUNCTIONS UNIVERSAIS PARA AUTOMAÇÃO
|
|
28
|
-
-- ============================================================================
|
|
29
|
-
|
|
30
|
-
-- Function para atualização automática de datetime_alt
|
|
31
|
-
CREATE OR REPLACE FUNCTION update_datetime_alt()
|
|
32
|
-
RETURNS TRIGGER AS $$
|
|
33
|
-
BEGIN
|
|
34
|
-
NEW.datetime_alt = CURRENT_TIMESTAMP;
|
|
35
|
-
RETURN NEW;
|
|
36
|
-
END;
|
|
37
|
-
$$ LANGUAGE plpgsql;
|
|
38
|
-
|
|
39
|
-
COMMENT ON FUNCTION update_datetime_alt() IS 'Function universal para atualizar datetime_alt automaticamente';
|
|
40
|
-
|
|
41
|
-
-- Function para soft delete (exclusão lógica)
|
|
42
|
-
CREATE OR REPLACE FUNCTION soft_delete()
|
|
43
|
-
RETURNS TRIGGER AS $$
|
|
44
|
-
BEGIN
|
|
45
|
-
-- Executa UPDATE ao invés de DELETE físico
|
|
46
|
-
EXECUTE format('UPDATE %I SET deleted = TRUE, datetime_del = CURRENT_TIMESTAMP WHERE id = %s',
|
|
47
|
-
TG_TABLE_NAME, OLD.id);
|
|
48
|
-
RETURN NULL; -- Impede o DELETE físico
|
|
49
|
-
END;
|
|
50
|
-
$$ LANGUAGE plpgsql;
|
|
51
|
-
|
|
52
|
-
COMMENT ON FUNCTION soft_delete() IS 'Function para implementar exclusão lógica ao invés de DELETE físico';
|
|
53
|
-
|
|
54
|
-
-- ============================================================================
|
|
55
|
-
-- SEÇÃO 2: TABELA DE AUDITORIA
|
|
56
|
-
-- ============================================================================
|
|
57
|
-
|
|
58
|
-
-- Criar tabela para auditoria se não existir
|
|
59
|
-
CREATE TABLE IF NOT EXISTS audit_log (
|
|
60
|
-
id SERIAL PRIMARY KEY,
|
|
61
|
-
table_name VARCHAR(100) NOT NULL,
|
|
62
|
-
operation_type VARCHAR(10) NOT NULL,
|
|
63
|
-
record_id INTEGER NOT NULL,
|
|
64
|
-
old_values JSONB,
|
|
65
|
-
new_values JSONB,
|
|
66
|
-
changed_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
67
|
-
changed_by VARCHAR(100) DEFAULT current_user,
|
|
68
|
-
|
|
69
|
-
-- Constraints
|
|
70
|
-
CONSTRAINT audit_log_operation_valid CHECK (operation_type IN ('INSERT', 'UPDATE', 'DELETE'))
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
-- Índices para tabela de auditoria
|
|
74
|
-
CREATE INDEX IF NOT EXISTS idx_audit_log_table_name ON audit_log(table_name);
|
|
75
|
-
CREATE INDEX IF NOT EXISTS idx_audit_log_operation_type ON audit_log(operation_type);
|
|
76
|
-
CREATE INDEX IF NOT EXISTS idx_audit_log_record_id ON audit_log(record_id);
|
|
77
|
-
CREATE INDEX IF NOT EXISTS idx_audit_log_changed_at ON audit_log(changed_at);
|
|
78
|
-
|
|
79
|
-
COMMENT ON TABLE audit_log IS 'Tabela para auditoria de mudanças no sistema';
|
|
80
|
-
|
|
81
|
-
-- ============================================================================
|
|
82
|
-
-- SEÇÃO 3: FUNCTION PARA AUDITORIA
|
|
83
|
-
-- ============================================================================
|
|
84
|
-
|
|
85
|
-
-- Function para auditoria de mudanças
|
|
86
|
-
CREATE OR REPLACE FUNCTION audit_changes()
|
|
87
|
-
RETURNS TRIGGER AS $$
|
|
88
|
-
DECLARE
|
|
89
|
-
operation_type VARCHAR(10);
|
|
90
|
-
table_name VARCHAR(100);
|
|
91
|
-
BEGIN
|
|
92
|
-
operation_type := TG_OP;
|
|
93
|
-
table_name := TG_TABLE_NAME;
|
|
94
|
-
|
|
95
|
-
-- Registrar operação em tabela de auditoria
|
|
96
|
-
INSERT INTO audit_log (
|
|
97
|
-
table_name,
|
|
98
|
-
operation_type,
|
|
99
|
-
record_id,
|
|
100
|
-
old_values,
|
|
101
|
-
new_values,
|
|
102
|
-
changed_at,
|
|
103
|
-
changed_by
|
|
104
|
-
) VALUES (
|
|
105
|
-
table_name,
|
|
106
|
-
operation_type,
|
|
107
|
-
COALESCE(NEW.id, OLD.id),
|
|
108
|
-
CASE WHEN operation_type != 'INSERT' THEN row_to_json(OLD) END,
|
|
109
|
-
CASE WHEN operation_type != 'DELETE' THEN row_to_json(NEW) END,
|
|
110
|
-
CURRENT_TIMESTAMP,
|
|
111
|
-
current_user
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
RETURN COALESCE(NEW, OLD);
|
|
115
|
-
END;
|
|
116
|
-
$$ LANGUAGE plpgsql;
|
|
117
|
-
|
|
118
|
-
COMMENT ON FUNCTION audit_changes() IS 'Function para registrar mudanças críticas em tabela de auditoria';
|
|
119
|
-
|
|
120
|
-
-- ============================================================================
|
|
121
|
-
-- SEÇÃO 4: FUNCTION PARA CONTROLE DE CONVERSAS
|
|
122
|
-
-- ============================================================================
|
|
123
|
-
|
|
124
|
-
-- Function para atualizar última mensagem da conversa
|
|
125
|
-
CREATE OR REPLACE FUNCTION update_conversation_last_message()
|
|
126
|
-
RETURNS TRIGGER AS $$
|
|
127
|
-
BEGIN
|
|
128
|
-
-- Atualizar conversations.id_last_message quando nova mensagem é inserida
|
|
129
|
-
UPDATE conversations
|
|
130
|
-
SET id_last_message = NEW.id,
|
|
131
|
-
last_message_at = NEW.datetime_add
|
|
132
|
-
WHERE id = NEW.id_conversation;
|
|
133
|
-
|
|
134
|
-
RETURN NEW;
|
|
135
|
-
END;
|
|
136
|
-
$$ LANGUAGE plpgsql;
|
|
137
|
-
|
|
138
|
-
COMMENT ON FUNCTION update_conversation_last_message() IS 'Function para atualizar última mensagem em conversations automaticamente';
|
|
139
|
-
|
|
140
|
-
-- ============================================================================
|
|
141
|
-
-- SEÇÃO 5: FUNCTION PARA VALIDAÇÃO DE STATUS
|
|
142
|
-
-- ============================================================================
|
|
143
|
-
|
|
144
|
-
-- Function para validar mudanças de status
|
|
145
|
-
CREATE OR REPLACE FUNCTION validate_status_transition()
|
|
146
|
-
RETURNS TRIGGER AS $$
|
|
147
|
-
BEGIN
|
|
148
|
-
-- Validar transições de status em conversations
|
|
149
|
-
IF TG_TABLE_NAME = 'conversations' THEN
|
|
150
|
-
-- Não permitir mudança de 'closed' para 'open' diretamente
|
|
151
|
-
IF OLD.status = 'closed' AND NEW.status = 'open' THEN
|
|
152
|
-
RAISE EXCEPTION 'Não é possível reabrir conversa fechada diretamente. Use função específica.';
|
|
153
|
-
END IF;
|
|
154
|
-
|
|
155
|
-
-- Validar transições válidas
|
|
156
|
-
IF OLD.status = 'pending' AND NEW.status NOT IN ('open', 'closed') THEN
|
|
157
|
-
RAISE EXCEPTION 'Transição de status inválida: % -> %', OLD.status, NEW.status;
|
|
158
|
-
END IF;
|
|
159
|
-
END IF;
|
|
160
|
-
|
|
161
|
-
RETURN NEW;
|
|
162
|
-
END;
|
|
163
|
-
$$ LANGUAGE plpgsql;
|
|
164
|
-
|
|
165
|
-
COMMENT ON FUNCTION validate_status_transition() IS 'Function para garantir transições válidas de status';
|
|
166
|
-
|
|
167
|
-
-- ============================================================================
|
|
168
|
-
-- SEÇÃO 6: TRIGGERS PARA ATUALIZAÇÃO AUTOMÁTICA DE datetime_alt
|
|
169
|
-
-- ============================================================================
|
|
170
|
-
|
|
171
|
-
-- Triggers para todas as 17 tabelas
|
|
172
|
-
CREATE TRIGGER trigger_accounts_update_datetime
|
|
173
|
-
BEFORE UPDATE ON accounts
|
|
174
|
-
FOR EACH ROW
|
|
175
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
176
|
-
|
|
177
|
-
CREATE TRIGGER trigger_users_update_datetime
|
|
178
|
-
BEFORE UPDATE ON users
|
|
179
|
-
FOR EACH ROW
|
|
180
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
181
|
-
|
|
182
|
-
CREATE TRIGGER trigger_people_update_datetime
|
|
183
|
-
BEFORE UPDATE ON people
|
|
184
|
-
FOR EACH ROW
|
|
185
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
186
|
-
|
|
187
|
-
CREATE TRIGGER trigger_tags_update_datetime
|
|
188
|
-
BEFORE UPDATE ON tags
|
|
189
|
-
FOR EACH ROW
|
|
190
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
191
|
-
|
|
192
|
-
CREATE TRIGGER trigger_credentials_update_datetime
|
|
193
|
-
BEFORE UPDATE ON credentials
|
|
194
|
-
FOR EACH ROW
|
|
195
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
196
|
-
|
|
197
|
-
CREATE TRIGGER trigger_agents_update_datetime
|
|
198
|
-
BEFORE UPDATE ON agents
|
|
199
|
-
FOR EACH ROW
|
|
200
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
201
|
-
|
|
202
|
-
CREATE TRIGGER trigger_tools_update_datetime
|
|
203
|
-
BEFORE UPDATE ON tools
|
|
204
|
-
FOR EACH ROW
|
|
205
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
206
|
-
|
|
207
|
-
CREATE TRIGGER trigger_channels_update_datetime
|
|
208
|
-
BEFORE UPDATE ON channels
|
|
209
|
-
FOR EACH ROW
|
|
210
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
211
|
-
|
|
212
|
-
CREATE TRIGGER trigger_leads_update_datetime
|
|
213
|
-
BEFORE UPDATE ON leads
|
|
214
|
-
FOR EACH ROW
|
|
215
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
216
|
-
|
|
217
|
-
CREATE TRIGGER trigger_missions_update_datetime
|
|
218
|
-
BEFORE UPDATE ON missions
|
|
219
|
-
FOR EACH ROW
|
|
220
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
221
|
-
|
|
222
|
-
CREATE TRIGGER trigger_objectives_update_datetime
|
|
223
|
-
BEFORE UPDATE ON objectives
|
|
224
|
-
FOR EACH ROW
|
|
225
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
226
|
-
|
|
227
|
-
CREATE TRIGGER trigger_conversations_update_datetime
|
|
228
|
-
BEFORE UPDATE ON conversations
|
|
229
|
-
FOR EACH ROW
|
|
230
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
231
|
-
|
|
232
|
-
CREATE TRIGGER trigger_objectives_tools_update_datetime
|
|
233
|
-
BEFORE UPDATE ON objectives_tools
|
|
234
|
-
FOR EACH ROW
|
|
235
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
236
|
-
|
|
237
|
-
CREATE TRIGGER trigger_messages_update_datetime
|
|
238
|
-
BEFORE UPDATE ON messages
|
|
239
|
-
FOR EACH ROW
|
|
240
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
241
|
-
|
|
242
|
-
CREATE TRIGGER trigger_companies_update_datetime
|
|
243
|
-
BEFORE UPDATE ON companies
|
|
244
|
-
FOR EACH ROW
|
|
245
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
246
|
-
|
|
247
|
-
CREATE TRIGGER trigger_conversations_tags_update_datetime
|
|
248
|
-
BEFORE UPDATE ON conversations_tags
|
|
249
|
-
FOR EACH ROW
|
|
250
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
251
|
-
|
|
252
|
-
CREATE TRIGGER trigger_leads_tags_update_datetime
|
|
253
|
-
BEFORE UPDATE ON leads_tags
|
|
254
|
-
FOR EACH ROW
|
|
255
|
-
EXECUTE FUNCTION update_datetime_alt();
|
|
256
|
-
|
|
257
|
-
-- ============================================================================
|
|
258
|
-
-- SEÇÃO 7: TRIGGERS DE AUDITORIA PARA TABELAS CRÍTICAS
|
|
259
|
-
-- ============================================================================
|
|
260
|
-
|
|
261
|
-
-- Auditoria para conversations
|
|
262
|
-
CREATE TRIGGER trigger_conversations_audit
|
|
263
|
-
AFTER INSERT OR UPDATE OR DELETE ON conversations
|
|
264
|
-
FOR EACH ROW
|
|
265
|
-
EXECUTE FUNCTION audit_changes();
|
|
266
|
-
|
|
267
|
-
-- Auditoria para messages
|
|
268
|
-
CREATE TRIGGER trigger_messages_audit
|
|
269
|
-
AFTER INSERT OR UPDATE OR DELETE ON messages
|
|
270
|
-
FOR EACH ROW
|
|
271
|
-
EXECUTE FUNCTION audit_changes();
|
|
272
|
-
|
|
273
|
-
-- Auditoria para leads
|
|
274
|
-
CREATE TRIGGER trigger_leads_audit
|
|
275
|
-
AFTER INSERT OR UPDATE OR DELETE ON leads
|
|
276
|
-
FOR EACH ROW
|
|
277
|
-
EXECUTE FUNCTION audit_changes();
|
|
278
|
-
|
|
279
|
-
-- Auditoria para users
|
|
280
|
-
CREATE TRIGGER trigger_users_audit
|
|
281
|
-
AFTER INSERT OR UPDATE OR DELETE ON users
|
|
282
|
-
FOR EACH ROW
|
|
283
|
-
EXECUTE FUNCTION audit_changes();
|
|
284
|
-
|
|
285
|
-
-- Auditoria para accounts
|
|
286
|
-
CREATE TRIGGER trigger_accounts_audit
|
|
287
|
-
AFTER INSERT OR UPDATE OR DELETE ON accounts
|
|
288
|
-
FOR EACH ROW
|
|
289
|
-
EXECUTE FUNCTION audit_changes();
|
|
290
|
-
|
|
291
|
-
-- ============================================================================
|
|
292
|
-
-- SEÇÃO 8: TRIGGER PARA CONTROLE DE CONVERSAS
|
|
293
|
-
-- ============================================================================
|
|
294
|
-
|
|
295
|
-
-- Trigger para messages - atualizar última mensagem da conversa
|
|
296
|
-
CREATE TRIGGER trigger_messages_update_conversation
|
|
297
|
-
AFTER INSERT ON messages
|
|
298
|
-
FOR EACH ROW
|
|
299
|
-
EXECUTE FUNCTION update_conversation_last_message();
|
|
300
|
-
|
|
301
|
-
-- ============================================================================
|
|
302
|
-
-- SEÇÃO 9: TRIGGER PARA VALIDAÇÃO DE STATUS
|
|
303
|
-
-- ============================================================================
|
|
304
|
-
|
|
305
|
-
-- Trigger para conversations - validar mudanças de status
|
|
306
|
-
CREATE TRIGGER trigger_conversations_validate_status
|
|
307
|
-
BEFORE UPDATE ON conversations
|
|
308
|
-
FOR EACH ROW
|
|
309
|
-
WHEN (OLD.status IS DISTINCT FROM NEW.status)
|
|
310
|
-
EXECUTE FUNCTION validate_status_transition();
|
|
311
|
-
|
|
312
|
-
-- ============================================================================
|
|
313
|
-
-- SEÇÃO 10: FUNCTIONS PARA LIMPEZA E MANUTENÇÃO
|
|
314
|
-
-- ============================================================================
|
|
315
|
-
|
|
316
|
-
-- Function para limpeza de dados antigos
|
|
317
|
-
CREATE OR REPLACE FUNCTION cleanup_old_data()
|
|
318
|
-
RETURNS void AS $$
|
|
319
|
-
BEGIN
|
|
320
|
-
-- Arquivar conversas antigas (mais de 1 ano e fechadas)
|
|
321
|
-
UPDATE conversations
|
|
322
|
-
SET deleted = TRUE,
|
|
323
|
-
datetime_del = CURRENT_TIMESTAMP
|
|
324
|
-
WHERE status = 'closed'
|
|
325
|
-
AND datetime_add < CURRENT_DATE - INTERVAL '1 year'
|
|
326
|
-
AND deleted = FALSE;
|
|
327
|
-
|
|
328
|
-
-- Arquivar mensagens órfãs (sem conversa ativa)
|
|
329
|
-
UPDATE messages
|
|
330
|
-
SET deleted = TRUE,
|
|
331
|
-
datetime_del = CURRENT_TIMESTAMP
|
|
332
|
-
WHERE id_conversation NOT IN (SELECT id FROM conversations WHERE deleted = FALSE)
|
|
333
|
-
AND deleted = FALSE;
|
|
334
|
-
|
|
335
|
-
-- Limpar logs de auditoria antigos (mais de 2 anos)
|
|
336
|
-
DELETE FROM audit_log
|
|
337
|
-
WHERE changed_at < CURRENT_DATE - INTERVAL '2 years';
|
|
338
|
-
|
|
339
|
-
RAISE NOTICE '[%] Limpeza automática executada - conversas arquivadas, mensagens órfãs removidas, logs antigos limpos', CURRENT_TIMESTAMP;
|
|
340
|
-
END;
|
|
341
|
-
$$ LANGUAGE plpgsql;
|
|
342
|
-
|
|
343
|
-
COMMENT ON FUNCTION cleanup_old_data() IS 'Function para arquivar dados antigos e manter performance do banco';
|
|
344
|
-
|
|
345
|
-
-- ============================================================================
|
|
346
|
-
-- SEÇÃO 11: FUNCTIONS UTILITÁRIAS
|
|
347
|
-
-- ============================================================================
|
|
348
|
-
|
|
349
|
-
-- Function para reativar registro deletado
|
|
350
|
-
CREATE OR REPLACE FUNCTION undelete_record(table_name VARCHAR, record_id INTEGER)
|
|
351
|
-
RETURNS void AS $$
|
|
352
|
-
BEGIN
|
|
353
|
-
EXECUTE format('UPDATE %I SET deleted = FALSE, datetime_del = NULL WHERE id = %s',
|
|
354
|
-
table_name, record_id);
|
|
355
|
-
|
|
356
|
-
RAISE NOTICE '[%] Registro reativado: %s.id = %', now(), table_name, record_id;
|
|
357
|
-
END;
|
|
358
|
-
$$ LANGUAGE plpgsql;
|
|
359
|
-
|
|
360
|
-
COMMENT ON FUNCTION undelete_record(VARCHAR, INTEGER) IS 'Function para reativar registros com soft delete';
|
|
361
|
-
|
|
362
|
-
-- Function para estatísticas gerais de uma conta
|
|
363
|
-
CREATE OR REPLACE FUNCTION get_account_stats(account_id INTEGER)
|
|
364
|
-
RETURNS TABLE(
|
|
365
|
-
total_conversations INTEGER,
|
|
366
|
-
total_messages INTEGER,
|
|
367
|
-
total_leads INTEGER,
|
|
368
|
-
active_agents INTEGER,
|
|
369
|
-
active_users INTEGER,
|
|
370
|
-
stats_generated_at TIMESTAMP WITH TIME ZONE
|
|
371
|
-
) AS $$
|
|
372
|
-
BEGIN
|
|
373
|
-
RETURN QUERY
|
|
374
|
-
SELECT
|
|
375
|
-
(SELECT COUNT(*)::INTEGER FROM conversations WHERE id_account = account_id AND deleted = FALSE) as total_conversations,
|
|
376
|
-
(SELECT COUNT(*)::INTEGER FROM messages WHERE id_account = account_id AND deleted = FALSE) as total_messages,
|
|
377
|
-
(SELECT COUNT(*)::INTEGER FROM leads WHERE id_account = account_id AND deleted = FALSE) as total_leads,
|
|
378
|
-
(SELECT COUNT(*)::INTEGER FROM agents WHERE id_account = account_id AND deleted = FALSE) as active_agents,
|
|
379
|
-
(SELECT COUNT(*)::INTEGER FROM users WHERE id_account = account_id AND deleted = FALSE) as active_users,
|
|
380
|
-
CURRENT_TIMESTAMP as stats_generated_at;
|
|
381
|
-
END;
|
|
382
|
-
$$ LANGUAGE plpgsql;
|
|
383
|
-
|
|
384
|
-
COMMENT ON FUNCTION get_account_stats(INTEGER) IS 'Function para obter estatísticas resumidas de uma conta';
|
|
385
|
-
|
|
386
|
-
-- Function para reabrir conversa fechada (com validação)
|
|
387
|
-
CREATE OR REPLACE FUNCTION reopen_conversation(conversation_id INTEGER, reopened_by_user_id INTEGER)
|
|
388
|
-
RETURNS void AS $$
|
|
389
|
-
DECLARE
|
|
390
|
-
conv_status VARCHAR(20);
|
|
391
|
-
conv_account INTEGER;
|
|
392
|
-
BEGIN
|
|
393
|
-
-- Verificar se conversa existe e está fechada
|
|
394
|
-
SELECT status, id_account INTO conv_status, conv_account
|
|
395
|
-
FROM conversations
|
|
396
|
-
WHERE id = conversation_id AND deleted = FALSE;
|
|
397
|
-
|
|
398
|
-
IF NOT FOUND THEN
|
|
399
|
-
RAISE EXCEPTION 'Conversa não encontrada ou já foi deletada';
|
|
400
|
-
END IF;
|
|
401
|
-
|
|
402
|
-
IF conv_status != 'closed' THEN
|
|
403
|
-
RAISE EXCEPTION 'Conversa não está fechada. Status atual: %', conv_status;
|
|
404
|
-
END IF;
|
|
405
|
-
|
|
406
|
-
-- Reabrir conversa
|
|
407
|
-
UPDATE conversations
|
|
408
|
-
SET status = 'open',
|
|
409
|
-
datetime_alt = CURRENT_TIMESTAMP
|
|
410
|
-
WHERE id = conversation_id;
|
|
411
|
-
|
|
412
|
-
-- Registrar na auditoria
|
|
413
|
-
INSERT INTO audit_log (table_name, operation_type, record_id, new_values, changed_at, changed_by)
|
|
414
|
-
VALUES ('conversations', 'REOPEN', conversation_id,
|
|
415
|
-
json_build_object('status', 'open', 'reopened_by', reopened_by_user_id),
|
|
416
|
-
CURRENT_TIMESTAMP, current_user);
|
|
417
|
-
|
|
418
|
-
RAISE NOTICE '[%] Conversa % reaberta por usuário %', now(), conversation_id, reopened_by_user_id;
|
|
419
|
-
END;
|
|
420
|
-
$$ LANGUAGE plpgsql;
|
|
421
|
-
|
|
422
|
-
COMMENT ON FUNCTION reopen_conversation(INTEGER, INTEGER) IS 'Function para reabrir conversa fechada com validação e auditoria';
|
|
423
|
-
|
|
424
|
-
-- Function para backup de dados críticos
|
|
425
|
-
CREATE OR REPLACE FUNCTION backup_critical_data(backup_date DATE DEFAULT CURRENT_DATE)
|
|
426
|
-
RETURNS TABLE(
|
|
427
|
-
table_name VARCHAR,
|
|
428
|
-
record_count BIGINT,
|
|
429
|
-
backup_status VARCHAR
|
|
430
|
-
) AS $$
|
|
431
|
-
BEGIN
|
|
432
|
-
-- Esta function seria expandida para fazer backup real
|
|
433
|
-
-- Por enquanto, apenas retorna contagens
|
|
434
|
-
RETURN QUERY
|
|
435
|
-
SELECT 'accounts'::VARCHAR, COUNT(*), 'counted'::VARCHAR FROM accounts WHERE deleted = FALSE
|
|
436
|
-
UNION ALL
|
|
437
|
-
SELECT 'conversations'::VARCHAR, COUNT(*), 'counted'::VARCHAR FROM conversations WHERE deleted = FALSE
|
|
438
|
-
UNION ALL
|
|
439
|
-
SELECT 'messages'::VARCHAR, COUNT(*), 'counted'::VARCHAR FROM messages WHERE deleted = FALSE
|
|
440
|
-
UNION ALL
|
|
441
|
-
SELECT 'leads'::VARCHAR, COUNT(*), 'counted'::VARCHAR FROM leads WHERE deleted = FALSE;
|
|
442
|
-
|
|
443
|
-
RAISE NOTICE '[%] Backup de dados críticos contabilizado para %', now(), backup_date;
|
|
444
|
-
END;
|
|
445
|
-
$$ LANGUAGE plpgsql;
|
|
446
|
-
|
|
447
|
-
COMMENT ON FUNCTION backup_critical_data(DATE) IS 'Function para contabilizar dados críticos para backup';
|
|
448
|
-
|
|
449
|
-
-- ============================================================================
|
|
450
|
-
-- VERIFICAÇÃO PÓS-EXECUÇÃO E LOGGING
|
|
451
|
-
-- ============================================================================
|
|
452
|
-
|
|
453
|
-
-- Verificação final
|
|
454
|
-
DO $$
|
|
455
|
-
DECLARE
|
|
456
|
-
function_count INTEGER;
|
|
457
|
-
trigger_count INTEGER;
|
|
458
|
-
BEGIN
|
|
459
|
-
-- Contar functions criadas
|
|
460
|
-
SELECT COUNT(*) INTO function_count
|
|
461
|
-
FROM information_schema.routines
|
|
462
|
-
WHERE routine_schema = 'public'
|
|
463
|
-
AND routine_name IN (
|
|
464
|
-
'update_datetime_alt', 'soft_delete', 'audit_changes',
|
|
465
|
-
'update_conversation_last_message', 'validate_status_transition',
|
|
466
|
-
'cleanup_old_data', 'undelete_record', 'get_account_stats',
|
|
467
|
-
'reopen_conversation', 'backup_critical_data'
|
|
468
|
-
);
|
|
469
|
-
|
|
470
|
-
-- Contar triggers criados
|
|
471
|
-
SELECT COUNT(*) INTO trigger_count
|
|
472
|
-
FROM information_schema.triggers
|
|
473
|
-
WHERE trigger_schema = 'public'
|
|
474
|
-
AND trigger_name LIKE 'trigger_%';
|
|
475
|
-
|
|
476
|
-
-- Verificar se tabela de auditoria existe
|
|
477
|
-
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'audit_log') THEN
|
|
478
|
-
RAISE EXCEPTION 'Falha na criação da tabela audit_log';
|
|
479
|
-
END IF;
|
|
480
|
-
|
|
481
|
-
RAISE NOTICE '[%] ============================================================================', now();
|
|
482
|
-
RAISE NOTICE '[%] TRIGGERS E FUNCTIONS CRIADOS COM SUCESSO:', now();
|
|
483
|
-
RAISE NOTICE '[%] - % functions implementadas', now(), function_count;
|
|
484
|
-
RAISE NOTICE '[%] - % triggers criados', now(), trigger_count;
|
|
485
|
-
RAISE NOTICE '[%] - Tabela audit_log criada para auditoria', now();
|
|
486
|
-
RAISE NOTICE '[%] - Sistema de automação e auditoria ativo', now();
|
|
487
|
-
RAISE NOTICE '[%] ============================================================================', now();
|
|
488
|
-
|
|
489
|
-
IF function_count < 10 THEN
|
|
490
|
-
RAISE WARNING 'Número de functions menor que esperado. Verificar implementação.';
|
|
491
|
-
END IF;
|
|
492
|
-
|
|
493
|
-
IF trigger_count < 20 THEN
|
|
494
|
-
RAISE WARNING 'Número de triggers menor que esperado. Verificar implementação.';
|
|
495
|
-
END IF;
|
|
496
|
-
|
|
497
|
-
END $$;
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
export const properties = {
|
|
2
|
-
id: {
|
|
3
|
-
type: "number",
|
|
4
|
-
filterable: true,
|
|
5
|
-
unique: true,
|
|
6
|
-
autoIncrement: true,
|
|
7
|
-
index: true
|
|
8
|
-
},
|
|
9
|
-
deleted: {
|
|
10
|
-
type: "boolean",
|
|
11
|
-
default: false,
|
|
12
|
-
filterable: true
|
|
13
|
-
},
|
|
14
|
-
datetime_add: {
|
|
15
|
-
type: "date",
|
|
16
|
-
filterable: true,
|
|
17
|
-
updatable: false
|
|
18
|
-
},
|
|
19
|
-
datetime_alt: {
|
|
20
|
-
type: "date",
|
|
21
|
-
filterable: true,
|
|
22
|
-
updatable: true
|
|
23
|
-
},
|
|
24
|
-
datetime_del: {
|
|
25
|
-
type: "date",
|
|
26
|
-
filterable: true
|
|
27
|
-
},
|
|
28
|
-
id_account: {
|
|
29
|
-
type: "number",
|
|
30
|
-
required: true,
|
|
31
|
-
updatable: false,
|
|
32
|
-
filterable: true,
|
|
33
|
-
reference: {
|
|
34
|
-
module: "accounts",
|
|
35
|
-
label: "name",
|
|
36
|
-
value: "id",
|
|
37
|
-
disabled: true
|
|
38
|
-
},
|
|
39
|
-
interface: {
|
|
40
|
-
label: {
|
|
41
|
-
"pt-br": "Conta",
|
|
42
|
-
"en": "Account"
|
|
43
|
-
},
|
|
44
|
-
component: "select",
|
|
45
|
-
disabled: true
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
title: {
|
|
49
|
-
type: "string",
|
|
50
|
-
required: true,
|
|
51
|
-
filterable: true,
|
|
52
|
-
searchable: true,
|
|
53
|
-
validation: {
|
|
54
|
-
maxLength: 255
|
|
55
|
-
},
|
|
56
|
-
interface: {
|
|
57
|
-
label: {
|
|
58
|
-
"pt-br": "Título",
|
|
59
|
-
"en": "Title"
|
|
60
|
-
},
|
|
61
|
-
component: "string",
|
|
62
|
-
placeholder: {
|
|
63
|
-
"pt-br": "Dê um título curto e descritivo",
|
|
64
|
-
"en": "Give a short and descriptive title"
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
provider: {
|
|
69
|
-
type: "string",
|
|
70
|
-
required: true,
|
|
71
|
-
filterable: true,
|
|
72
|
-
default: "web-chat",
|
|
73
|
-
options: [
|
|
74
|
-
{ value: "web-chat", label: { "pt-br": "Web Chat", "en": "Web Chat" } },
|
|
75
|
-
{ value: "whatsap-oficial", label: { "pt-br": "WhatsApp (API Oficial)", "en": "WhatsApp (API Oficial)" } },
|
|
76
|
-
{ value: "z-api", label: { "pt-br": "WhatsApp (Z-API)", "en": "WhatsApp (Z-API)" } },
|
|
77
|
-
{ value: "evolution-api", label: { "pt-br": "WhatsApp (Evolution API)", "en": "WhatsApp (Evolution API)" } },
|
|
78
|
-
{ value: "telegram", label: { "pt-br": "Telegram", "en": "Telegram" } },
|
|
79
|
-
{ value: "facebook", label: { "pt-br": "Facebook", "en": "Facebook" } },
|
|
80
|
-
{ value: "instagram", label: { "pt-br": "Instagram", "en": "Instagram" } }
|
|
81
|
-
],
|
|
82
|
-
interface: {
|
|
83
|
-
component: "select",
|
|
84
|
-
label: {
|
|
85
|
-
"pt-br": "Provedor",
|
|
86
|
-
"en": "Provider"
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
url: {
|
|
91
|
-
type: "string",
|
|
92
|
-
interface: {
|
|
93
|
-
label: {
|
|
94
|
-
"pt-br": "URL",
|
|
95
|
-
"en": "URL"
|
|
96
|
-
},
|
|
97
|
-
component: "string",
|
|
98
|
-
placeholder: {
|
|
99
|
-
"pt-br": "URL do canal",
|
|
100
|
-
"en": "Channel URL"
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
active: {
|
|
105
|
-
type: "boolean",
|
|
106
|
-
default: true,
|
|
107
|
-
filterable: true,
|
|
108
|
-
interface: {
|
|
109
|
-
label: {
|
|
110
|
-
"pt-br": "Ativo",
|
|
111
|
-
"en": "Active"
|
|
112
|
-
},
|
|
113
|
-
component: "checkbox"
|
|
114
|
-
}
|
|
115
|
-
},
|
|
116
|
-
id_credential: {
|
|
117
|
-
type: "number",
|
|
118
|
-
required: false,
|
|
119
|
-
reference: {
|
|
120
|
-
module: "credentials",
|
|
121
|
-
label: "title",
|
|
122
|
-
value: "id",
|
|
123
|
-
},
|
|
124
|
-
interface: {
|
|
125
|
-
label: {
|
|
126
|
-
"pt-br": "Credencial",
|
|
127
|
-
"en": "Credential"
|
|
128
|
-
},
|
|
129
|
-
component: "select",
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
handle: {
|
|
133
|
-
type: "string",
|
|
134
|
-
filterable: true,
|
|
135
|
-
validation: {
|
|
136
|
-
maxLength: 255
|
|
137
|
-
},
|
|
138
|
-
interface: {
|
|
139
|
-
label: {
|
|
140
|
-
"pt-br": "Identificador do canal",
|
|
141
|
-
"en": "Channel identifier"
|
|
142
|
-
},
|
|
143
|
-
component: "string",
|
|
144
|
-
placeholder: {
|
|
145
|
-
"pt-br": "Identificador único do canal (Ex: número do WhatsApp, ID do Telegram, @ do Instagram, etc.)",
|
|
146
|
-
"en": "Unique identifier of the channel (e.g., WhatsApp number, Telegram ID, Instagram @, etc.)"
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
},
|
|
150
|
-
};
|