From 66b5888d802c42288a751ed584d689be5536e4fc Mon Sep 17 00:00:00 2001 From: gti Date: Tue, 22 Sep 2026 15:38:55 -0300 Subject: [PATCH] feat: add blocker resolution action to panel --- central/app/web.py | 20 +++++++++++++++++++- central/templates/blockers.html | 2 +- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/central/app/web.py b/central/app/web.py index 9c175e4..e92ae15 100644 --- a/central/app/web.py +++ b/central/app/web.py @@ -109,7 +109,25 @@ def router(session_factory): def blockers(request: Request, page: int = 1, blocker_type: str | None = None): session, auth_data, redirect = page_auth(request) if redirect: return redirect - try: return render(request, "blockers.html", {"result": list_blockers(session, page=page, page_size=50, blocker_type=blocker_type), "auth": auth_data}) + try: return render(request, "blockers.html", {"result": list_blockers(session, page=page, page_size=50, blocker_type=blocker_type), "auth": auth_data, "csrf_token": request.cookies.get("gti_csrf", "")}) + finally: session.close() + + @routes.post("/blockers/{blocker_id}/resolve") + async def resolve_blocker(request: Request, blocker_id: int): + session, auth_data, redirect = page_auth(request) + if redirect: return redirect + try: + values = await form_values(request); web_session, admin = auth_data + require_csrf(web_session, values.get("csrf_token")) + if values.get("confirm") != "yes" or not values.get("context", "").strip(): return HTMLResponse("confirmation and context required", status_code=400) + from .models import BlockedProduct + blocker = session.get(BlockedProduct, blocker_id) + if not blocker: return HTMLResponse("Blocker not found", status_code=404) + from datetime import datetime, timezone + blocker.resolved_at = datetime.now(timezone.utc); blocker.resolution_source = "HUMAN_PANEL" + record_audit(session, admin_user_id=admin.id, tenant_id=blocker.tenant_id, action="RESOLVE_BLOCKER", target_type="blocker", target_id=str(blocker_id), context={"context": values["context"]}) + session.commit() + return RedirectResponse("/blockers", status_code=303) finally: session.close() @routes.get("/jobs", response_class=HTMLResponse) diff --git a/central/templates/blockers.html b/central/templates/blockers.html index 5e00dec..ae844c2 100644 --- a/central/templates/blockers.html +++ b/central/templates/blockers.html @@ -1 +1 @@ -{% extends "base.html" %}{% block title %}Blockers | GTI Fiscal{% endblock %}{% block content %}

FILA FISCAL

Blockers globais

{% for item in result.items %}{% else %}{% endfor %}
ClienteProdutoCampoTipoMotivoÚltima ocorrênciaRetries
{{ item.client or item.tenant_id }}{{ item.product_code }}{{ item.description or "" }}{{ item.field }}{{ item.blocker_type }}{{ item.reason }}{{ item.last_seen_at }}{{ item.retry_count }}
Nenhum blocker aberto.
{% endblock %} +{% extends "base.html" %}{% block title %}Blockers | GTI Fiscal{% endblock %}{% block content %}

FILA FISCAL

Blockers globais

{% for item in result.items %}{% else %}{% endfor %}
ClienteProdutoCampoTipoMotivoÚltima ocorrênciaAção
{{ item.client or item.tenant_id }}{{ item.product_code }}{{ item.description or "" }}{{ item.field }}{{ item.blocker_type }}{{ item.reason }}{{ item.last_seen_at }}{{ item.retry_count }} retries
Nenhum blocker aberto.
{% endblock %}