You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
959 lines
42 KiB
Python
959 lines
42 KiB
Python
from fastapi import APIRouter, Depends, Request
|
|
from fastapi.responses import HTMLResponse, RedirectResponse, Response
|
|
|
|
from admin_app.api.dependencies import get_optional_panel_staff_context
|
|
from admin_app.core import AdminSettings, AuthenticatedStaffContext, get_admin_settings
|
|
from admin_app.services import ToolManagementService
|
|
from admin_app.view.assets import PANEL_STATIC_MOUNT_NAME
|
|
from admin_app.view.rendering import (
|
|
render_bot_monitoring_page,
|
|
render_collaborator_management_page,
|
|
render_login_page,
|
|
render_panel_home,
|
|
render_rental_reports_page,
|
|
render_sales_revenue_reports_page,
|
|
render_system_configuration_page,
|
|
render_tool_intake_page,
|
|
render_tool_review_page,
|
|
)
|
|
from admin_app.view.view_models import (
|
|
AdminBotMonitoringPageView,
|
|
AdminCollaboratorManagementPageView,
|
|
AdminLoginPageView,
|
|
AdminPanelHomeView,
|
|
AdminPanelMetric,
|
|
AdminPanelModuleCard,
|
|
AdminPanelNavigationItem,
|
|
AdminPanelQuickAction,
|
|
AdminPanelRoadmapItem,
|
|
AdminPanelSurfaceLink,
|
|
AdminRentalReportsPageView,
|
|
AdminSalesRevenueReportsPageView,
|
|
AdminSystemConfigurationPageView,
|
|
AdminToolIntakeDomainOption,
|
|
AdminToolIntakePageView,
|
|
AdminToolIntakeParameterTypeOption,
|
|
AdminToolReviewPageView,
|
|
AdminToolReviewWorkflowStep,
|
|
)
|
|
from shared.contracts import AdminPermission, StaffRole, role_has_permission
|
|
|
|
panel_router = APIRouter(tags=["panel"])
|
|
|
|
|
|
@panel_router.get("/panel", name="panel_entry")
|
|
def panel_entry(
|
|
request: Request,
|
|
current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context),
|
|
) -> RedirectResponse:
|
|
target_route_name = "panel_home" if current_context is not None else "admin_login_view"
|
|
return _redirect_to_route(request, target_route_name)
|
|
|
|
|
|
@panel_router.get("/panel/admin", response_class=HTMLResponse, name="panel_home")
|
|
def panel_home(
|
|
request: Request,
|
|
current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context),
|
|
) -> Response:
|
|
if current_context is None:
|
|
return _redirect_to_route(request, "admin_login_view")
|
|
|
|
settings = _resolve_settings(request)
|
|
view = _build_home_view(request, settings, current_context)
|
|
css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css"))
|
|
js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js"))
|
|
return HTMLResponse(render_panel_home(view, css_href=css_href, js_href=js_href))
|
|
|
|
|
|
@panel_router.get("/login", response_class=HTMLResponse, name="admin_login_view")
|
|
def login_page(
|
|
request: Request,
|
|
current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context),
|
|
) -> Response:
|
|
if current_context is not None:
|
|
return _redirect_to_route(request, "panel_home")
|
|
|
|
settings = _resolve_settings(request)
|
|
view = _build_login_view(request, settings)
|
|
css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css"))
|
|
js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js"))
|
|
return HTMLResponse(render_login_page(view, css_href=css_href, js_href=js_href))
|
|
|
|
|
|
@panel_router.get("/panel/tools/new", response_class=HTMLResponse, name="admin_tool_intake_view")
|
|
def tool_intake_page(
|
|
request: Request,
|
|
current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context),
|
|
) -> Response:
|
|
if current_context is None:
|
|
return _redirect_to_route(request, "admin_login_view")
|
|
|
|
settings = _resolve_settings(request)
|
|
view = _build_tool_intake_view(request, settings, current_context.principal.role)
|
|
css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css"))
|
|
js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js"))
|
|
return HTMLResponse(render_tool_intake_page(view, css_href=css_href, js_href=js_href))
|
|
|
|
|
|
@panel_router.get("/panel/tools/review", response_class=HTMLResponse, name="admin_tool_review_view")
|
|
def tool_review_page(
|
|
request: Request,
|
|
current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context),
|
|
) -> Response:
|
|
if current_context is None:
|
|
return _redirect_to_route(request, "admin_login_view")
|
|
|
|
settings = _resolve_settings(request)
|
|
view = _build_tool_review_view(request, settings)
|
|
css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css"))
|
|
js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js"))
|
|
return HTMLResponse(render_tool_review_page(view, css_href=css_href, js_href=js_href))
|
|
|
|
|
|
@panel_router.get("/panel/colaboradores/gestao", response_class=HTMLResponse, name="admin_collaborator_management_view")
|
|
def collaborator_management_page(
|
|
request: Request,
|
|
current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context),
|
|
) -> Response:
|
|
if current_context is None:
|
|
return _redirect_to_route(request, "admin_login_view")
|
|
if not role_has_permission(current_context.principal.role, AdminPermission.MANAGE_STAFF_ACCOUNTS):
|
|
return _redirect_to_route(request, "panel_home")
|
|
|
|
settings = _resolve_settings(request)
|
|
view = _build_collaborator_management_view(request, settings)
|
|
css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css"))
|
|
js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js"))
|
|
return HTMLResponse(render_collaborator_management_page(view, css_href=css_href, js_href=js_href))
|
|
|
|
|
|
@panel_router.get("/panel/sistema/configuracoes", response_class=HTMLResponse, name="admin_system_configuration_view")
|
|
def system_configuration_page(
|
|
request: Request,
|
|
current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context),
|
|
) -> Response:
|
|
if current_context is None:
|
|
return _redirect_to_route(request, "admin_login_view")
|
|
if not role_has_permission(current_context.principal.role, AdminPermission.VIEW_SYSTEM):
|
|
return _redirect_to_route(request, "panel_home")
|
|
|
|
settings = _resolve_settings(request)
|
|
view = _build_system_configuration_view(request, settings)
|
|
css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css"))
|
|
js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js"))
|
|
return HTMLResponse(render_system_configuration_page(view, css_href=css_href, js_href=js_href))
|
|
|
|
|
|
@panel_router.get("/panel/relatorios/vendas-arrecadacao", response_class=HTMLResponse, name="admin_sales_revenue_reports_view")
|
|
def sales_revenue_reports_page(
|
|
request: Request,
|
|
current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context),
|
|
) -> Response:
|
|
if current_context is None:
|
|
return _redirect_to_route(request, "admin_login_view")
|
|
if not role_has_permission(current_context.principal.role, AdminPermission.VIEW_REPORTS):
|
|
return _redirect_to_route(request, "panel_home")
|
|
|
|
settings = _resolve_settings(request)
|
|
view = _build_sales_revenue_reports_view(request, settings)
|
|
css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css"))
|
|
js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js"))
|
|
return HTMLResponse(render_sales_revenue_reports_page(view, css_href=css_href, js_href=js_href))
|
|
|
|
|
|
@panel_router.get("/panel/relatorios/locacao", response_class=HTMLResponse, name="admin_rental_reports_view")
|
|
def rental_reports_page(
|
|
request: Request,
|
|
current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context),
|
|
) -> Response:
|
|
if current_context is None:
|
|
return _redirect_to_route(request, "admin_login_view")
|
|
if not role_has_permission(current_context.principal.role, AdminPermission.VIEW_REPORTS):
|
|
return _redirect_to_route(request, "panel_home")
|
|
|
|
settings = _resolve_settings(request)
|
|
view = _build_rental_reports_view(request, settings)
|
|
css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css"))
|
|
js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js"))
|
|
return HTMLResponse(render_rental_reports_page(view, css_href=css_href, js_href=js_href))
|
|
|
|
|
|
@panel_router.get("/panel/monitoramento/bot", response_class=HTMLResponse, name="admin_bot_monitoring_view")
|
|
def bot_monitoring_page(
|
|
request: Request,
|
|
current_context: AuthenticatedStaffContext | None = Depends(get_optional_panel_staff_context),
|
|
) -> Response:
|
|
if current_context is None:
|
|
return _redirect_to_route(request, "admin_login_view")
|
|
if not role_has_permission(current_context.principal.role, AdminPermission.VIEW_REPORTS):
|
|
return _redirect_to_route(request, "panel_home")
|
|
|
|
settings = _resolve_settings(request)
|
|
view = _build_bot_monitoring_view(request, settings)
|
|
css_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="styles/panel.css"))
|
|
js_href = str(request.url_for(PANEL_STATIC_MOUNT_NAME, path="scripts/panel.js"))
|
|
return HTMLResponse(render_bot_monitoring_page(view, css_href=css_href, js_href=js_href))
|
|
|
|
|
|
def _build_home_view(
|
|
request: Request,
|
|
settings: AdminSettings,
|
|
current_context: AuthenticatedStaffContext,
|
|
) -> AdminPanelHomeView:
|
|
panel_href = str(request.url_for("panel_home"))
|
|
tool_intake_view_href = str(request.url_for("admin_tool_intake_view"))
|
|
tool_review_view_href = str(request.url_for("admin_tool_review_view"))
|
|
collaborator_management_view_href = str(request.url_for("admin_collaborator_management_view"))
|
|
system_configuration_view_href = str(request.url_for("admin_system_configuration_view"))
|
|
sales_revenue_reports_view_href = str(request.url_for("admin_sales_revenue_reports_view"))
|
|
rental_reports_view_href = str(request.url_for("admin_rental_reports_view"))
|
|
bot_monitoring_view_href = str(request.url_for("admin_bot_monitoring_view"))
|
|
audit_href = _build_prefixed_path(settings.admin_api_prefix, "/audit/events")
|
|
can_manage_collaborators = role_has_permission(
|
|
current_context.principal.role,
|
|
AdminPermission.MANAGE_STAFF_ACCOUNTS,
|
|
)
|
|
|
|
navigation = [
|
|
AdminPanelNavigationItem(
|
|
label="Dashboard",
|
|
href=panel_href,
|
|
description="Entrada principal do ambiente interno.",
|
|
badge="Ativo",
|
|
is_active=True,
|
|
),
|
|
AdminPanelNavigationItem(
|
|
label="Cadastro de tools",
|
|
href=tool_intake_view_href,
|
|
description="Pre-cadastro validado para novas tools antes da revisao.",
|
|
badge="Novo",
|
|
),
|
|
AdminPanelNavigationItem(
|
|
label="Revisao de tools",
|
|
href=tool_review_view_href,
|
|
description="Fluxo humano de revisao, aprovacao e ativacao.",
|
|
badge="Operacao",
|
|
),
|
|
AdminPanelNavigationItem(
|
|
label="Configuracoes do sistema",
|
|
href=system_configuration_view_href,
|
|
description="Leitura funcional, runtime e governanca do admin em uma tela dedicada.",
|
|
badge="Fase 4",
|
|
),
|
|
AdminPanelNavigationItem(
|
|
label="Relatorios comerciais",
|
|
href=sales_revenue_reports_view_href,
|
|
description="Tela combinada para vendas e arrecadacao dentro da sessao do painel.",
|
|
badge="Relatorios",
|
|
),
|
|
AdminPanelNavigationItem(
|
|
label="Relatorios de locacao",
|
|
href=rental_reports_view_href,
|
|
description="Tela dedicada para frota, contratos e ocupacao na sessao do painel.",
|
|
badge="Locacao",
|
|
),
|
|
AdminPanelNavigationItem(
|
|
label="Monitoramento do bot",
|
|
href=bot_monitoring_view_href,
|
|
description="Fluxo operacional e telemetria conversacional em uma superficie dedicada.",
|
|
badge="Bot",
|
|
),
|
|
AdminPanelNavigationItem(
|
|
label="Areas do sistema",
|
|
href="#modules",
|
|
description="Mapa claro dos modulos internos disponiveis.",
|
|
badge="Painel",
|
|
),
|
|
AdminPanelNavigationItem(
|
|
label="Fluxo recomendado",
|
|
href="#workflow",
|
|
description="Sequencia sugerida para operar o admin.",
|
|
badge="Guia",
|
|
),
|
|
]
|
|
quick_actions = [
|
|
AdminPanelQuickAction(
|
|
label="Cadastrar tool",
|
|
href=tool_intake_view_href,
|
|
button_class="btn-dark",
|
|
),
|
|
AdminPanelQuickAction(
|
|
label="Revisar tools",
|
|
href=tool_review_view_href,
|
|
button_class="btn-outline-dark",
|
|
),
|
|
AdminPanelQuickAction(
|
|
label="Config. sistema",
|
|
href=system_configuration_view_href,
|
|
button_class="btn-outline-secondary",
|
|
),
|
|
AdminPanelQuickAction(
|
|
label="Relatorios",
|
|
href=sales_revenue_reports_view_href,
|
|
button_class="btn-outline-dark",
|
|
),
|
|
AdminPanelQuickAction(
|
|
label="Locacao",
|
|
href=rental_reports_view_href,
|
|
button_class="btn-outline-dark",
|
|
),
|
|
AdminPanelQuickAction(
|
|
label="Monitorar bot",
|
|
href=bot_monitoring_view_href,
|
|
button_class="btn-outline-dark",
|
|
),
|
|
]
|
|
modules = [
|
|
AdminPanelModuleCard(
|
|
eyebrow="Fluxo de entrada",
|
|
title="Cadastro de tools",
|
|
description="Tela real para o colaborador preencher metadados, definir parametros e validar o pre-cadastro antes da revisao humana.",
|
|
status_label="Tela ativa",
|
|
status_variant="success",
|
|
highlights=(
|
|
"Formulario protegido por sessao web",
|
|
"Draft persistido logo apos a validacao",
|
|
"Direcao clara para revisao de diretor",
|
|
),
|
|
cta_label="Abrir cadastro",
|
|
href=tool_intake_view_href,
|
|
is_available=True,
|
|
),
|
|
AdminPanelModuleCard(
|
|
eyebrow="Fluxo principal",
|
|
title="Revisao de tools",
|
|
description="Area operacional do painel para leitura da fila, aprovacao humana e ativacao controlada.",
|
|
status_label="Tela ativa",
|
|
status_variant="success",
|
|
highlights=(
|
|
"Fila protegida por sessao web",
|
|
"Catalogo ativo para comparacao",
|
|
"Leitura clara do workflow de aprovacao",
|
|
),
|
|
cta_label="Abrir revisao",
|
|
href=tool_review_view_href,
|
|
is_available=True,
|
|
),
|
|
AdminPanelModuleCard(
|
|
eyebrow="Acompanhamento",
|
|
title="Configuracao do sistema",
|
|
description="Tela dedicada para consultar configuracao funcional, runtime administrativo e governanca do sistema sem sair do painel.",
|
|
status_label="Tela ativa",
|
|
status_variant="primary",
|
|
highlights=(
|
|
"Catalogo funcional e governanca do bot conectados",
|
|
"Runtime e seguranca carregados por permissao",
|
|
"Separacao de modelos visivel na mesma superficie",
|
|
),
|
|
cta_label="Abrir configuracoes",
|
|
href=system_configuration_view_href,
|
|
is_available=True,
|
|
),
|
|
AdminPanelModuleCard(
|
|
eyebrow="Relatorios operacionais",
|
|
title="Relatorios de vendas e arrecadacao",
|
|
description="Tela dedicada para acompanhar o bootstrap de vendas e arrecadacao com leitura pronta para sessao web do painel.",
|
|
status_label="Tela ativa",
|
|
status_variant="info",
|
|
highlights=(
|
|
"Vendas e arrecadacao na mesma superficie",
|
|
"Leitura protegida por sessao web",
|
|
"Materializacao e proximos passos visiveis na UI",
|
|
),
|
|
cta_label="Abrir relatorios",
|
|
href=sales_revenue_reports_view_href,
|
|
is_available=True,
|
|
),
|
|
AdminPanelModuleCard(
|
|
eyebrow="Relatorios operacionais",
|
|
title="Relatorios de locacao",
|
|
description="Tela dedicada para acompanhar a estrutura inicial de frota e contratos de locacao pela sessao web do painel.",
|
|
status_label="Tela ativa",
|
|
status_variant="info",
|
|
highlights=(
|
|
"Frota e contratos lidos na mesma superficie",
|
|
"Leitura protegida por sessao web",
|
|
"Catalogo inicial e materializacao visiveis na UI",
|
|
),
|
|
cta_label="Abrir locacao",
|
|
href=rental_reports_view_href,
|
|
is_available=True,
|
|
),
|
|
AdminPanelModuleCard(
|
|
eyebrow="Monitoramento operacional",
|
|
title="Monitoramento do bot",
|
|
description="Tela dedicada para acompanhar fluxo operacional e telemetria conversacional pela sessao web do painel.",
|
|
status_label="Tela ativa",
|
|
status_variant="info",
|
|
highlights=(
|
|
"Fluxo do bot e telemetria na mesma superficie",
|
|
"Leitura protegida por sessao web",
|
|
"Materializacao e proximos passos visiveis na UI",
|
|
),
|
|
cta_label="Abrir monitoramento",
|
|
href=bot_monitoring_view_href,
|
|
is_available=True,
|
|
),
|
|
AdminPanelModuleCard(
|
|
eyebrow="Governanca",
|
|
title="Auditoria operacional",
|
|
description="Eventos de login, logout, aprovacao e publicacao continuam registrados para rastreabilidade.",
|
|
status_label="Auditavel",
|
|
status_variant="secondary",
|
|
highlights=(
|
|
"Historico de operacao interna",
|
|
"Base para filtros e timeline",
|
|
"Suporte a conformidade do fluxo administrativo",
|
|
),
|
|
),
|
|
]
|
|
surface_links = [
|
|
AdminPanelSurfaceLink(
|
|
method="Acesso",
|
|
label="Dashboard administrativa",
|
|
href=panel_href,
|
|
description="Entrada principal do time interno depois do login.",
|
|
),
|
|
AdminPanelSurfaceLink(
|
|
method="Cadastro",
|
|
label="Nova tool",
|
|
href=tool_intake_view_href,
|
|
description="Formulario real para validar o pre-cadastro de uma nova tool.",
|
|
),
|
|
AdminPanelSurfaceLink(
|
|
method="Operacao",
|
|
label="Revisao de tools",
|
|
href=tool_review_view_href,
|
|
description="Area com fila, contrato e catalogo ativo para tomada de decisao.",
|
|
),
|
|
AdminPanelSurfaceLink(
|
|
method="Sistema",
|
|
label="Configuracoes do sistema",
|
|
href=system_configuration_view_href,
|
|
description="Tela dedicada para leitura funcional, runtime e governanca administrativa.",
|
|
),
|
|
AdminPanelSurfaceLink(
|
|
method="Relatorios",
|
|
label="Vendas e arrecadacao",
|
|
href=sales_revenue_reports_view_href,
|
|
description="Tela combinada para a primeira camada visual dos relatorios comerciais da fase 4.",
|
|
),
|
|
AdminPanelSurfaceLink(
|
|
method="Relatorios",
|
|
label="Locacao",
|
|
href=rental_reports_view_href,
|
|
description="Tela dedicada para a estrutura inicial de frota, contratos e ocupacao da fase 4.",
|
|
),
|
|
AdminPanelSurfaceLink(
|
|
method="Monitoramento",
|
|
label="Bot operacional",
|
|
href=bot_monitoring_view_href,
|
|
description="Tela dedicada para fluxo operacional e telemetria conversacional do bot na fase 4.",
|
|
),
|
|
AdminPanelSurfaceLink(
|
|
method="Auditoria",
|
|
label="Eventos administrativos",
|
|
href=audit_href,
|
|
description="Consulta de eventos internos para rastrear operacoes sensiveis.",
|
|
),
|
|
]
|
|
roadmap = [
|
|
AdminPanelRoadmapItem(
|
|
step="01",
|
|
title="Entrar pelo login administrativo",
|
|
description="A sessao web libera o ambiente interno e evita navegacao confusa antes da autenticacao.",
|
|
status_label="Obrigatorio",
|
|
),
|
|
AdminPanelRoadmapItem(
|
|
step="02",
|
|
title="Passar pela dashboard",
|
|
description="A home protegida organiza os modulos e mostra por onde comecar a operacao.",
|
|
status_label="Entrada",
|
|
),
|
|
AdminPanelRoadmapItem(
|
|
step="03",
|
|
title="Cadastrar ou validar o pre-draft",
|
|
description="Use a nova tela para descrever a tool, seus parametros e o objetivo operacional antes da revisao.",
|
|
status_label="Cadastro",
|
|
),
|
|
AdminPanelRoadmapItem(
|
|
step="04",
|
|
title="Abrir revisao de tools",
|
|
description="Encaminhe a ferramenta para analise humana, aprovacao e ativacao controlada.",
|
|
status_label="Principal",
|
|
),
|
|
AdminPanelRoadmapItem(
|
|
step="05",
|
|
title="Consultar runtime e auditoria",
|
|
description="Quando necessario, acompanhe configuracao e eventos do admin para suportar a decisao operacional.",
|
|
status_label="Suporte",
|
|
),
|
|
]
|
|
|
|
if can_manage_collaborators:
|
|
navigation.insert(
|
|
3,
|
|
AdminPanelNavigationItem(
|
|
label="Colaboradores",
|
|
href=collaborator_management_view_href,
|
|
description="Cadastro e governanca de acessos internos, exclusivo para diretor.",
|
|
badge="Diretor",
|
|
),
|
|
)
|
|
quick_actions.insert(
|
|
2,
|
|
AdminPanelQuickAction(
|
|
label="Gerir equipe",
|
|
href=collaborator_management_view_href,
|
|
button_class="btn-outline-dark",
|
|
),
|
|
)
|
|
modules.insert(
|
|
2,
|
|
AdminPanelModuleCard(
|
|
eyebrow="Governanca de acesso",
|
|
title="Gestao de colaboradores",
|
|
description="Tela dedicada para o diretor criar contas internas, acompanhar o status da equipe e manter a entrada administrativa sob controle.",
|
|
status_label="Tela ativa",
|
|
status_variant="dark",
|
|
highlights=(
|
|
"Criacao de colaborador com senha inicial",
|
|
"Ativacao e desativacao sem tocar no banco manualmente",
|
|
"Fluxo exclusivo para diretor",
|
|
),
|
|
cta_label="Abrir equipe",
|
|
href=collaborator_management_view_href,
|
|
is_available=True,
|
|
),
|
|
)
|
|
surface_links.insert(
|
|
3,
|
|
AdminPanelSurfaceLink(
|
|
method="Equipe",
|
|
label="Gestao de colaboradores",
|
|
href=collaborator_management_view_href,
|
|
description="Controle de acesso interno para cadastrar e administrar a equipe administrativa.",
|
|
),
|
|
)
|
|
roadmap = [
|
|
AdminPanelRoadmapItem(
|
|
step="01",
|
|
title="Entrar pelo login administrativo",
|
|
description="A sessao web libera o ambiente interno e evita navegacao confusa antes da autenticacao.",
|
|
status_label="Obrigatorio",
|
|
),
|
|
AdminPanelRoadmapItem(
|
|
step="02",
|
|
title="Passar pela dashboard",
|
|
description="A home protegida organiza os modulos e mostra por onde comecar a operacao.",
|
|
status_label="Entrada",
|
|
),
|
|
AdminPanelRoadmapItem(
|
|
step="03",
|
|
title="Cadastrar ou validar o pre-draft",
|
|
description="Use a nova tela para descrever a tool, seus parametros e o objetivo operacional antes da revisao.",
|
|
status_label="Cadastro",
|
|
),
|
|
AdminPanelRoadmapItem(
|
|
step="04",
|
|
title="Organizar a equipe interna",
|
|
description="Diretores podem cadastrar novos colaboradores e controlar rapidamente o status de acesso administrativo.",
|
|
status_label="Diretor",
|
|
),
|
|
AdminPanelRoadmapItem(
|
|
step="05",
|
|
title="Abrir revisao de tools",
|
|
description="Encaminhe a ferramenta para analise humana, aprovacao e ativacao controlada.",
|
|
status_label="Principal",
|
|
),
|
|
AdminPanelRoadmapItem(
|
|
step="06",
|
|
title="Consultar runtime e auditoria",
|
|
description="Quando necessario, acompanhe configuracao e eventos do admin para suportar a decisao operacional.",
|
|
status_label="Suporte",
|
|
),
|
|
]
|
|
|
|
return AdminPanelHomeView(
|
|
service="orquestrador-admin",
|
|
app_name=settings.admin_app_name,
|
|
panel_title="Painel Administrativo",
|
|
panel_subtitle=(
|
|
"Area interna protegida para operar o admin com mais clareza, foco e navegacao orientada por fluxo."
|
|
),
|
|
environment=settings.admin_environment,
|
|
version=settings.admin_version,
|
|
api_prefix=settings.admin_api_prefix or "/",
|
|
release_label="Bootstrap UI v1",
|
|
navigation=tuple(navigation),
|
|
quick_actions=tuple(quick_actions),
|
|
metrics=(
|
|
AdminPanelMetric(
|
|
label="Runtimes independentes",
|
|
value="2",
|
|
description="Produto e admin seguem isolados para deploy e operacao.",
|
|
),
|
|
AdminPanelMetric(
|
|
label="Perfis internos",
|
|
value=str(len(StaffRole)),
|
|
description="Hierarquia base com colaborador e diretor.",
|
|
),
|
|
AdminPanelMetric(
|
|
label="Permissoes administrativas",
|
|
value=str(len(AdminPermission)),
|
|
description="Camada pronta para crescer por modulo sem misturar contexto.",
|
|
),
|
|
AdminPanelMetric(
|
|
label="Refresh token",
|
|
value=f"{settings.admin_auth_refresh_token_ttl_days} dias",
|
|
description="Sessao web persistida com renovacao controlada.",
|
|
),
|
|
),
|
|
modules=tuple(modules),
|
|
surface_links=tuple(surface_links),
|
|
roadmap=tuple(roadmap),
|
|
)
|
|
|
|
|
|
def _build_login_view(request: Request, settings: AdminSettings) -> AdminLoginPageView:
|
|
dashboard_href = str(request.url_for("panel_home"))
|
|
auth_endpoint = _build_prefixed_path(settings.admin_api_prefix, "/panel/auth/login")
|
|
password_requirements = []
|
|
if settings.admin_auth_password_require_uppercase:
|
|
password_requirements.append("maiuscula")
|
|
if settings.admin_auth_password_require_lowercase:
|
|
password_requirements.append("minuscula")
|
|
if settings.admin_auth_password_require_digit:
|
|
password_requirements.append("digito")
|
|
if settings.admin_auth_password_require_symbol:
|
|
password_requirements.append("simbolo")
|
|
|
|
password_policy_label = (
|
|
f"Minimo de {settings.admin_auth_password_min_length} caracteres"
|
|
+ (f" com {', '.join(password_requirements)}." if password_requirements else ".")
|
|
)
|
|
|
|
return AdminLoginPageView(
|
|
app_name=settings.admin_app_name,
|
|
title="Login administrativo",
|
|
subtitle=(
|
|
"Entre primeiro com sua conta interna. A dashboard e os modulos do sistema so aparecem depois da autenticacao."
|
|
),
|
|
environment=settings.admin_environment,
|
|
version=settings.admin_version,
|
|
dashboard_href=dashboard_href,
|
|
auth_endpoint=auth_endpoint,
|
|
email_placeholder="voce@empresa.com",
|
|
password_placeholder="Sua senha administrativa",
|
|
access_token_ttl_label=f"{settings.admin_auth_access_token_ttl_minutes} minutos",
|
|
refresh_token_ttl_label=f"{settings.admin_auth_refresh_token_ttl_days} dias",
|
|
password_policy_label=password_policy_label,
|
|
security_highlights=(
|
|
"Identidade separada do usuario de atendimento",
|
|
"Rotacao de refresh token ja implementada",
|
|
"Trilha de auditoria para login e logout",
|
|
),
|
|
integration_notes=(
|
|
"A dashboard administrativa so aparece depois da autenticacao do StaffAccount.",
|
|
"Revisao, configuracao e operacao interna ficam atras da sessao web do painel.",
|
|
"Cookies httpOnly e refresh token rotacionado mantem a sessao do navegador protegida.",
|
|
),
|
|
)
|
|
|
|
|
|
def _build_tool_intake_view(
|
|
request: Request,
|
|
settings: AdminSettings,
|
|
current_role: StaffRole | str | None,
|
|
) -> AdminToolIntakePageView:
|
|
service = ToolManagementService(settings)
|
|
form_payload = service.build_draft_form_payload(submitter_role=current_role)
|
|
|
|
return AdminToolIntakePageView(
|
|
app_name=settings.admin_app_name,
|
|
title="Cadastro de nova tool",
|
|
subtitle=(
|
|
"Formulario guiado para estruturar uma proposta de tool, registrar o draft versionado e encaminhar a triagem humana antes de qualquer geracao de codigo."
|
|
),
|
|
environment=settings.admin_environment,
|
|
version=settings.admin_version,
|
|
dashboard_href=str(request.url_for("panel_home")),
|
|
review_href=str(request.url_for("admin_tool_review_view")),
|
|
intake_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/tools/drafts/intake"),
|
|
domain_options=tuple(
|
|
AdminToolIntakeDomainOption(
|
|
value=item["value"],
|
|
label=item["label"],
|
|
description=item["description"],
|
|
)
|
|
for item in form_payload["domain_options"]
|
|
),
|
|
parameter_type_options=tuple(
|
|
AdminToolIntakeParameterTypeOption(
|
|
value=item["code"].value,
|
|
label=item["label"],
|
|
description=item["description"],
|
|
)
|
|
for item in form_payload["parameter_types"]
|
|
),
|
|
naming_rules=tuple(form_payload["naming_rules"]),
|
|
submission_notes=tuple(form_payload["submission_notes"]),
|
|
approval_notes=tuple(form_payload["approval_notes"]),
|
|
)
|
|
|
|
|
|
def _build_tool_review_view(request: Request, settings: AdminSettings) -> AdminToolReviewPageView:
|
|
dashboard_href = str(request.url_for("panel_home"))
|
|
overview_endpoint = _build_prefixed_path(settings.admin_api_prefix, "/panel/tools/overview")
|
|
contracts_endpoint = _build_prefixed_path(settings.admin_api_prefix, "/panel/tools/contracts")
|
|
review_queue_endpoint = _build_prefixed_path(settings.admin_api_prefix, "/panel/tools/review-queue")
|
|
publications_endpoint = _build_prefixed_path(settings.admin_api_prefix, "/panel/tools/publications")
|
|
|
|
return AdminToolReviewPageView(
|
|
app_name=settings.admin_app_name,
|
|
title="Triagem, revisao e ativacao",
|
|
subtitle=(
|
|
"Hub visual para acompanhar a proposta da tool desde a triagem para geracao, passando pelas iteracoes de codigo, ate a ativacao controlada no catalogo do produto."
|
|
),
|
|
environment=settings.admin_environment,
|
|
version=settings.admin_version,
|
|
dashboard_href=dashboard_href,
|
|
overview_endpoint=overview_endpoint,
|
|
contracts_endpoint=contracts_endpoint,
|
|
review_queue_endpoint=review_queue_endpoint,
|
|
publications_endpoint=publications_endpoint,
|
|
workflow=(
|
|
AdminToolReviewWorkflowStep(
|
|
eyebrow="Cadastro manual",
|
|
title="Criar a proposta",
|
|
description="Receber o cadastro manual da tool e consolidar o draft administrativo sem consumir geracao de codigo.",
|
|
status_label="Draft",
|
|
status_variant="info",
|
|
),
|
|
AdminToolReviewWorkflowStep(
|
|
eyebrow="Triagem humana",
|
|
title="Triar antes de gerar",
|
|
description="Decidir se a proposta realmente merece consumir geracao de codigo ou deve ser encerrada antes disso.",
|
|
status_label="Triagem",
|
|
status_variant="warning",
|
|
),
|
|
AdminToolReviewWorkflowStep(
|
|
eyebrow="Pipeline",
|
|
title="Gerar ou refatorar",
|
|
description="Executar a geracao isolada, registrar a iteracao correspondente e validar automaticamente o codigo antes da leitura humana.",
|
|
status_label="Geracao",
|
|
status_variant="info",
|
|
),
|
|
AdminToolReviewWorkflowStep(
|
|
eyebrow="Decisao humana",
|
|
title="Ler e decidir",
|
|
description="A diretoria revisa a iteracao atual do codigo, pede ajustes quando necessario ou valida a versao para aprovacao final.",
|
|
status_label="Revisao",
|
|
status_variant="warning",
|
|
),
|
|
AdminToolReviewWorkflowStep(
|
|
eyebrow="Publicacao",
|
|
title="Ativar com governanca",
|
|
description="Publicar apenas a iteracao aprovada e sincronizar o catalogo que abastece o runtime de produto.",
|
|
status_label="Ativacao",
|
|
status_variant="success",
|
|
),
|
|
),
|
|
review_notes=(
|
|
"Conferir se a proposta esta no gate correto: triagem para geracao, ajustes solicitados ou leitura do codigo atual.",
|
|
"Observar se a descricao, o objetivo operacional e os parametros deixam claro o valor de negocio da tool.",
|
|
"Ler o codigo completo da iteracao atual antes de validar, solicitar ajustes ou encerrar a proposta.",
|
|
),
|
|
approval_notes=(
|
|
"Verificar nome, descricao, semantica dos parametros e a iteracao que esta sendo aprovada antes da ativacao.",
|
|
"Confirmar se a tool respeita a separacao entre admin e product definida nas ADRs e nos contratos compartilhados.",
|
|
"Checar se a publicacao planejada e auditavel, segura e vinculada ao codigo mais recente revisado pela diretoria.",
|
|
),
|
|
activation_notes=(
|
|
"Publicacoes ativas exigem papel com permissao publish_tools e aprovacao humana vinculada a iteracao mais recente.",
|
|
"A leitura do catalogo e feita via sessao web do painel para facilitar a operacao do navegador e a auditoria do fluxo.",
|
|
"Sem permissao de publicacao, a tela continua util para triagem e revisao, mas bloqueia a ativacao no catalogo ativo.",
|
|
),
|
|
)
|
|
|
|
|
|
|
|
def _build_sales_revenue_reports_view(
|
|
request: Request,
|
|
settings: AdminSettings,
|
|
) -> AdminSalesRevenueReportsPageView:
|
|
return AdminSalesRevenueReportsPageView(
|
|
app_name=settings.admin_app_name,
|
|
title="Relatorios de vendas e arrecadacao",
|
|
subtitle=(
|
|
"Visao unica para acompanhar vendas e arrecadacao no painel administrativo."
|
|
),
|
|
environment=settings.admin_environment,
|
|
version=settings.admin_version,
|
|
dashboard_href=str(request.url_for("panel_home")),
|
|
sales_overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/reports/sales/overview"),
|
|
revenue_overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/reports/arrecadacao/overview"),
|
|
access_notes=(
|
|
"A equipe interna pode consultar esta tela com a permissao de relatorios.",
|
|
"Os dados exibidos aparecem de forma consolidada para leitura segura no admin.",
|
|
"Vendas e arrecadacao ficam juntas para facilitar a rotina do time.",
|
|
),
|
|
reading_notes=(
|
|
"Comece pelos indicadores de cada bloco para ter uma leitura rapida.",
|
|
"Use os cards para entender rapidamente o foco de cada relatorio.",
|
|
"A area de proximas melhorias mostra o que entra nas etapas seguintes.",
|
|
),
|
|
)
|
|
|
|
|
|
def _build_rental_reports_view(
|
|
request: Request,
|
|
settings: AdminSettings,
|
|
) -> AdminRentalReportsPageView:
|
|
return AdminRentalReportsPageView(
|
|
app_name=settings.admin_app_name,
|
|
title="Relatorios de locacao",
|
|
subtitle=(
|
|
"Visao dedicada da locacao para acompanhar frota, contratos e receita operacional."
|
|
),
|
|
environment=settings.admin_environment,
|
|
version=settings.admin_version,
|
|
dashboard_href=str(request.url_for("panel_home")),
|
|
overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/reports/locacao/overview"),
|
|
access_notes=(
|
|
"A equipe interna pode consultar esta tela com a permissao de relatorios.",
|
|
"Os dados exibidos aparecem de forma consolidada para leitura segura no admin.",
|
|
"Locacao fica em uma tela propria para manter a leitura mais organizada.",
|
|
),
|
|
reading_notes=(
|
|
"Comece pelos indicadores principais para entender o momento da operacao.",
|
|
"Use os cards para ver rapidamente os temas cobertos nesta etapa.",
|
|
"A area de proximas melhorias indica o que ainda entra nas proximas entregas.",
|
|
),
|
|
)
|
|
|
|
|
|
def _build_bot_monitoring_view(
|
|
request: Request,
|
|
settings: AdminSettings,
|
|
) -> AdminBotMonitoringPageView:
|
|
return AdminBotMonitoringPageView(
|
|
app_name=settings.admin_app_name,
|
|
title="Monitoramento operacional do bot",
|
|
subtitle=(
|
|
"Painel unico para acompanhar o fluxo do bot e a telemetria do atendimento."
|
|
),
|
|
environment=settings.admin_environment,
|
|
version=settings.admin_version,
|
|
dashboard_href=str(request.url_for("panel_home")),
|
|
bot_flow_overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/reports/fluxo-bot/overview"),
|
|
telemetry_overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/reports/telemetria-conversacional/overview"),
|
|
access_notes=(
|
|
"A equipe interna pode consultar esta tela com a permissao de relatorios.",
|
|
"Os dados exibidos aparecem de forma consolidada para leitura segura no painel.",
|
|
"Fluxo e telemetria ficam juntos para agilizar a analise da operacao.",
|
|
),
|
|
reading_notes=(
|
|
"Comece pelo fluxo do bot para localizar status, desvios e pontos de atencao.",
|
|
"Use a telemetria para acompanhar volume, latencia e saude do atendimento.",
|
|
"A area de proximas melhorias resume o que ainda entra antes dos dashboards completos.",
|
|
),
|
|
)
|
|
|
|
|
|
def _build_system_configuration_view(
|
|
request: Request,
|
|
settings: AdminSettings,
|
|
) -> AdminSystemConfigurationPageView:
|
|
return AdminSystemConfigurationPageView(
|
|
app_name=settings.admin_app_name,
|
|
title="Configuracoes do sistema",
|
|
subtitle=(
|
|
"Visao unica do catalogo funcional, das regras do atendimento e das protecoes do painel."
|
|
),
|
|
environment=settings.admin_environment,
|
|
version=settings.admin_version,
|
|
dashboard_href=str(request.url_for("panel_home")),
|
|
overview_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration"),
|
|
runtime_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/runtime"),
|
|
security_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/security"),
|
|
model_runtimes_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/model-runtimes"),
|
|
functional_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/functional"),
|
|
functional_detail_base=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/functional"),
|
|
bot_governance_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/system/configuration/functional/bot-governance"),
|
|
access_notes=(
|
|
"A equipe interna ja consegue consultar o catalogo funcional e os ajustes do atendimento nesta tela.",
|
|
"Detalhes mais sensiveis do ambiente continuam reservados para perfis com permissao elevada.",
|
|
"Toda a superficie segue somente leitura nesta etapa.",
|
|
),
|
|
governance_notes=(
|
|
"Configuracoes do atendimento e da geracao de tools aparecem separadas para evitar confusao.",
|
|
"Os ajustes do bot continuam bloqueados para escrita direta nas tabelas operacionais.",
|
|
"O foco aqui e leitura clara do estado atual antes da futura tela de edicao.",
|
|
),
|
|
)
|
|
|
|
|
|
def _build_collaborator_management_view(
|
|
request: Request,
|
|
settings: AdminSettings,
|
|
) -> AdminCollaboratorManagementPageView:
|
|
password_requirements = []
|
|
if settings.admin_auth_password_require_uppercase:
|
|
password_requirements.append("maiuscula")
|
|
if settings.admin_auth_password_require_lowercase:
|
|
password_requirements.append("minuscula")
|
|
if settings.admin_auth_password_require_digit:
|
|
password_requirements.append("digito")
|
|
if settings.admin_auth_password_require_symbol:
|
|
password_requirements.append("simbolo")
|
|
|
|
password_policy_label = (
|
|
f"Minimo de {settings.admin_auth_password_min_length} caracteres"
|
|
+ (f" com {', '.join(password_requirements)}." if password_requirements else ".")
|
|
)
|
|
|
|
return AdminCollaboratorManagementPageView(
|
|
app_name=settings.admin_app_name,
|
|
title="Gestao de colaboradores",
|
|
subtitle=(
|
|
"Tela exclusiva de diretor para organizar a equipe interna, criar novos acessos administrativos e controlar rapidamente quem segue ativo no painel."
|
|
),
|
|
environment=settings.admin_environment,
|
|
version=settings.admin_version,
|
|
dashboard_href=str(request.url_for("panel_home")),
|
|
collection_endpoint=_build_prefixed_path(settings.admin_api_prefix, "/panel/colaboradores"),
|
|
password_policy_label=password_policy_label,
|
|
onboarding_notes=(
|
|
"Novos acessos nascem sempre com papel de colaborador.",
|
|
"A senha inicial ja respeita a mesma politica do login administrativo.",
|
|
"Ativar ou desativar colaborador nao exige acesso direto ao banco.",
|
|
),
|
|
governance_notes=(
|
|
"Somente diretor acessa esta tela e as rotas de gestao de colaboradores.",
|
|
"Cada criacao e alteracao de status gera trilha de auditoria administrativa.",
|
|
"A conta de diretor continua fora deste fluxo para evitar mudancas acidentais na governanca principal.",
|
|
),
|
|
)
|
|
|
|
|
|
def _redirect_to_route(request: Request, route_name: str) -> RedirectResponse:
|
|
return RedirectResponse(url=str(request.url_for(route_name)), status_code=302)
|
|
|
|
|
|
def _resolve_settings(request: Request) -> AdminSettings:
|
|
app_settings = getattr(request.app.state, "admin_settings", None)
|
|
if isinstance(app_settings, AdminSettings):
|
|
return app_settings
|
|
return get_admin_settings()
|
|
|
|
|
|
def _build_prefixed_path(api_prefix: str, path: str) -> str:
|
|
normalized_prefix = api_prefix.rstrip("/")
|
|
normalized_path = path if path.startswith("/") else f"/{path}"
|
|
if not normalized_prefix:
|
|
return normalized_path
|
|
if normalized_path == "/":
|
|
return f"{normalized_prefix}/"
|
|
return f"{normalized_prefix}{normalized_path}"
|