Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions python/dataload.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"# fazendo importações\n",
"import os\n",
"from random import choice, choices, randint, triangular\n",
"from datetime import date, timedelta\n",
"from datetime import datetime, date, timedelta, timezone\n",
"from dotenv import load_dotenv\n",
"from faker import Faker\n",
"import pandas as pd\n",
Expand Down Expand Up @@ -774,6 +774,36 @@
"dados_meta_responsavel = []\n",
"dados_usuario_treinamento = []\n",
"dados_priorizacao = []\n",
"dados_notificacao = []\n",
"\n",
"ciclos_empresa = {}\n",
"for id_ciclo_notificacao, ciclo_notificacao in enumerate(dados_ciclo, start=1):\n",
" ciclos_empresa.setdefault(ciclo_notificacao['id_empresa'], []).append(id_ciclo_notificacao)\n",
"\n",
"agora = datetime.now(timezone.utc)\n",
"for _ in range(100):\n",
" id_empresa = choice(lista_id_empresa)\n",
" id_usuario_destino = choice(usuarios_empresa[id_empresa])\n",
" id_ciclo_notificacao = choice(ciclos_empresa[id_empresa])\n",
" criado_em = faker.date_time_between(start_date='-365d', end_date='now', tzinfo=timezone.utc)\n",
" lido_em = None\n",
" if choice([True, False]):\n",
" intervalo_leitura = int((agora - criado_em).total_seconds())\n",
" lido_em = criado_em + timedelta(seconds=randint(1, intervalo_leitura)) if intervalo_leitura else criado_em\n",
"\n",
" dados_notificacao.append({\n",
" 'id_usuario_destino': id_usuario_destino,\n",
" 'id_empresa': id_empresa,\n",
" 'tipo': 'CICLO_ATUALIZADO',\n",
" 'categoria': 'PDCA',\n",
" 'tipo_entidade': 'CICLO',\n",
" 'id_entidade': str(id_ciclo_notificacao),\n",
" 'deep_link': f'/ciclos/{id_ciclo_notificacao}',\n",
" 'chave_deduplicacao': f'dataload:{uuid4()}',\n",
" 'criado_em': criado_em,\n",
" 'lido_em': lido_em,\n",
" 'expira_em': criado_em + timedelta(days=90)\n",
" })\n",
"\n",
"for id_ciclo, ciclo in enumerate(dados_ciclo, start=1):\n",
" colaborador_empresa = usuarios_empresa[ciclo['id_empresa']]\n",
Expand Down Expand Up @@ -825,7 +855,8 @@
"df_meta_responsavel = pd.DataFrame(dados_meta_responsavel)\n",
"df_priorizacao_problema = pd.DataFrame(dados_priorizacao)\n",
"df_usuario_treinamento = pd.DataFrame(dados_usuario_treinamento)\n",
"df_usuario_ciclo = pd.DataFrame(dados_usuario_ciclo)"
"df_usuario_ciclo = pd.DataFrame(dados_usuario_ciclo)\n",
"df_notificacao = pd.DataFrame(dados_notificacao)\n"
]
},
{
Expand All @@ -849,6 +880,7 @@
"tabelas = {\n",
" ('public', 'empresa'): df_empresa,\n",
" ('public', 'usuario_sistema'): df_usuario,\n",
" ('auditoria', 'notificacao'): df_notificacao,\n",
" ('public', 'colaborador'): df_colaborador,\n",
" ('public', 'email_empresa'): df_email_empresa,\n",
" ('public', 'telefone_empresa'): df_telefone_empresa,\n",
Expand Down
31 changes: 17 additions & 14 deletions sql/001_script.sql
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ CREATE TABLE IF NOT EXISTS usuario_sistema (
nome VARCHAR(160) NOT NULL,
email_login VARCHAR(254) NOT NULL UNIQUE CHECK (email_login ~* '^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$'),
firebase_uid VARCHAR(128) UNIQUE,
firebase_fid TEXT,
tipo_usuario VARCHAR(40) NOT NULL CHECK (tipo_usuario IN ('ADMIN', 'GESTOR', 'COLABORADOR')),
status VARCHAR(40) NOT NULL CHECK (status IN ('ATIVO', 'INATIVO', 'PENDENTE', 'BLOQUEADO', 'ARQUIVADO')),
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW(),
Expand Down Expand Up @@ -270,16 +271,6 @@ CREATE TABLE IF NOT EXISTS pdca.tarefa (
CONSTRAINT tarefa_datas_check CHECK ((data_inicio_real IS NULL OR data_fim_prevista >= data_inicio_real) AND (data_fim_real IS NULL OR data_inicio_real IS NULL OR data_fim_real >= data_inicio_real))
);


CREATE TABLE IF NOT EXISTS pdca.alerta_prazo (
id BIGSERIAL PRIMARY KEY,
id_tarefa BIGINT NOT NULL REFERENCES pdca.tarefa(id) ON DELETE CASCADE,
id_usuario_destino BIGINT NOT NULL REFERENCES usuario_sistema(id) ON DELETE CASCADE,
mensagem TEXT NOT NULL,
enviado_em TIMESTAMPTZ NOT NULL DEFAULT NOW(),
lido_em TIMESTAMPTZ
);

CREATE TABLE IF NOT EXISTS pdca.tarefa_dependencia (
id_tarefa BIGINT NOT NULL REFERENCES pdca.tarefa(id) ON DELETE CASCADE,
id_tarefa_dependencia BIGINT NOT NULL REFERENCES pdca.tarefa(id) ON DELETE CASCADE,
Expand Down Expand Up @@ -393,9 +384,21 @@ CREATE TABLE IF NOT EXISTS auditoria.log_tarefa (
CONSTRAINT log_tarefa_json_check CHECK (jsonb_typeof(dados_antes) = 'object' AND jsonb_typeof(dados_depois) = 'object')
);



-----------Anexos (alterar no modelo lógico)
CREATE TABLE IF NOT EXISTS auditoria.notificacao (
id BIGSERIAL PRIMARY KEY,
id_usuario_destino BIGINT NOT NULL REFERENCES public.usuario_sistema(id) ON DELETE CASCADE,
id_empresa BIGINT NOT NULL REFERENCES public.empresa(id) ON DELETE CASCADE,
tipo VARCHAR(60) NOT NULL,
categoria VARCHAR(40) NOT NULL,
tipo_entidade VARCHAR(40) NOT NULL,
id_entidade VARCHAR(100) NOT NULL,
deep_link VARCHAR(240) NOT NULL,
chave_deduplicacao VARCHAR(160) NOT NULL,
criado_em TIMESTAMPTZ NOT NULL DEFAULT NOW(),
lido_em TIMESTAMPTZ,
expira_em TIMESTAMPTZ,
CONSTRAINT uk_notificacao_destinatario_deduplicacao UNIQUE (id_usuario_destino, chave_deduplicacao)
);

CREATE TABLE IF NOT EXISTS pdca.anexo (
id BIGSERIAL PRIMARY KEY,
Expand Down Expand Up @@ -446,4 +449,4 @@ CREATE TABLE IF NOT EXISTS pdca.anexo (
)
OR tipo_arquivo LIKE 'image/%'
)
);
);
19 changes: 9 additions & 10 deletions sql/002_indices.sql
Original file line number Diff line number Diff line change
Expand Up @@ -173,17 +173,17 @@ CREATE INDEX IF NOT EXISTS idx_problema_status ON pdca.problema (status);
-- ANTES: execution time -> 0.401
-- DEPOIS: execution time -> 0.081

-- Alerta Prazo por Tarefa
EXPLAIN ANALYZE SELECT * FROM pdca.alerta_prazo WHERE id_tarefa = 1;
CREATE INDEX IF NOT EXISTS idx_alerta_tarefa ON pdca.alerta_prazo (id_tarefa);
-- ANTES: execution time -> 0.681
-- Notificações por destinatário
EXPLAIN ANALYZE SELECT * FROM auditoria.notificacao WHERE id_usuario_destino = 64 ORDER BY criado_em DESC, id DESC;
CREATE INDEX IF NOT EXISTS ix_notificacao_destinatario_criado ON auditoria.notificacao (id_usuario_destino, criado_em DESC, id DESC);
-- ANTES: execution time -> 0.091
-- DEPOIS: execution time -> 0.027

-- Alerta Prazo por Usuário
EXPLAIN ANALYZE SELECT * FROM pdca.alerta_prazo WHERE id_usuario_destino = 1;
CREATE INDEX IF NOT EXISTS idx_alerta_usuario ON pdca.alerta_prazo (id_usuario_destino);
-- ANTES: execution time -> 0.329
-- DEPOIS: execution time -> 0.025
-- Notificações não lidas por destinatário
EXPLAIN ANALYZE SELECT * FROM auditoria.notificacao WHERE id_usuario_destino = 65 AND lido_em IS NULL ORDER BY criado_em DESC, id DESC;
CREATE INDEX IF NOT EXISTS ix_notificacao_destinatario_nao_lida ON auditoria.notificacao (id_usuario_destino, criado_em DESC, id DESC) WHERE lido_em IS NULL;
-- ANTES: execution time -> 0.027
-- DEPOIS: execution time -> 0.026

-- Colaborador por Empresa
EXPLAIN ANALYZE SELECT * FROM colaborador WHERE id_empresa = 1;
Expand Down Expand Up @@ -276,7 +276,6 @@ CREATE INDEX IF NOT EXISTS idx_email_colaborador ON email_colaborador (id_colabo
-- DEPOIS: execution time -> 0.035

-- Índices Únicos

CREATE UNIQUE INDEX IF NOT EXISTS idx_telefone_colaborador_principal
ON public.telefone_colaborador (id_colaborador) WHERE principal = TRUE;

Expand Down
26 changes: 20 additions & 6 deletions sql/003_functions_triggers_procedures.sql
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ EXECUTE FUNCTION public.fn_preencher_nickname_colaborador();
-- PROCEDURES
-- ######################

-- 1 (gera alertas de atraso para tarefas que estão atrasadas e atualiza o status das mesmas para 'ATRASADA')
-- 1 (gera notificações de atraso para tarefas vencidas e atualiza o status para 'ATRASADA')

CREATE OR REPLACE PROCEDURE pdca.pr_gerar_alertas_atraso()
LANGUAGE plpgsql
Expand All @@ -824,16 +824,30 @@ DECLARE
r RECORD;
BEGIN
FOR r IN
SELECT id, id_responsavel, titulo, data_fim_prevista FROM pdca.tarefa
WHERE data_fim_prevista < CURRENT_DATE AND status NOT IN ('CONCLUIDA', 'CANCELADA')
SELECT t.id, t.id_responsavel, t.titulo, t.data_fim_prevista, c.id_empresa, c.id AS id_ciclo
FROM pdca.tarefa t
JOIN pdca.plano_acao pa ON pa.id = t.id_plano_acao
JOIN pdca.ciclo c ON c.id = pa.id_ciclo
WHERE t.data_fim_prevista < CURRENT_DATE AND t.status NOT IN ('CONCLUIDA', 'CANCELADA')
LOOP
PERFORM set_config('app.current_user_id', r.id_responsavel::text, true);

INSERT INTO pdca.alerta_prazo (id_tarefa, id_usuario_destino, mensagem) VALUES (r.id, r.id_responsavel,
FORMAT('A tarefa "%s" está atrasada desde %s.', r.titulo, TO_CHAR(r.data_fim_prevista, 'DD/MM/YYYY')));
INSERT INTO auditoria.notificacao (
id_usuario_destino, id_empresa, tipo, categoria, tipo_entidade,
id_entidade, deep_link, chave_deduplicacao
) VALUES (
r.id_responsavel,
r.id_empresa,
'TAREFA_ATRASADA',
'PRAZO',
'TAREFA',
r.id::TEXT,
FORMAT('/ciclos/%s/tarefas/%s', r.id_ciclo, r.id),
FORMAT('tarefa-atrasada:%s', r.id)
)
ON CONFLICT (id_usuario_destino, chave_deduplicacao) DO NOTHING;

UPDATE pdca.tarefa SET status = 'ATRASADA' WHERE id = r.id;

END LOOP;
END;
$$;
Expand Down
25 changes: 16 additions & 9 deletions sql/007_comments.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ COMMENT ON COLUMN public.usuario_sistema.id_empresa IS 'Empresa a qual o usuario
COMMENT ON COLUMN public.usuario_sistema.nome IS 'Nome do usuario.';
COMMENT ON COLUMN public.usuario_sistema.email_login IS 'E-mail utilizado para login no sistema.';
COMMENT ON COLUMN public.usuario_sistema.firebase_uid IS 'Identificador unico do usuario no Firebase Authentication.';
COMMENT ON COLUMN public.usuario_sistema.firebase_fid IS 'Firebase Installation ID (FID) atual associado a um dispositivo do usuario; atualizar quando renovado e limpar no logout ou quando invalido.';
COMMENT ON COLUMN public.usuario_sistema.tipo_usuario IS 'Perfil de acesso do usuario: ADMIN, GESTOR ou COLABORADOR.';
COMMENT ON COLUMN public.usuario_sistema.status IS 'Situacao do usuario no sistema.';
COMMENT ON COLUMN public.usuario_sistema.criado_em IS 'Data e hora de criacao do registro.';
Expand Down Expand Up @@ -225,14 +226,6 @@ COMMENT ON COLUMN pdca.tarefa.data_fim_real IS 'Data real de conclusao da tarefa
COMMENT ON COLUMN pdca.tarefa.criado_em IS 'Data e hora de criacao do registro.';
COMMENT ON COLUMN pdca.tarefa.atualizado_em IS 'Data e hora da ultima atualizacao do registro.';

COMMENT ON TABLE pdca.alerta_prazo IS 'Alertas enviados a usuarios sobre prazos de tarefas.';
COMMENT ON COLUMN pdca.alerta_prazo.id IS 'Identificador unico do alerta.';
COMMENT ON COLUMN pdca.alerta_prazo.id_tarefa IS 'Tarefa relacionada ao alerta.';
COMMENT ON COLUMN pdca.alerta_prazo.id_usuario_destino IS 'Usuario destinatario do alerta.';
COMMENT ON COLUMN pdca.alerta_prazo.mensagem IS 'Mensagem enviada no alerta.';
COMMENT ON COLUMN pdca.alerta_prazo.enviado_em IS 'Data e hora de envio do alerta.';
COMMENT ON COLUMN pdca.alerta_prazo.lido_em IS 'Data e hora de leitura do alerta.';

COMMENT ON TABLE pdca.tarefa_dependencia IS 'Dependencias entre tarefas de planos de acao.';
COMMENT ON COLUMN pdca.tarefa_dependencia.id_tarefa IS 'Tarefa que depende de outra tarefa.';
COMMENT ON COLUMN pdca.tarefa_dependencia.id_tarefa_dependencia IS 'Tarefa que deve ser considerada como dependencia.';
Expand Down Expand Up @@ -341,4 +334,18 @@ COMMENT ON COLUMN auditoria.log_tarefa.id_usuario IS 'Usuario responsavel pela o
COMMENT ON COLUMN auditoria.log_tarefa.dados_antes IS 'Estado da tarefa antes da operacao.';
COMMENT ON COLUMN auditoria.log_tarefa.dados_depois IS 'Estado da tarefa depois da operacao.';
COMMENT ON COLUMN auditoria.log_tarefa.data_log IS 'Data e hora de criacao do log.';
COMMENT ON COLUMN auditoria.log_tarefa.operacao IS 'Tipo de operacao auditada.';
COMMENT ON COLUMN auditoria.log_tarefa.operacao IS 'Tipo de operacao auditada.';

COMMENT ON TABLE auditoria.notificacao IS 'Notificacoes destinadas aos usuarios da plataforma.';
COMMENT ON COLUMN auditoria.notificacao.id IS 'Identificador unico da notificacao.';
COMMENT ON COLUMN auditoria.notificacao.id_usuario_destino IS 'Usuario que recebera a notificacao.';
COMMENT ON COLUMN auditoria.notificacao.id_empresa IS 'Empresa associada a notificacao.';
COMMENT ON COLUMN auditoria.notificacao.tipo IS 'Tipo do evento que originou a notificacao.';
COMMENT ON COLUMN auditoria.notificacao.categoria IS 'Categoria funcional da notificacao.';
COMMENT ON COLUMN auditoria.notificacao.tipo_entidade IS 'Tipo do registro relacionado a notificacao.';
COMMENT ON COLUMN auditoria.notificacao.id_entidade IS 'Identificador do registro relacionado, armazenado como texto.';
COMMENT ON COLUMN auditoria.notificacao.deep_link IS 'Caminho para abrir o contexto relacionado na aplicacao.';
COMMENT ON COLUMN auditoria.notificacao.chave_deduplicacao IS 'Chave unica por destinatario usada para evitar notificacoes duplicadas.';
COMMENT ON COLUMN auditoria.notificacao.criado_em IS 'Data e hora de criacao da notificacao.';
COMMENT ON COLUMN auditoria.notificacao.lido_em IS 'Data e hora em que o destinatario leu a notificacao, quando aplicavel.';
COMMENT ON COLUMN auditoria.notificacao.expira_em IS 'Data e hora em que a notificacao deixa de ser valida, quando aplicavel.';
25 changes: 16 additions & 9 deletions sql/008_catalogo.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ INSERT INTO auditoria.catalogo_dados (
('public', 'usuario_sistema', 'nome', 'VARCHAR(160)', FALSE, FALSE, NULL, TRUE, 'Nome do usuário.', 'SENSIVEL', 'Nome do usuário.'),
('public', 'usuario_sistema', 'email_login', 'VARCHAR(254)', FALSE, FALSE, NULL, TRUE, 'Deve corresponder ao padrão de e-mail válido. Único no sistema.', 'SENSIVEL', 'E-mail utilizado para login no sistema.'),
('public', 'usuario_sistema', 'firebase_uid', 'VARCHAR(128)', FALSE, FALSE, NULL, FALSE, 'Obrigatório caso o status seja ATIVO.', 'RESTRITO', 'Identificador único do usuário no Firebase Authentication.'),
('public', 'usuario_sistema', 'firebase_fid', 'TEXT', FALSE, FALSE, NULL, FALSE, 'Firebase Installation ID atual associado a um único dispositivo do usuário; atualizar quando renovado e limpar quando inválido ou no logout.', 'RESTRITO', 'Identificador de destino usado pelo acta-fcm-api para enviar push ao usuário.'),
('public', 'usuario_sistema', 'tipo_usuario', 'VARCHAR(40)', FALSE, FALSE, NULL, TRUE, 'Valores aceitos: ADMIN, GESTOR ou COLABORADOR.', 'INTERNO', 'Perfil de acesso do usuário: ADMIN, GESTOR ou COLABORADOR.'),
('public', 'usuario_sistema', 'status', 'VARCHAR(40)', FALSE, FALSE, NULL, TRUE, 'Valores aceitos: ATIVO, INATIVO, PENDENTE, BLOQUEADO, ARQUIVADO.', 'INTERNO', 'Situação do usuário no sistema.'),
('public', 'usuario_sistema', 'criado_em', 'TIMESTAMPTZ', FALSE, FALSE, NULL, TRUE, 'Valor padrão obtido com NOW().', 'INTERNO', 'Data e hora de criação do registro.'),
Expand Down Expand Up @@ -232,14 +233,6 @@ INSERT INTO auditoria.catalogo_dados (
('pdca', 'tarefa', 'criado_em', 'TIMESTAMPTZ', FALSE, FALSE, NULL, TRUE, 'Valor padrão NOW().', 'INTERNO', 'Data e hora de criação do registro.'),
('pdca', 'tarefa', 'atualizado_em', 'TIMESTAMPTZ', FALSE, FALSE, NULL, FALSE, 'Última modificação.', 'INTERNO', 'Data e hora da última atualização do registro.'),

-- pdca.alerta_prazo
('pdca', 'alerta_prazo', 'id', 'BIGSERIAL', TRUE, FALSE, NULL, TRUE, 'Gerado automaticamente.', 'INTERNO', 'Identificador único do alerta.'),
('pdca', 'alerta_prazo', 'id_tarefa', 'BIGINT', FALSE, TRUE, 'pdca.tarefa(id)', TRUE, 'ON DELETE CASCADE.', 'INTERNO', 'Tarefa relacionada ao alerta.'),
('pdca', 'alerta_prazo', 'id_usuario_destino', 'BIGINT', FALSE, TRUE, 'public.usuario_sistema(id)', TRUE, 'ON DELETE CASCADE.', 'INTERNO', 'Usuário destinatário do alerta.'),
('pdca', 'alerta_prazo', 'mensagem', 'TEXT', FALSE, FALSE, NULL, TRUE, 'Texto do alerta.', 'INTERNO', 'Mensagem enviada no alerta.'),
('pdca', 'alerta_prazo', 'enviado_em', 'TIMESTAMPTZ', FALSE, FALSE, NULL, TRUE, 'Valor padrão NOW().', 'INTERNO', 'Data e hora de envio do alerta.'),
('pdca', 'alerta_prazo', 'lido_em', 'TIMESTAMPTZ', FALSE, FALSE, NULL, FALSE, 'Registrado na confirmação de leitura.', 'INTERNO', 'Data e hora de leitura do alerta.'),

-- pdca.tarefa_dependencia
('pdca', 'tarefa_dependencia', 'id_tarefa', 'BIGINT', TRUE, TRUE, 'pdca.tarefa(id)', TRUE, 'ON DELETE CASCADE. Parte da PK.', 'INTERNO', 'Tarefa que depende de outra tarefa.'),
('pdca', 'tarefa_dependencia', 'id_tarefa_dependencia', 'BIGINT', TRUE, TRUE, 'pdca.tarefa(id)', TRUE, 'ON DELETE CASCADE. Parte da PK. Deve ser diferente de id_tarefa.', 'INTERNO', 'Tarefa que deve ser considerada como dependência.'),
Expand Down Expand Up @@ -349,4 +342,18 @@ INSERT INTO auditoria.catalogo_dados (
('auditoria', 'log_tarefa', 'dados_antes', 'JSONB', FALSE, FALSE, NULL, TRUE, 'Snapshot anterior (Objeto JSONB).', 'RESTRITO', 'Estado da tarefa antes da operação.'),
('auditoria', 'log_tarefa', 'dados_depois', 'JSONB', FALSE, FALSE, NULL, TRUE, 'Snapshot posterior (Objeto JSONB).', 'RESTRITO', 'Estado da tarefa depois da operação.'),
('auditoria', 'log_tarefa', 'data_log', 'TIMESTAMPTZ', FALSE, FALSE, NULL, TRUE, 'Valor padrão NOW().', 'RESTRITO', 'Data e hora de criação do log.'),
('auditoria', 'log_tarefa', 'operacao', 'VARCHAR(40)', FALSE, FALSE, NULL, TRUE, 'INSERT, UPDATE, DELETE, LOGIN, LOGOUT, READ, EXPORT.', 'RESTRITO', 'Tipo de operação auditada.');
('auditoria', 'log_tarefa', 'operacao', 'VARCHAR(40)', FALSE, FALSE, NULL, TRUE, 'INSERT, UPDATE, DELETE, LOGIN, LOGOUT, READ, EXPORT.', 'RESTRITO', 'Tipo de operação auditada.'),

-- auditoria.notificacao
('auditoria', 'notificacao', 'id', 'BIGSERIAL', TRUE, FALSE, NULL, TRUE, 'Gerado automaticamente pelo banco de dados.', 'INTERNO', 'Identificador único da notificação.'),
('auditoria', 'notificacao', 'id_usuario_destino', 'BIGINT', FALSE, TRUE, 'public.usuario_sistema(id)', TRUE, 'ON DELETE CASCADE.', 'INTERNO', 'Usuário que receberá a notificação.'),
('auditoria', 'notificacao', 'id_empresa', 'BIGINT', FALSE, TRUE, 'public.empresa(id)', TRUE, 'ON DELETE CASCADE.', 'INTERNO', 'Empresa associada à notificação.'),
('auditoria', 'notificacao', 'tipo', 'VARCHAR(60)', FALSE, FALSE, NULL, TRUE, 'Tipo do evento que originou a notificação.', 'INTERNO', 'Tipo do evento que originou a notificação.'),
('auditoria', 'notificacao', 'categoria', 'VARCHAR(40)', FALSE, FALSE, NULL, TRUE, 'Categoria funcional definida pela aplicação.', 'INTERNO', 'Categoria funcional da notificação.'),
('auditoria', 'notificacao', 'tipo_entidade', 'VARCHAR(40)', FALSE, FALSE, NULL, TRUE, 'Tipo do registro relacionado.', 'INTERNO', 'Tipo do registro relacionado à notificação.'),
('auditoria', 'notificacao', 'id_entidade', 'VARCHAR(100)', FALSE, FALSE, NULL, TRUE, 'Identificador do registro relacionado, armazenado como texto.', 'INTERNO', 'Identificador do registro relacionado.'),
('auditoria', 'notificacao', 'deep_link', 'VARCHAR(240)', FALSE, FALSE, NULL, TRUE, 'Caminho interno para o contexto relacionado na aplicação.', 'INTERNO', 'Caminho para abrir o contexto da notificação.'),
('auditoria', 'notificacao', 'chave_deduplicacao', 'VARCHAR(160)', FALSE, FALSE, NULL, TRUE, 'Única por destinatário; impede duplicidade para a mesma chave.', 'INTERNO', 'Chave de deduplicação da notificação por destinatário.'),
('auditoria', 'notificacao', 'criado_em', 'TIMESTAMPTZ', FALSE, FALSE, NULL, TRUE, 'Valor padrão NOW().', 'INTERNO', 'Data e hora de criação da notificação.'),
('auditoria', 'notificacao', 'lido_em', 'TIMESTAMPTZ', FALSE, FALSE, NULL, FALSE, 'NULL enquanto não lida.', 'INTERNO', 'Data e hora da leitura pelo destinatário.'),
('auditoria', 'notificacao', 'expira_em', 'TIMESTAMPTZ', FALSE, FALSE, NULL, FALSE, 'Data de expiração opcional; a aplicação deve filtrar ou remover registros expirados.', 'INTERNO', 'Data e hora de expiração da notificação, quando aplicável.');
Loading
Loading