File size: 7,715 Bytes
0f0ef8d |
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 |
# pages/Inbox_Admin.py
# -*- coding: utf-8 -*-
import streamlit as st
from datetime import datetime
from sqlalchemy import func
# Model
from models import IOIRunSugestao
# (Opcional) auditoria
try:
from utils_auditoria import registrar_log
except Exception:
registrar_log = None
# ------------- CONFIG BÁSICA -------------
st.set_page_config(page_title="📬 Inbox Admin • IOI-RUN", layout="wide")
STATUS_PENDENTE = "pendente"
STATUS_RESPONDIDA = "respondida"
# ------------- Sessão de banco ciente do ambiente -------------
def _get_db_session():
"""
Retorna uma sessão de banco consistente com o ambiente atual.
Tenta usar o db_router (se presente); senão, cai para SessionLocal().
"""
try:
from db_router import get_session_for_current_db
return get_session_for_current_db()
except Exception:
pass
try:
from banco import SessionLocal
return SessionLocal()
except Exception as e:
st.error(f"Banco indisponível: {e}")
raise
def _debug_banco_caption():
"""Mostra em qual banco estamos (Produção/Teste/Treinamento)."""
try:
from db_router import current_db_choice, bank_label
choice = current_db_choice()
label = bank_label(choice)
st.caption(f"🗄️ Banco ativo: **{label}**")
except Exception:
st.caption("🗄️ Banco ativo: **default**")
# ------------- Guarda de rota (somente admin) -------------
def _ensure_admin():
perfil = (st.session_state.get("perfil") or "").strip().lower()
if perfil != "admin":
st.error("Acesso negado. Esta página é restrita a administradores.")
st.stop()
# ------------- Página -------------
def main():
_ensure_admin()
st.title("📬 Caixa de Entrada • IOI‑RUN (Admin)")
st.caption("Responda sugestões dos usuários em uma página separada, sem interferência do app principal.")
_debug_banco_caption()
# Estados persistentes exclusivos desta página (prefixo 'adm_inbox_')
st.session_state.setdefault("adm_inbox_area", "todos")
st.session_state.setdefault("adm_inbox_status", STATUS_PENDENTE)
st.session_state.setdefault("adm_inbox_usuario", "")
st.session_state.setdefault("adm_inbox_nonce", 0)
AREAS = ["todos", "WMS", "FPSO", "UI/UX", "Relatórios", "Integrações", "Performance", "Segurança", "Outros"]
STATUS = [STATUS_PENDENTE, STATUS_RESPONDIDA, "todos"]
# ------------- Filtros -------------
col_f1, col_f2, col_f3, col_f4 = st.columns([1, 1, 1, 0.6])
col_f1.selectbox(
"Área/Tema",
AREAS,
key="adm_inbox_area",
index=AREAS.index(st.session_state["adm_inbox_area"]) if st.session_state["adm_inbox_area"] in AREAS else 0
)
col_f2.selectbox(
"Status",
STATUS,
key="adm_inbox_status",
index=STATUS.index(st.session_state["adm_inbox_status"]) if st.session_state["adm_inbox_status"] in STATUS else 0
)
col_f3.text_input(
"Filtrar por usuário (login exato)",
key="adm_inbox_usuario",
value=st.session_state["adm_inbox_usuario"]
)
if col_f4.button("🔄 Atualizar lista"):
st.session_state["adm_inbox_nonce"] += 1
st.rerun()
# ------------- Consulta -------------
db = _get_db_session()
try:
q = db.query(IOIRunSugestao)
if st.session_state["adm_inbox_area"] != "todos":
q = q.filter(IOIRunSugestao.area == st.session_state["adm_inbox_area"])
if st.session_state["adm_inbox_status"] != "todos":
q = q.filter(func.lower(IOIRunSugestao.status) == st.session_state["adm_inbox_status"])
if (st.session_state["adm_inbox_usuario"] or "").strip():
q = q.filter(IOIRunSugestao.usuario == (st.session_state["adm_inbox_usuario"] or "").strip())
sugestoes = q.order_by(IOIRunSugestao.data_envio.desc()).all()
except Exception as e:
st.error(f"Erro ao consultar sugestões: {e}")
sugestoes = []
# ------------- Lista / Edição -------------
if not sugestoes:
st.info("Nenhuma sugestão encontrada para os filtros aplicados.")
else:
for s in sugestoes:
dt_envio = s.data_envio.strftime("%d/%m/%Y %H:%M") if s.data_envio else "—"
titulo = f"📩 {dt_envio} — {s.usuario} — Status: {s.status or '—'}"
if s.area:
titulo += f" — Área: {s.area}"
with st.expander(titulo, expanded=False):
st.markdown("**Sugestão:**")
st.write(s.mensagem or "—")
with st.form(key=f"adm_inbox_form_{s.id}", clear_on_submit=False):
resposta_txt = st.text_area(
f"Responder ao usuário ({s.usuario}) — ID {s.id}",
value=s.resposta or "",
key=f"adm_inbox_resposta_{s.id}",
placeholder="Digite sua resposta para este usuário…",
height=140
)
col_a1, col_a2 = st.columns([1, 1])
enviar = col_a1.form_submit_button("📤 Enviar resposta")
pendenciar = col_a2.form_submit_button("⏳ Marcar como pendente")
if enviar:
try:
s.resposta = (resposta_txt or "").strip()
s.status = STATUS_RESPONDIDA if s.resposta else STATUS_PENDENTE
s.data_resposta = datetime.now() if s.resposta else None
s.responsavel = st.session_state.get("usuario")
db.add(s)
db.commit()
# Auditoria (opcional)
if registrar_log and s.resposta:
try:
registrar_log(
usuario=st.session_state.get("usuario"),
acao=f"Respondeu sugestão IOI‑RUN (ID {s.id}) para {s.usuario}",
tabela="ioirun_sugestao",
registro_id=s.id
)
except Exception:
pass
st.success("Resposta registrada com sucesso! (Agora em 'respondida')")
st.rerun()
except Exception as e:
db.rollback()
st.error(f"Erro ao salvar resposta: {e}")
if pendenciar:
try:
s.status = STATUS_PENDENTE
s.resposta = None
s.data_resposta = None
s.responsavel = None
db.add(s)
db.commit()
st.info("Sugestão marcada como pendente novamente.")
st.rerun()
except Exception as e:
db.rollback()
st.error(f"Erro ao alterar status: {e}")
st.markdown("---")
st.caption("Use o **menu lateral** para navegar para outros módulos.")
try:
db.close()
except Exception:
pass
if __name__ == "__main__":
main() |