Browse Source

WIP

websockets-2025
Edward Ribeiro 4 weeks ago
parent
commit
1dc0843053
  1. 54
      sapl/painel/README.md
  2. 6
      sapl/painel/consumers.py
  3. 6
      sapl/painel/views.py
  4. 255
      sapl/sessao/migrations/0070_views_sessao_plenaria.py

54
sapl/painel/README.md

@ -0,0 +1,54 @@
# Websockets
Rodar o container antes de iniciar o SAPL:
```commandline
sudo docker run --rm -p 6379:6379 redis:7-alpine redis-server --save "" --appendonly no
```
Executar o SAPL
Instalar dependências do Websockets e Redis:
```commandline
pip install -r requirements/dev-requirements.txt
```
Abrir um terminal e rodar `yarn` para servir as páginas VueJS:
```commandline
yarn serve
```
Executar o SAPL (duas formas):
DAPHNE:
Em outro terminal, no diretório raiz, execute como Daphne abaixo:
```commandline
daphne -b 127.0.0.1 -p 8000 sapl.asgi:application
```
Daphne é excelente para debugar a parte de WebSockets, pois contém melhores mensagens de erro e log.
O runserver geralmente só vai dar crash ou falhar ao enviar as mensagens via WebSocket.
**MAS atenção: Daphne não faz reload automático após mudanças na página!**
Para isso é que parar e reiniciar o Daphne ou usar `.manage.py runserver`
RUNSERVER:
Em outro terminal, no diretório raiz, execute como Daphne abaixo para debugar os websockets (melhores mensagens de log)
```commandline
./manage.py runserver
```
Logar no SAPL e acessar a página `http://localhost:8000/painel/v2`
Ferramentas:
`wscat`: permite fazer chamadas a websockets via CLI, mas para acessar o WS endpoint do painel precisa estar autenticado.
**Redis Insight:** GUI que é tipo um pgAdmin para o Redis;

6
sapl/painel/consumers.py

