|
|
|
|
|
|
| import streamlit as st
|
| from datetime import datetime
|
| from sqlalchemy import func
|
|
|
|
|
| from models import IOIRunSugestao
|
|
|
|
|
| try:
|
| from utils_auditoria import registrar_log
|
| except Exception:
|
| registrar_log = None
|
|
|
|
|
| st.set_page_config(page_title="📬 Inbox Admin • IOI-RUN", layout="wide")
|
|
|
| STATUS_PENDENTE = "pendente"
|
| STATUS_RESPONDIDA = "respondida"
|
|
|
|
|
|
|
| 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**")
|
|
|
|
|
|
|
| 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()
|
|
|
|
|
|
|
| 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()
|
|
|
|
|
| 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"]
|
|
|
|
|
| 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()
|
|
|
|
|
| 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 = []
|
|
|
|
|
| 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()
|
|
|
|
|
| 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() |