fix: reconcile final control panel coverage UX

This commit is contained in:
gti
2026-09-22 23:04:53 -03:00
parent 283749e860
commit ce606b04cc
12 changed files with 312 additions and 12 deletions
@@ -17,6 +17,8 @@ def test_fixture_creates_one_hundred_varied_installations_and_events():
assert {row.agent_health for row in snapshots} == {"ONLINE", "DEGRADED", "OFFLINE", "FAILED", "UNKNOWN"}
assert {row.version_drift for row in snapshots} == {"CURRENT", "OUTDATED", "UNKNOWN"}
assert {row.installation_id for row in session.query(Installation).all()} == {str(uuid.uuid5(uuid.NAMESPACE_DNS, f"fixture-{index}")) for index in range(100)}
assert all(row.fiscally_complete + row.safe_blocked + row.failed_products == row.total_products for row in snapshots)
assert all(row.coverage_percent == round(row.fiscally_complete * 100 / row.total_products, 1) for row in snapshots)
blockers = session.query(BlockedProduct).all()
assert len({row.blocker_fingerprint for row in blockers}) == len(blockers)
+86 -1
View File
@@ -22,6 +22,8 @@ def _panel_client():
snapshot = session.scalar(select(AgentSnapshot).where(AgentSnapshot.installation_id == installation.id))
snapshot.total_products = 50
snapshot.fiscally_complete = 49
snapshot.safe_blocked = 1
snapshot.failed_products = 0
snapshot.coverage_percent = 98
job = Job(
agent_id=agent_id,
@@ -80,7 +82,7 @@ def test_dashboard_renders_operational_queue_labels_and_human_dates():
assert response.status_code == 200
for label in ("Agents total", "Online", "Degraded", "Offline", "Failed", "Unknown"):
assert label in response.text
assert "Produtos bloqueados" in response.text
assert "Produtos com blockers abertos" in response.text
assert "Blockers abertos" in response.text
assert "ATENÇÃO NECESSÁRIA" in response.text
assert "Ver todos" in response.text
@@ -89,6 +91,30 @@ def test_dashboard_renders_operational_queue_labels_and_human_dates():
assert not re.search(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}", response.text)
def test_dashboard_coverage_displays_reconciled_product_buckets():
client, _, _ = _panel_client()
response = client.get("/")
assert response.status_code == 200
for label in ("Produtos avaliados", "Completos", "Bloqueados com segurança", "Falhas técnicas", "Não classificados"):
assert label in response.text
assert "Produtos com blockers abertos" in response.text
assert "Cobertura reconciliada" in response.text
def test_login_has_centered_card_and_explicit_field_labels():
client, _, _ = _panel_client()
response = client.get("/login")
assert response.status_code == 200
assert 'class="login-page"' in response.text
assert 'class="login-card"' in response.text
assert '<label for="login-username">Usuário</label>' in response.text
assert '<label for="login-password">Senha</label>' in response.text
def test_dashboard_lists_bounded_failed_job_rows_with_identity_error_age_and_empty_state():
client, agent_id, _ = _panel_client()
factory = client._session_factory
@@ -159,6 +185,27 @@ def test_agents_render_separate_health_and_fiscal_status_with_server_sort():
assert 'value="worst_coverage"' in response.text
def test_agent_list_hides_technical_uuid_and_explains_remainder():
client, agent_id, _ = _panel_client()
with client._session_factory() as session:
installation = session.scalar(select(Installation).where(Installation.agent_id == agent_id))
technical_uuid = installation.installation_id
agent = session.get(Agent, agent_id)
agent.agent_version = None
snapshot = session.scalar(select(AgentSnapshot).where(AgentSnapshot.installation_id == installation.id))
snapshot.version_drift = "UNKNOWN"
session.commit()
response = client.get("/agents")
assert response.status_code == 200
assert technical_uuid not in response.text
assert "classificados" in response.text
assert "bloqueados com segurança" in response.text
assert "falhas técnicas" in response.text
assert "<td>Desconhecida<small>Desconhecida</small></td>" not in response.text
def test_agent_list_and_detail_show_localized_last_seen_with_iso_tooltip():
client, agent_id, _ = _panel_client()
expected_iso = '2026-09-22T19:11:37+00:00'
@@ -310,6 +357,44 @@ def test_agent_detail_resolves_agent_after_first_hundred_installations():
assert "Late ERP 104" in response.text
def test_agent_detail_reconciles_coverage_and_formats_missing_technical_fields():
client, agent_id, _ = _panel_client()
with client._session_factory() as session:
agent = session.get(Agent, agent_id)
agent.agent_version = None
installation = session.scalar(select(Installation).where(Installation.agent_id == agent_id))
snapshot = session.scalar(select(AgentSnapshot).where(AgentSnapshot.installation_id == installation.id))
snapshot.version_drift = "UNKNOWN"
session.commit()
response = client.get(f"/agents/{agent_id}")
assert response.status_code == 200
for label in ("Produtos", "Completos", "Bloqueados com segurança", "Falhas técnicas", "Não classificados", "Cobertura fiscal"):
assert label in response.text
assert "Não informado" in response.text
assert "Desconhecida" in response.text
assert "Desconhecida · Desconhecida" not in response.text
assert "ODS -" not in response.text
context = response.text.split("<h2>Contexto da empresa</h2>", 1)[1].split("</article>", 1)[0]
assert "Reprocessar tudo" in context
assert not re.search(r"<(?:a|button)\b[^>]*>\s*</(?:a|button)>", context)
def test_agent_detail_reports_negative_coverage_counts_as_data_inconsistency():
client, agent_id, _ = _panel_client()
with client._session_factory() as session:
installation = session.scalar(select(Installation).where(Installation.agent_id == agent_id))
snapshot = session.scalar(select(AgentSnapshot).where(AgentSnapshot.installation_id == installation.id))
snapshot.failed_products = -1
session.commit()
response = client.get(f"/agents/{agent_id}")
assert response.status_code == 200
assert "contagens negativas" in response.text
def test_agent_event_filters_lookahead_and_safe_event_reference_links_and_confirmation():
client, agent_id, _ = _panel_client()
factory = client._session_factory
@@ -100,6 +100,70 @@ def test_dashboard_reconciles_five_health_states_and_counts_distinct_safe_produc
assert summary["online"] == 1 and summary["safe_blocked"] == 2
def test_snapshot_coverage_exposes_unclassified_residual_and_overcount():
session_factory = setup_db()
with session_factory() as session:
tenant, agent, installation, snapshot = _installation(session, 1, coverage=80, blocked=1)
snapshot.total_products = 100
snapshot.fiscally_complete = 96
snapshot.safe_blocked = 1
snapshot.failed_products = 1
session.commit()
item = list_installations(session, page_size=5)["items"][0]
assert item["unclassified_products"] == 2
assert item["coverage_overcount_products"] == 0
assert item["coverage_invariant_pass"] is True
assert item["total_products"] == item["fiscally_complete"] + item["safe_blocked"] + item["failed_products"] + item["unclassified_products"]
snapshot.fiscally_complete = 99
session.commit()
inconsistent = list_installations(session, page_size=5)["items"][0]
assert inconsistent["unclassified_products"] == 0
assert inconsistent["coverage_overcount_products"] == 1
assert inconsistent["coverage_invariant_pass"] is False
def test_dashboard_coverage_totals_reconcile_and_keep_registry_metric_separate():
session_factory = setup_db()
with session_factory() as session:
tenant, _, installation, snapshot = _installation(session, 1, coverage=96, blocked=1)
snapshot.total_products = 100
snapshot.fiscally_complete = 96
snapshot.safe_blocked = 1
snapshot.failed_products = 1
_blocker(session, tenant, product="P-OPEN", field="CFOP", index=91, installation_id=installation.id)
session.commit()
summary = dashboard_summary(session, now=NOW)
assert summary["total_products"] == 100
assert summary["fiscally_complete"] == 96
assert summary["safe_blocked"] == 1
assert summary["failed_products"] == 1
assert summary["unclassified_products"] == 2
assert summary["coverage_overcount_products"] == 0
assert summary["coverage_invariant_pass"] is True
assert summary["safe_blocked_products"] == 1
assert summary["total_products"] == summary["fiscally_complete"] + summary["safe_blocked"] + summary["failed_products"] + summary["unclassified_products"]
def test_dashboard_marks_inconsistent_snapshot_partition_instead_of_clamping():
session_factory = setup_db()
with session_factory() as session:
_, _, _, snapshot = _installation(session, 1, coverage=100, blocked=2)
snapshot.total_products = 10
snapshot.fiscally_complete = 9
snapshot.safe_blocked = 2
snapshot.failed_products = 0
session.commit()
summary = dashboard_summary(session, now=NOW)
assert summary["coverage_overcount_products"] == 1
assert summary["coverage_invariant_pass"] is False
def test_attention_items_are_ranked_and_capped_at_ten():
session_factory = setup_db()
with session_factory() as session: