diff --git a/.gitea/workflows/deploy-dev.yml b/.gitea/workflows/deploy-dev.yml index ed97a13..5774426 100644 --- a/.gitea/workflows/deploy-dev.yml +++ b/.gitea/workflows/deploy-dev.yml @@ -62,8 +62,40 @@ jobs: PGHOST="${PGHOST//[$'\t\r\n ']}" PGPORT="${PGPORT//[$'\t\r\n ']}" export PGHOST PGPORT - echo "Aplicando migrations..." - for f in $(ls "$DEPLOY_PATH/database/migrations/"*.sql | sort); do - echo "Aplicando: $(basename "$f")" + + echo "Inicializando controle de migrations..." + psql -v ON_ERROR_STOP=1 -f "$DEPLOY_PATH/database/migrations/000_schema_migrations.sql" + + echo "Aplicando migrations pendentes..." + for f in $(ls "$DEPLOY_PATH/database/migrations/"[0-9][0-9][0-9]_*.sql | sort); do + filename=$(basename "$f") + already_run=$(psql -tAc "SELECT COUNT(*) FROM schema_migrations WHERE filename = '$filename'") + if [ "$already_run" = "0" ]; then + echo "Aplicando: $filename" + psql -v ON_ERROR_STOP=1 -f "$f" + psql -c "INSERT INTO schema_migrations (filename) VALUES ('$filename') ON CONFLICT DO NOTHING" + echo "OK: $filename" + else + echo "Ignorando (ja aplicada): $filename" + fi + done + + - name: Executar seeds (dev) + shell: bash + env: + PGHOST: ${{ secrets.DB_HOST }} + PGPORT: ${{ secrets.DB_PORT }} + PGUSER: ${{ secrets.DB_USER }} + PGDATABASE: ${{ secrets.DB_NAME }} + PGPASSWORD: ${{ secrets.DB_PASSWORD }} + run: | + set -euo pipefail + PGHOST="${PGHOST//[$'\t\r\n ']}" + PGPORT="${PGPORT//[$'\t\r\n ']}" + export PGHOST PGPORT + + echo "Aplicando seeds de desenvolvimento..." + for f in $(ls "$DEPLOY_PATH/database/seeds/"*.sql | sort); do + echo "Seed: $(basename "$f")" psql -v ON_ERROR_STOP=1 -f "$f" done diff --git a/database/migrations/000_schema_migrations.sql b/database/migrations/000_schema_migrations.sql new file mode 100644 index 0000000..4025320 --- /dev/null +++ b/database/migrations/000_schema_migrations.sql @@ -0,0 +1,38 @@ +-- Migration 000: Controle de migrations aplicadas +-- Este arquivo roda sempre (antes do loop principal) e e idempotente. +-- Cria a tabela de rastreamento e marca todas as migrations existentes +-- como ja aplicadas para que nao re-executem em ambientes ja provisionados. + +CREATE TABLE IF NOT EXISTS schema_migrations ( + filename VARCHAR(255) PRIMARY KEY, + applied_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP +); + +INSERT INTO schema_migrations (filename) VALUES + ('001_auth.sql'), + ('002_area.sql'), + ('003_whatsapp.sql'), + ('004_whatsapp_templates.sql'), + ('005_whatsapp_assignment_queue.sql'), + ('006_whatsapp_triage_state.sql'), + ('007_agent_notes.sql'), + ('008_mensagens.sql'), + ('009_customer_contacts.sql'), + ('010_agenda_contatos.sql'), + ('011_whatsapp_awaiting_customer_reply.sql'), + ('012_whatsapp_template_workflow.sql'), + ('013_agent_presence_pause.sql'), + ('014_hr_decision_tree_keywords.sql'), + ('015_configurable_triage_flow.sql'), + ('016_triage_resolution_step.sql'), + ('017_bot_flow_builder.sql'), + ('018_bot_flow_close_node.sql'), + ('019_admin_audit_ai_contents.sql'), + ('020_whatsapp_template_category.sql'), + ('021_agenda_contact_channels.sql'), + ('022_whatsapp_config.sql'), + ('023_whatsapp_templates_hsm.sql'), + ('024_mensagens_media_columns.sql'), + ('025_mensagens_media_filename.sql'), + ('026_remove_fake_templates.sql') +ON CONFLICT DO NOTHING; diff --git a/database/migrations/004_whatsapp.sql b/database/migrations/003_whatsapp.sql similarity index 100% rename from database/migrations/004_whatsapp.sql rename to database/migrations/003_whatsapp.sql diff --git a/database/migrations/005_templates.sql b/database/migrations/004_whatsapp_templates.sql similarity index 100% rename from database/migrations/005_templates.sql rename to database/migrations/004_whatsapp_templates.sql diff --git a/database/migrations/006_whatsapp_assignment_queue.sql b/database/migrations/005_whatsapp_assignment_queue.sql similarity index 100% rename from database/migrations/006_whatsapp_assignment_queue.sql rename to database/migrations/005_whatsapp_assignment_queue.sql diff --git a/database/migrations/007_whatsapp_triage_state.sql b/database/migrations/006_whatsapp_triage_state.sql similarity index 100% rename from database/migrations/007_whatsapp_triage_state.sql rename to database/migrations/006_whatsapp_triage_state.sql diff --git a/database/migrations/008_agent_notes.sql b/database/migrations/007_agent_notes.sql similarity index 100% rename from database/migrations/008_agent_notes.sql rename to database/migrations/007_agent_notes.sql diff --git a/database/migrations/008_mensagens.sql b/database/migrations/008_mensagens.sql new file mode 100644 index 0000000..4110916 --- /dev/null +++ b/database/migrations/008_mensagens.sql @@ -0,0 +1,17 @@ +-- Migration 008: Tabela de mensagens do WhatsApp +CREATE TABLE IF NOT EXISTS mensagens ( + id SERIAL PRIMARY KEY, + wamid VARCHAR(255) NOT NULL, + chat_id VARCHAR(255) NOT NULL, + from_me BOOLEAN NOT NULL DEFAULT FALSE, + type VARCHAR(50) NOT NULL, + body TEXT, + sender_name VARCHAR(255), + status VARCHAR(50), + timestamp BIGINT NOT NULL, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + UNIQUE (wamid) +); + +CREATE INDEX IF NOT EXISTS idx_mensagens_chat_id ON mensagens (chat_id); +CREATE INDEX IF NOT EXISTS idx_mensagens_timestamp ON mensagens (timestamp DESC); diff --git a/database/migrations/012_whatsapp_awaiting_customer_reply.sql b/database/migrations/011_whatsapp_awaiting_customer_reply.sql similarity index 100% rename from database/migrations/012_whatsapp_awaiting_customer_reply.sql rename to database/migrations/011_whatsapp_awaiting_customer_reply.sql diff --git a/database/migrations/011_whatsapp_opening_templates.sql b/database/migrations/011_whatsapp_opening_templates.sql deleted file mode 100644 index 7fc3bc6..0000000 --- a/database/migrations/011_whatsapp_opening_templates.sql +++ /dev/null @@ -1,19 +0,0 @@ --- ============================================================ --- Migration 011: Templates de abertura ativa do WhatsApp --- Tabela: whatsapp_templates --- ============================================================ - -INSERT INTO whatsapp_templates (name, content) VALUES -('abertura_atendimento_padrao', 'Ola, {nome}. Tudo bem? Estamos entrando em contato pelo atendimento. Podemos seguir por aqui?'), -('abertura_retorno_contato', 'Ola, {nome}. Estamos retornando seu contato para dar continuidade ao seu atendimento.'), -('abertura_suporte', 'Ola, {nome}. Aqui e do suporte. Estamos entrando em contato para te ajudar com sua solicitacao.'), -('abertura_financeiro', 'Ola, {nome}. Aqui e do financeiro. Estamos entrando em contato para tratar de uma informacao importante sobre seu atendimento.'), -('abertura_comercial', 'Ola, {nome}. Aqui e do comercial. Estamos entrando em contato para conversar sobre sua solicitacao.'), -('abertura_confirmacao_dados', 'Ola, {nome}. Precisamos confirmar alguns dados para seguir com seu atendimento.'), -('abertura_contato_agendado', 'Ola, {nome}. Este contato foi combinado anteriormente e estamos disponiveis para seguir.'), -('abertura_pos_atendimento', 'Ola, {nome}. Estamos fazendo um acompanhamento sobre seu atendimento recente.'), -('abertura_aviso_importante', 'Ola, {nome}. Temos uma informacao importante para compartilhar com voce.'), -('abertura_contato_inicial', 'Ola, {nome}. Vamos iniciar seu atendimento por este canal.') -ON CONFLICT (name) DO UPDATE SET - content = EXCLUDED.content, - updated_at = CURRENT_TIMESTAMP; diff --git a/database/migrations/014_whatsapp_template_workflow.sql b/database/migrations/012_whatsapp_template_workflow.sql similarity index 100% rename from database/migrations/014_whatsapp_template_workflow.sql rename to database/migrations/012_whatsapp_template_workflow.sql diff --git a/database/migrations/015_agent_presence_pause.sql b/database/migrations/013_agent_presence_pause.sql similarity index 100% rename from database/migrations/015_agent_presence_pause.sql rename to database/migrations/013_agent_presence_pause.sql diff --git a/database/migrations/016_hr_decision_tree_keywords.sql b/database/migrations/014_hr_decision_tree_keywords.sql similarity index 100% rename from database/migrations/016_hr_decision_tree_keywords.sql rename to database/migrations/014_hr_decision_tree_keywords.sql diff --git a/database/migrations/017_configurable_triage_flow.sql b/database/migrations/015_configurable_triage_flow.sql similarity index 94% rename from database/migrations/017_configurable_triage_flow.sql rename to database/migrations/015_configurable_triage_flow.sql index 6f974fb..04cc0c1 100644 --- a/database/migrations/017_configurable_triage_flow.sql +++ b/database/migrations/015_configurable_triage_flow.sql @@ -1,5 +1,5 @@ -- ============================================================ --- Migration 017: Fluxo configuravel de triagem do Agente Virtual Sothis +-- Migration 015: Fluxo configuravel de triagem do Agente Virtual Sothis -- Tabelas: -- bot_triage_flows -- bot_triage_audiences @@ -29,7 +29,8 @@ CREATE TABLE IF NOT EXISTS bot_triage_audiences ( sort_order INTEGER NOT NULL DEFAULT 1, active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP + updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + UNIQUE (flow_id, label) ); CREATE TABLE IF NOT EXISTS bot_triage_intents ( @@ -41,7 +42,8 @@ CREATE TABLE IF NOT EXISTS bot_triage_intents ( sort_order INTEGER NOT NULL DEFAULT 1, active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP + updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + UNIQUE (audience_id, label) ); ALTER TABLE whatsapp_chat_atribuicoes @@ -114,7 +116,7 @@ JOIN ( ('Sou ex-colaborador', 'ex colaborador, ex-colaborador, rescisao, fgts, informe de rendimentos, desligamento', 2), ('Sou candidato a uma vaga', 'candidato, vaga, curriculo, processo seletivo, entrevista, candidatura', 3) ) AS seed(label, keywords, sort_order) ON TRUE -ON CONFLICT DO NOTHING; +ON CONFLICT (flow_id, label) DO NOTHING; WITH audiences AS ( SELECT bta.id, bta.label @@ -142,4 +144,4 @@ SELECT audiences.id, seed.label, areas.id, seed.keywords, seed.sort_order, TRUE, FROM seed INNER JOIN audiences ON audiences.label = seed.audience_label INNER JOIN areas ON areas.nome = seed.area_nome -ON CONFLICT DO NOTHING; +ON CONFLICT (audience_id, label) DO NOTHING; diff --git a/database/migrations/018_triage_resolution_step.sql b/database/migrations/016_triage_resolution_step.sql similarity index 100% rename from database/migrations/018_triage_resolution_step.sql rename to database/migrations/016_triage_resolution_step.sql diff --git a/database/migrations/019_bot_flow_builder.sql b/database/migrations/017_bot_flow_builder.sql similarity index 100% rename from database/migrations/019_bot_flow_builder.sql rename to database/migrations/017_bot_flow_builder.sql diff --git a/database/migrations/020_bot_flow_close_node_and_area_delete.sql b/database/migrations/018_bot_flow_close_node.sql similarity index 100% rename from database/migrations/020_bot_flow_close_node_and_area_delete.sql rename to database/migrations/018_bot_flow_close_node.sql diff --git a/database/migrations/021_admin_audit_ai_contents.sql b/database/migrations/019_admin_audit_ai_contents.sql similarity index 100% rename from database/migrations/021_admin_audit_ai_contents.sql rename to database/migrations/019_admin_audit_ai_contents.sql diff --git a/database/migrations/022_whatsapp_template_category.sql b/database/migrations/020_whatsapp_template_category.sql similarity index 100% rename from database/migrations/022_whatsapp_template_category.sql rename to database/migrations/020_whatsapp_template_category.sql diff --git a/database/migrations/023_agenda_contact_channels.sql b/database/migrations/021_agenda_contact_channels.sql similarity index 100% rename from database/migrations/023_agenda_contact_channels.sql rename to database/migrations/021_agenda_contact_channels.sql diff --git a/database/migrations/025_whatsapp_config.sql b/database/migrations/022_whatsapp_config.sql similarity index 100% rename from database/migrations/025_whatsapp_config.sql rename to database/migrations/022_whatsapp_config.sql diff --git a/database/migrations/026_whatsapp_templates_hsm.sql b/database/migrations/023_whatsapp_templates_hsm.sql similarity index 100% rename from database/migrations/026_whatsapp_templates_hsm.sql rename to database/migrations/023_whatsapp_templates_hsm.sql diff --git a/database/migrations/027_mensagens_media_columns.sql b/database/migrations/024_mensagens_media_columns.sql similarity index 100% rename from database/migrations/027_mensagens_media_columns.sql rename to database/migrations/024_mensagens_media_columns.sql diff --git a/database/migrations/028_mensagens_media_filename.sql b/database/migrations/025_mensagens_media_filename.sql similarity index 100% rename from database/migrations/028_mensagens_media_filename.sql rename to database/migrations/025_mensagens_media_filename.sql diff --git a/database/migrations/029_remove_fake_templates.sql b/database/migrations/026_remove_fake_templates.sql similarity index 100% rename from database/migrations/029_remove_fake_templates.sql rename to database/migrations/026_remove_fake_templates.sql diff --git a/database/migrations/030_remove_opening_templates.sql b/database/migrations/030_remove_opening_templates.sql deleted file mode 100644 index 841606c..0000000 --- a/database/migrations/030_remove_opening_templates.sql +++ /dev/null @@ -1,18 +0,0 @@ --- Migration 030: Remove templates de abertura sem vinculo com a Meta --- A migration 011 re-insere esses templates em todo deploy via ON CONFLICT DO UPDATE. --- Este arquivo garante que sejam removidos caso nao estejam vinculados a Meta. - -DELETE FROM whatsapp_templates -WHERE name IN ( - 'abertura_atendimento_padrao', - 'abertura_retorno_contato', - 'abertura_suporte', - 'abertura_financeiro', - 'abertura_comercial', - 'abertura_confirmacao_dados', - 'abertura_contato_agendado', - 'abertura_pos_atendimento', - 'abertura_aviso_importante', - 'abertura_contato_inicial' -) -AND meta_template_name IS NULL; diff --git a/database/migrations/003_demo_access.sql b/database/seeds/001_demo_access.sql similarity index 100% rename from database/migrations/003_demo_access.sql rename to database/seeds/001_demo_access.sql