# 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()