-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatabase_schema.sql
More file actions
315 lines (278 loc) · 9.93 KB
/
database_schema.sql
File metadata and controls
315 lines (278 loc) · 9.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
-- Esquema do banco de dados para o aplicativo Lujeee no Supabase
-- Tabela de usuários
CREATE TABLE IF NOT EXISTS usuarios (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
nome TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
telefone TEXT UNIQUE NOT NULL,
numero_contador TEXT UNIQUE NOT NULL,
senha TEXT NOT NULL,
tipo TEXT NOT NULL DEFAULT 'pre-pago', -- Tipo de plano: pre-pago ou pos-pago
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Habilitar RLS na tabela de usuários
ALTER TABLE usuarios ENABLE ROW LEVEL SECURITY;
-- Criar políticas RLS para a tabela de usuários
-- Permitir inserções anônimas (para cadastro)
CREATE POLICY "Permitir inserções anônimas" ON usuarios FOR INSERT TO anon WITH CHECK (true);
-- Permitir leitura apenas para o próprio usuário autenticado
CREATE POLICY "Usuários podem ver apenas seus próprios dados" ON usuarios FOR SELECT
USING (auth.uid() = id OR auth.role() = 'anon');
-- Permitir atualização apenas para o próprio usuário
CREATE POLICY "Usuários podem atualizar apenas seus próprios dados" ON usuarios FOR UPDATE
USING (auth.uid() = id) WITH CHECK (auth.uid() = id);
-- Permitir exclusão apenas para o próprio usuário
CREATE POLICY "Usuários podem excluir apenas seus próprios dados" ON usuarios FOR DELETE
USING (auth.uid() = id);
-- Tabela de consumo de energia
CREATE TABLE IF NOT EXISTS consumo_energia (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
usuario_id UUID REFERENCES usuarios(id) ON DELETE CASCADE,
valor_kwh DECIMAL(10, 2) NOT NULL,
data_leitura DATE NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Índice para melhorar a performance de consultas de consumo por usuário
CREATE INDEX IF NOT EXISTS idx_consumo_usuario ON consumo_energia(usuario_id);
-- Tabela de alarmes de consumo
CREATE TABLE IF NOT EXISTS alarmes_kwh (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
usuario_id UUID REFERENCES usuarios(id) ON DELETE CASCADE,
ativado BOOLEAN DEFAULT FALSE,
limite_kwh DECIMAL(10, 2),
notificacao_app BOOLEAN DEFAULT TRUE,
notificacao_email BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_alarme_usuario UNIQUE (usuario_id)
);
-- Tabela de notificações de alarme
CREATE TABLE IF NOT EXISTS notificacoes_alarme (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
usuario_id UUID REFERENCES usuarios(id) ON DELETE CASCADE,
alarme_id UUID REFERENCES alarmes_kwh(id) ON DELETE CASCADE,
percentual INTEGER NOT NULL, -- 80, 90 ou 100% do limite
lida BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela de feedback dos usuários
CREATE TABLE IF NOT EXISTS feedback (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
usuario_id UUID REFERENCES usuarios(id) ON DELETE SET NULL,
titulo TEXT NOT NULL,
descricao TEXT NOT NULL,
categoria TEXT NOT NULL, -- Problema, Sugestão, Elogio
classificacao INTEGER CHECK (classificacao BETWEEN 1 AND 5),
resolvido BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela de dicas de economia
CREATE TABLE IF NOT EXISTS dicas (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
titulo TEXT NOT NULL,
descricao TEXT NOT NULL,
categoria TEXT NOT NULL, -- Iluminação, Eletrodomésticos, etc.
economia_estimada TEXT,
imagem_url TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela de controle de tema
CREATE TABLE IF NOT EXISTS preferencias_usuario (
usuario_id UUID PRIMARY KEY REFERENCES usuarios(id) ON DELETE CASCADE,
tema_escuro BOOLEAN DEFAULT FALSE,
notificacoes_ativadas BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Tabela de sessões (para substituir o auth do Supabase)
CREATE TABLE IF NOT EXISTS sessoes (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
usuario_id UUID REFERENCES usuarios(id) ON DELETE CASCADE,
token TEXT NOT NULL UNIQUE,
created_at TIMESTAMPTZ DEFAULT NOW(),
expires_at TIMESTAMPTZ NOT NULL,
CONSTRAINT unique_usuario_sessao UNIQUE (usuario_id, token)
);
-- Função para atualizar o timestamp de updated_at
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Triggers para atualizar automaticamente o campo updated_at
CREATE TRIGGER update_usuario_updated_at
BEFORE UPDATE ON usuarios
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_alarmes_updated_at
BEFORE UPDATE ON alarmes_kwh
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_dicas_updated_at
BEFORE UPDATE ON dicas
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_preferencias_updated_at
BEFORE UPDATE ON preferencias_usuario
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- Views para relatórios
-- View para consumo mensal por usuário
CREATE OR REPLACE VIEW consumo_mensal AS
SELECT
usuario_id,
DATE_TRUNC('month', data_leitura) AS mes,
SUM(valor_kwh) AS total_kwh
FROM
consumo_energia
GROUP BY
usuario_id, DATE_TRUNC('month', data_leitura);
-- View para consumo semanal por usuário
CREATE OR REPLACE VIEW consumo_semanal AS
SELECT
usuario_id,
DATE_TRUNC('week', data_leitura) AS semana,
SUM(valor_kwh) AS total_kwh
FROM
consumo_energia
GROUP BY
usuario_id, DATE_TRUNC('week', data_leitura);
-- Habilitar RLS para todas as tabelas
ALTER TABLE consumo_energia ENABLE ROW LEVEL SECURITY;
ALTER TABLE alarmes_kwh ENABLE ROW LEVEL SECURITY;
ALTER TABLE notificacoes_alarme ENABLE ROW LEVEL SECURITY;
ALTER TABLE feedback ENABLE ROW LEVEL SECURITY;
ALTER TABLE preferencias_usuario ENABLE ROW LEVEL SECURITY;
ALTER TABLE sessoes ENABLE ROW LEVEL SECURITY;
-- Função para autenticação personalizada
CREATE OR REPLACE FUNCTION autenticar_usuario(
p_telefone TEXT,
p_senha TEXT
) RETURNS TABLE (
id UUID,
nome TEXT,
telefone TEXT,
token TEXT
) AS $$
DECLARE
v_user_id UUID;
v_nome TEXT;
v_token TEXT;
BEGIN
-- Obter ID e nome do usuário
SELECT usuarios.id, usuarios.nome INTO v_user_id, v_nome
FROM usuarios
WHERE telefone = p_telefone AND senha = p_senha;
IF v_user_id IS NULL THEN
RAISE EXCEPTION 'Credenciais inválidas';
END IF;
-- Gerar token
v_token := encode(gen_random_bytes(32), 'hex');
-- Criar nova sessão
INSERT INTO sessoes (usuario_id, token, expires_at)
VALUES (v_user_id, v_token, NOW() + INTERVAL '30 days');
-- Retornar dados do usuário e token
RETURN QUERY
SELECT v_user_id, v_nome, p_telefone, v_token;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Função para obter usuário a partir do token
CREATE OR REPLACE FUNCTION obter_usuario_por_token(
p_token TEXT
) RETURNS UUID AS $$
DECLARE
v_user_id UUID;
BEGIN
SELECT usuario_id INTO v_user_id
FROM sessoes
WHERE token = p_token AND expires_at > NOW();
RETURN v_user_id;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Função para registrar novo usuário
CREATE OR REPLACE FUNCTION registrar_usuario(
p_nome TEXT,
p_email TEXT,
p_telefone TEXT,
p_numero_contador TEXT,
p_senha TEXT,
p_tipo TEXT DEFAULT 'pos-pago'
) RETURNS UUID AS $$
DECLARE
v_user_id UUID;
BEGIN
-- Verificar se o telefone já está em uso
IF EXISTS (SELECT 1 FROM usuarios WHERE telefone = p_telefone) THEN
RAISE EXCEPTION 'Telefone já cadastrado';
END IF;
-- Verificar se o contador já está em uso
IF EXISTS (SELECT 1 FROM usuarios WHERE numero_contador = p_numero_contador) THEN
RAISE EXCEPTION 'Número do contador já cadastrado';
END IF;
-- Inserir usuário
INSERT INTO usuarios (nome, email, telefone, numero_contador, senha, tipo)
VALUES (p_nome, p_email, p_telefone, p_numero_contador, p_senha, p_tipo)
RETURNING id INTO v_user_id;
-- Criar preferências padrão
INSERT INTO preferencias_usuario (usuario_id)
VALUES (v_user_id);
-- Criar alarme padrão (desativado)
INSERT INTO alarmes_kwh (usuario_id, ativado, limite_kwh)
VALUES (v_user_id, FALSE, 300);
RETURN v_user_id;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Função para obter relatório de consumo
CREATE OR REPLACE FUNCTION obter_relatorio_consumo(
p_usuario_id UUID,
p_tipo TEXT, -- 'diario', 'semanal', 'mensal'
p_data_inicio DATE,
p_data_fim DATE
) RETURNS TABLE (
periodo TEXT,
consumo DECIMAL
) AS $$
BEGIN
IF p_tipo = 'diario' THEN
RETURN QUERY
SELECT
TO_CHAR(data_leitura, 'DD/MM/YYYY') AS periodo,
valor_kwh AS consumo
FROM
consumo_energia
WHERE
usuario_id = p_usuario_id
AND data_leitura BETWEEN p_data_inicio AND p_data_fim
ORDER BY
data_leitura;
ELSIF p_tipo = 'semanal' THEN
RETURN QUERY
SELECT
TO_CHAR(DATE_TRUNC('week', data_leitura), 'DD/MM/YYYY') AS periodo,
SUM(valor_kwh) AS consumo
FROM
consumo_energia
WHERE
usuario_id = p_usuario_id
AND data_leitura BETWEEN p_data_inicio AND p_data_fim
GROUP BY
DATE_TRUNC('week', data_leitura)
ORDER BY
DATE_TRUNC('week', data_leitura);
ELSIF p_tipo = 'mensal' THEN
RETURN QUERY
SELECT
TO_CHAR(DATE_TRUNC('month', data_leitura), 'MM/YYYY') AS periodo,
SUM(valor_kwh) AS consumo
FROM
consumo_energia
WHERE
usuario_id = p_usuario_id
AND data_leitura BETWEEN p_data_inicio AND p_data_fim
GROUP BY
DATE_TRUNC('month', data_leitura)
ORDER BY
DATE_TRUNC('month', data_leitura);
END IF;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;