@ -30,19 +30,19 @@ def get_dados_painel(pk: int) -> dict:
# Painel
presentes = SessaoPresencaView.objects.filter(sessao_plenaria_id=4984,
presentes = SessaoPresencaView.objects.filter(sessao_plenaria_id=pk,
etapa_sessao='expediente').values_list('parlamentar_id',
'nome_parlamentar',
'filiacao', )
presentes = [dict(zip(['parlamentar_id', 'nome_parlamentar', 'filiacao'], p)) for p in presentes]
oradores = SessaoOradorView.objects.filter(sessao_plenaria_id=4983,
oradores = SessaoOradorView.objects.filter(sessao_plenaria_id=pk,
etapa_sessao='expediente').values_list('ordem_pronunciamento',
'nome_parlamentar',
)
oradores = [dict(zip(['ordem_pronunciamento', 'nome_parlamentar'], o)) for o in oradores]
votos = SessaoMateriaVotacaoView.objects.get(sessao_plenaria_id=4984, etapa_sessao='ordemdia', materia_id=4148)
votos = SessaoMateriaVotacaoView.objects.get(sessao_plenaria_id=pk, etapa_sessao='expediente', materia_id=31919)
# TODO: recover stopwatch state from DB/Cache
stopwatch = {

6
sapl/painel/views.py

@ -639,10 +639,10 @@ def websocket_view(request):
utc_offset = now.utcoffset().total_seconds() / 60
# controller_id == session_id
context = {'head_title': str(_('Painel Plenário')),
'sessao_id': 4984, # TODO: recover from template call
'sessao_id': 2546, # TODO: recover from template call
'utc_offset': utc_offset,
'enable_live_ws': True,
'controller_id': 4984, # TODO: unify with sessao_id
'controller_id': 2546, # TODO: unify with sessao_id
}
return render(request, "painel/painel_v2.html", context)
@ -658,7 +658,7 @@ def painel_controller_view(request):
if command:
layer = get_channel_layer()
controller_id = 4984 # TODO: recover from template call
controller_id = 2393 # TODO: recover from template call
group = f"controller_{controller_id}"
print(group)

255
sapl/sessao/migrations/0070_views_sessao_plenaria.py

@ -0,0 +1,255 @@
# Generated by Django 2.2.28 on 2025-11-17 17:55
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('sessao', '0069_auto_20220919_1705'),
]
operations = [
migrations.RunSQL(
"""
CREATE OR REPLACE VIEW sessao_presenca_view AS
--
-- PRESENCAS DE PARLAMENTARES COM FILIACAO (SE HOUVER)
-- MANDATO DEVE ESTAR ATIVO NA LEGISLATIURA
-- PARLAMENTAR DEVE ESTAR ATIVO
--
-- EXPEDIENTE
SELECT
p.id,
presenca.sessao_plenaria_id,
'expediente' AS etapa_sessao,
p.id as parlamentar_id,
p.nome_parlamentar as nome_parlamentar,
COALESCE(af.sigla, 'SEM PARTIDO') AS filiacao
FROM sessao_sessaoplenariapresenca AS presenca
JOIN sessao_sessaoplenaria AS sp
ON presenca.sessao_plenaria_id = sp.id
JOIN parlamentares_parlamentar AS p
ON presenca.parlamentar_id = p.id
JOIN parlamentares_mandato AS m
ON p.id = m.parlamentar_id
AND m.legislatura_id = sp.legislatura_id
AND m.data_inicio_mandato <= sp.data_inicio
AND (m.data_fim_mandato IS NULL OR m.data_fim_mandato >= sp.data_inicio)
-- recupera uma filiacao partidaria, se existir
LEFT JOIN LATERAL (
SELECT pa.sigla
FROM parlamentares_filiacao f
JOIN parlamentares_partido pa ON pa.id = f.partido_id
WHERE f.parlamentar_id = p.id
AND f.data <= sp.data_inicio
AND (f.data_desfiliacao IS NULL OR f.data_desfiliacao >= sp.data_inicio)
ORDER BY f.data DESC
LIMIT 1
) AS af ON TRUE
WHERE p.ativo = TRUE
UNION ALL
-- ORDEM DO DIA
SELECT
p.id,
presenca.sessao_plenaria_id,
'ordemdia' AS etapa_sessao,
p.id as parlamentar_id,
p.nome_parlamentar as nome_parlamentar,
COALESCE(af.sigla, 'SEM PARTIDO') AS filiacao
FROM sessao_presencaordemdia AS presenca
JOIN sessao_sessaoplenaria AS sp
ON presenca.sessao_plenaria_id = sp.id
JOIN parlamentares_parlamentar AS p
ON presenca.parlamentar_id = p.id
JOIN parlamentares_mandato AS m
ON p.id = m.parlamentar_id
AND m.legislatura_id = sp.legislatura_id
AND m.data_inicio_mandato <= sp.data_inicio
AND (m.data_fim_mandato IS NULL OR m.data_fim_mandato >= sp.data_inicio)
-- recupera uma filiacao partidaria, se existir
LEFT JOIN LATERAL (
SELECT pa.sigla
FROM parlamentares_filiacao f
JOIN parlamentares_partido pa ON pa.id = f.partido_id
WHERE f.parlamentar_id = p.id
AND f.data <= sp.data_inicio
AND (f.data_desfiliacao IS NULL OR f.data_desfiliacao >= sp.data_inicio)
ORDER BY f.data DESC
LIMIT 1
) AS af ON TRUE
WHERE p.ativo = TRUE
ORDER BY sessao_plenaria_id, etapa_sessao, nome_parlamentar
"""
),
migrations.RunSQL(
"""
CREATE OR REPLACE VIEW sessao_orador_view AS
--
-- ORADORES DE ORDEMDIA/EXPEDIENTE
-- * PARLAMENTARES ATIVOS
--
SELECT od.id,
sessao_plenaria_id,
'ordemdia' as etapa_sessao,
numero_ordem as ordem_pronunciamento,
parlamentar_id,
nome_parlamentar,
COALESCE(af.sigla, 'SEM PARTIDO') AS filiacao
FROM sessao_oradorordemdia od
JOIN sessao_sessaoplenaria sp ON (od.sessao_plenaria_id = sp.id)
JOIN parlamentares_parlamentar p ON (od.parlamentar_id = p.id)
-- recupera uma filiacao partidaria, se existir
LEFT JOIN LATERAL (
SELECT pa.sigla
FROM parlamentares_filiacao f
JOIN parlamentares_partido pa ON pa.id = f.partido_id
WHERE f.parlamentar_id = p.id
AND f.data <= sp.data_inicio
AND (f.data_desfiliacao IS NULL OR f.data_desfiliacao >= sp.data_inicio)
ORDER BY f.data DESC
LIMIT 1
) AS af ON TRUE
AND p.ativo = TRUE
UNION ALL
SELECT ex.id,
sessao_plenaria_id,
'expediente' as etapa_sessao,
numero_ordem as ordem_pronunciamento,
parlamentar_id,
nome_parlamentar,
COALESCE(af.sigla, 'SEM PARTIDO') AS filiacao
FROM sessao_oradorexpediente ex
JOIN sessao_sessaoplenaria sp ON (ex.sessao_plenaria_id = sp.id)
JOIN parlamentares_parlamentar p on (ex.parlamentar_id = p.id)
-- recupera uma filiacao partidaria, se existir
LEFT JOIN LATERAL (
SELECT pa.sigla
FROM parlamentares_filiacao f
JOIN parlamentares_partido pa ON pa.id = f.partido_id
WHERE f.parlamentar_id = p.id
AND f.data <= sp.data_inicio
AND (f.data_desfiliacao IS NULL OR f.data_desfiliacao >= sp.data_inicio)
ORDER BY f.data DESC
LIMIT 1
) AS af ON TRUE
AND p.ativo = TRUE
ORDER BY sessao_plenaria_id, etapa_sessao, ordem_pronunciamento
"""
),
migrations.RunSQL(
"""
CREATE OR REPLACE VIEW sessao_materias_votacoes_view AS
--
-- Votacao/Leitura de Materias
--
-- EXPEDIENTE
WITH votacao_materias AS (
SELECT em.sessao_plenaria_id,
em.id id,
'expediente' etapa_sessao,
em.numero_ordem,
em.materia_id,
ml.ementa,
tipo_votacao,
CASE tipo_votacao
WHEN 1 THEN 'Simbólia'
WHEN 2 THEN 'Nominal'
WHEN 3 THEN 'Secreta'
WHEN 4 THEN 'Leitura'
ELSE ''
END as tipo_votacao_descricao,
resultado_votacao,
em.resultado,
total_votos,
votos_parlamentares,
votacao_aberta
FROM sessao_expedientemateria em
JOIN materia_materialegislativa ml ON (em.materia_id = ml.id)
LEFT JOIN sessao_registroleitura rl on (rl.expediente_id = em.id)
LEFT JOIN LATERAL (
SELECT jsonb_build_object(
'sim', coalesce(rv.numero_votos_sim, 0),
'não', coalesce(rv.numero_votos_nao, 0),
'abstencoes', coalesce(rv.numero_abstencoes, 0)
) as total_votos,
trv.nome resultado_votacao
FROM sessao_registrovotacao rv
JOIN sessao_tiporesultadovotacao trv on (rv.tipo_resultado_votacao_id = trv.id)
WHERE rv.expediente_id = em.id AND tipo_votacao != 4) rv ON TRUE
LEFT JOIN LATERAL (
SELECT em.sessao_plenaria_id,
em.numero_ordem,
jsonb_agg(jsonb_build_object(
'materia_id', em.materia_id,
'parlamentar_id', vp.parlamentar_id,
'parlamentar_nome', p.nome_parlamentar,
'voto', vp.voto
) ORDER BY em.materia_id) as votos_parlamentares
FROM sessao_votoparlamentar vp
JOIN parlamentares_parlamentar p ON (vp.parlamentar_id = p.id)
WHERE vp.expediente_id = em.id AND em.tipo_votacao != 4
GROUP BY em.sessao_plenaria_id, em.numero_ordem
ORDER BY em.sessao_plenaria_id, em.numero_ordem
) vp ON TRUE
UNION ALL
-- ORDEM DIA
SELECT od.sessao_plenaria_id,
od.id id,
'ordemdia' etapa_sessao,
od.numero_ordem,
od.materia_id,
ml.ementa,
tipo_votacao,
CASE tipo_votacao
WHEN 1 THEN 'Simbólia'
WHEN 2 THEN 'Nominal'
WHEN 3 THEN 'Secreta'
WHEN 4 THEN 'Leitura'
ELSE ''
END as tipo_votacao_descricao,
resultado_votacao,
od.resultado,
total_votos,
votos_parlamentares,
votacao_aberta
FROM sessao_ordemdia od
JOIN materia_materialegislativa ml ON (od.materia_id = ml.id)
LEFT JOIN sessao_registroleitura rl on (od.id = rl.expediente_id)
LEFT JOIN LATERAL (
SELECT jsonb_build_object(
'sim', coalesce(rv.numero_votos_sim, 0),
'não', coalesce(rv.numero_votos_nao, 0),
'abstencoes', coalesce(rv.numero_abstencoes, 0)
) as total_votos,
trv.nome resultado_votacao
FROM sessao_registrovotacao rv
JOIN sessao_tiporesultadovotacao trv on (rv.tipo_resultado_votacao_id = trv.id)
WHERE rv.expediente_id = od.id AND tipo_votacao != 4) rv ON TRUE
LEFT JOIN LATERAL (
SELECT od.sessao_plenaria_id,
od.numero_ordem,
jsonb_agg(jsonb_build_object(
'materia_id', od.materia_id,
'parlamentar_id', vp.parlamentar_id,
'parlamentar_nome', p.nome_parlamentar,
'voto', vp.voto
) ORDER BY od.materia_id) as votos_parlamentares
FROM sessao_votoparlamentar vp
JOIN parlamentares_parlamentar p ON (vp.parlamentar_id = p.id)
WHERE vp.expediente_id = od.id AND od.tipo_votacao != 4
GROUP BY od.sessao_plenaria_id, od.numero_ordem
ORDER BY od.sessao_plenaria_id, od.numero_ordem
) vp ON TRUE
)
SELECT *
FROM votacao_materias
ORDER BY sessao_plenaria_id, etapa_sessao, numero_ordem
"""
)
]
Loading…
Cancel
Save