from datetime import datetime, timedelta, timezone from sqlalchemy import event from central.app.audit import record_audit from central.app.blocked_products import upsert_blocker from central.app.control_plane import dashboard_summary, list_blockers, list_installations, list_jobs from central.app.events import record_event from central.app.models import Agent, AgentSnapshot, AuditEvent, BlockedProduct, Installation, Job, Tenant from central.tests.test_control_plane import setup_db NOW = datetime(2026, 9, 22, 19, 0, tzinfo=timezone.utc) def _installation(session, index, *, health="ONLINE", coverage=80, blocked=0, version="1.0.0rc1"): tenant = Tenant(name=f"Client {index}") session.add(tenant) session.flush() agent = Agent(tenant_id=tenant.id, name=f"agent-{index}", token_hash=f"token-{index}".ljust(64, "x"), agent_version=version) session.add(agent) session.flush() last_seen = { "ONLINE": NOW - timedelta(seconds=10), "DEGRADED": NOW - timedelta(seconds=10), "OFFLINE": NOW - timedelta(hours=2), "FAILED": NOW - timedelta(seconds=10), "UNKNOWN": None, }[health] installation = Installation( agent_id=agent.id, tenant_id=tenant.id, installation_id=f"00000000-0000-4000-8000-{index:012d}", display_name=f"Installation {index}", hostname=f"server-{index}", last_seen_at=last_seen, last_status="FAILED" if health == "FAILED" else "IDLE", ) session.add(installation) session.flush() snapshot = AgentSnapshot( installation_id=installation.id, total_products=100, fiscally_complete=coverage, coverage_percent=coverage, safe_blocked=blocked, failed_products=1 if health == "FAILED" else 0, last_job_status="FAILED" if health == "DEGRADED" else "COMPLETED", agent_health=health, version_drift="OUTDATED" if version != "1.0.0rc1" else "CURRENT", ) session.add(snapshot) session.flush() return tenant, agent, installation, snapshot def _blocker(session, tenant, *, product, field="CFOP", blocker_type="BLOCKED_MISSING_EVIDENCE", index=0, installation_id=None): row = BlockedProduct( tenant_id=tenant.id, installation_id=installation_id, company=tenant.name, product_code=product, description=f"Product {product}", blocker_type=blocker_type, field=field, reason_code="INSUFFICIENT_EVIDENCE", evidence_summary={"source": "test"}, input_fingerprint=f"input-{index}", blocker_fingerprint=f"blocker-{index}", first_seen_at=NOW - timedelta(hours=3), last_seen_at=NOW - timedelta(minutes=20), retry_count=2, ) session.add(row) session.flush() return row def test_dashboard_reconciles_five_health_states_and_counts_distinct_safe_products(): session_factory = setup_db() with session_factory() as session: first = _installation(session, 1, health="ONLINE", blocked=2)[0] second = _installation(session, 2, health="DEGRADED")[0] _installation(session, 3, health="OFFLINE") _installation(session, 4, health="FAILED") _installation(session, 5, health="UNKNOWN") _blocker(session, first, product="P1", field="CFOP", index=1) _blocker(session, first, product="P1", field="NCM", index=2) _blocker(session, second, product="P2", field="ICMS", index=3) session.commit() summary = dashboard_summary(session, now=NOW) assert summary["health_counts"] == {"ONLINE": 1, "DEGRADED": 1, "OFFLINE": 1, "FAILED": 1, "UNKNOWN": 1} assert summary["agents_total"] == sum(summary["health_counts"].values()) assert summary["safe_blocked_products"] == 2 assert summary["open_blockers"] == 3 assert summary["open_blocker_breakdown"] == {"CFOP": 1, "ST": 0, "ICMS": 1, "CSOSN": 0, "NCM": 1, "OTHER": 0} assert summary["online"] == 1 and summary["safe_blocked"] == 2 def test_attention_items_are_ranked_and_capped_at_ten(): session_factory = setup_db() with session_factory() as session: tenants = [] for index, health in enumerate(["FAILED"] * 2 + ["DEGRADED"] * 2 + ["OFFLINE"] * 2 + ["UNKNOWN"] * 2 + ["ONLINE"] * 4, 1): tenant = _installation(session, index, health=health, version="0.9.0" if index >= 9 else "1.0.0rc1")[0] tenants.append(tenant) for index, tenant in enumerate(tenants[8:10], 20): _blocker(session, tenant, product=f"P{index}", index=index) session.commit() items = dashboard_summary(session, now=NOW)["attention_items"] assert len(items) <= 10 assert [item["technical_health"] for item in items[:8]] == ["FAILED"] * 2 + ["DEGRADED"] * 2 + ["OFFLINE"] * 2 + ["UNKNOWN"] * 2 assert all({"client", "display_name", "hostname", "problem", "timestamp", "age", "link", "technical_health"} <= item.keys() for item in items) def test_installations_expose_separate_fiscal_and_technical_status_and_worst_sort(): session_factory = setup_db() with session_factory() as session: _installation(session, 1, coverage=90, blocked=0) _installation(session, 2, coverage=40, blocked=1, version="0.9.0") session.commit() result = list_installations(session, sort="worst_coverage", page_size=10, now=NOW) item = result["items"][0] assert item["display_name"] == "Installation 2" assert item["fiscal_completion_percent"] == 40 assert item["technical_health"] == "ONLINE" assert item["fiscal_status"] == "BLOCKED" assert item["version_drift"] == "OUTDATED" assert item["technical_ids"]["agent_id"] == item["agent_id"] def test_jobs_join_operational_identity_and_format_duration(): session_factory = setup_db() with session_factory() as session: tenant, agent, installation, _ = _installation(session, 1) session.add(Job(agent_id=agent.id, kind="REPROCESS_ALL", status="FAILED", created_at=NOW, started_at=NOW, finished_at=NOW + timedelta(seconds=194), error="failure")) session.commit() result = list_jobs(session, client="Client 1", search="server-1", page_size=10) item = result["items"][0] assert item["client"] == tenant.name assert item["display_name"] == installation.display_name assert item["hostname"] == installation.hostname assert item["job_id"] assert item["duration"] == "3 min 14 s" assert item["error"] == "failure" def test_blockers_filter_with_priority_age_and_stable_pagination(): session_factory = setup_db() with session_factory() as session: tenant, _, installation, _ = _installation(session, 1) critical = _blocker(session, tenant, product="P1", field="", blocker_type="TECHNICAL_FAILURE", index=1, installation_id=installation.id) _blocker(session, tenant, product="P2", field="CFOP", index=2, installation_id=installation.id) session.commit() result = list_blockers(session, client="Client 1", installation=installation.display_name, status="OPEN", search="P1", page=1, page_size=1) assert result["total"] == 1 assert result["items"][0]["id"] == critical.id assert result["items"][0]["priority"] == "CRITICAL" assert result["items"][0]["age"].startswith("há ") assert result["items"][0]["installation_id"] == installation.installation_id def test_blocker_detail_contains_context_events_jobs_and_resolution_audit(): session_factory = setup_db() with session_factory() as session: tenant, agent, installation, _ = _installation(session, 1) blocker = _blocker(session, tenant, product="P1", index=1, installation_id=installation.id) job = Job(agent_id=agent.id, kind="REPROCESS_ALL", status="FAILED", created_at=NOW, error="failed") session.add(job) session.flush() record_event(session, tenant_id=tenant.id, installation_id=installation.id, agent_id=agent.id, severity="ERROR", event_type="JOB_FAILED", message="job failed", blocker_id=blocker.id, job_id=job.id, occurred_at=NOW) record_audit(session, admin_user_id=None, tenant_id=tenant.id, action="RESOLVE_BLOCKER", target_type="blocker", target_id=str(blocker.id), context={"reason": "reviewed"}) session.commit() from central.app.control_plane import blocker_detail detail = blocker_detail(session, blocker.id) assert detail["client"] == tenant.name assert detail["installation"]["installation_id"] == installation.installation_id assert detail["evidence"]["source"] == "test" assert detail["related_events"][0]["job_id"] == job.id assert detail["related_jobs"][0]["job_id"] == job.id assert detail["resolution_audit"][0]["action"] == "RESOLVE_BLOCKER" def test_blockers_keep_exact_installation_identity_for_same_tenant(): session_factory = setup_db() with session_factory() as session: tenant = Tenant(name="Shared Client") session.add(tenant) session.flush() agent_a = Agent(tenant_id=tenant.id, name="agent-a", token_hash="token-a".ljust(64, "x")) agent_b = Agent(tenant_id=tenant.id, name="agent-b", token_hash="token-b".ljust(64, "x")) session.add_all([agent_a, agent_b]) session.flush() installation_a = Installation(agent_id=agent_a.id, tenant_id=tenant.id, installation_id="00000000-0000-4000-8000-000000000101", display_name="Store A", hostname="server-a") installation_b = Installation(agent_id=agent_b.id, tenant_id=tenant.id, installation_id="00000000-0000-4000-8000-000000000102", display_name="Store B", hostname="server-b") session.add_all([installation_a, installation_b]) session.flush() row_a = upsert_blocker(session, tenant.id, {"company": tenant.name, "product_code": "P-A", "field": "CFOP", "reason_code": "MISSING", "input_fingerprint": "a"}, installation_id=installation_a.id) row_b = upsert_blocker(session, tenant.id, {"company": tenant.name, "product_code": "P-B", "field": "CFOP", "reason_code": "MISSING", "input_fingerprint": "b"}, installation_id=installation_b.id) result_a = list_blockers(session, tenant_id=tenant.id, installation="Store A") result_b = list_blockers(session, tenant_id=tenant.id, installation="Store B") assert result_a["total"] == 1 and result_a["items"][0]["id"] == row_a.id assert result_a["items"][0]["installation_id"] == installation_a.installation_id assert result_b["total"] == 1 and result_b["items"][0]["id"] == row_b.id assert result_b["items"][0]["installation_id"] == installation_b.installation_id def test_legacy_tenant_blocker_has_no_fabricated_installation_context(): session_factory = setup_db() with session_factory() as session: tenant, _, installation, _ = _installation(session, 1) row = _blocker(session, tenant, product="LEGACY", index=99) result = list_blockers(session, tenant_id=tenant.id) assert result["items"][0]["id"] == row.id assert result["items"][0]["installation_id"] is None from central.app.control_plane import blocker_detail detail = blocker_detail(session, row.id) assert detail["installation"]["installation_id"] is None assert detail["server"]["hostname"] is None assert installation.hostname == "server-1" def test_dashboard_uses_sql_aggregates_for_operational_totals(): session_factory = setup_db() with session_factory() as session: tenant, _, _, _ = _installation(session, 1) _blocker(session, tenant, product="P1", index=101) statements = [] event.listen(session.bind, "before_cursor_execute", lambda conn, cursor, statement, parameters, context, executemany: statements.append(statement)) dashboard_summary(session, now=NOW) assert any("COUNT" in statement.upper() and "BLOCKED_PRODUCTS" in statement.upper() for statement in statements) assert any("DISTINCT" in statement.upper() and "BLOCKED_PRODUCTS" in statement.upper() for statement in statements) def test_health_filter_is_paginated_in_sql_and_counts_all_matches(): session_factory = setup_db() with session_factory() as session: for index in range(1, 4): _installation(session, index, health="ONLINE") statements = [] event.listen(session.bind, "before_cursor_execute", lambda conn, cursor, statement, parameters, context, executemany: statements.append(statement)) result = list_installations(session, health="ONLINE", page=2, page_size=1, now=NOW) assert result["total"] == 3 assert len(result["items"]) == 1 assert any("LIMIT" in statement.upper() and "INSTALLATIONS" in statement.upper() for statement in statements) def test_worst_coverage_sort_uses_the_displayed_derived_percentage(): session_factory = setup_db() with session_factory() as session: _, _, first, first_snapshot = _installation(session, 1, coverage=80) _, _, second, second_snapshot = _installation(session, 2, coverage=20) first_snapshot.coverage_percent = 10 second_snapshot.coverage_percent = 90 session.commit() result = list_installations(session, sort="worst_coverage", page_size=10, now=NOW) assert result["items"][0]["installation_id"] == second.installation_id assert result["items"][0]["fiscal_completion_percent"] == 20 assert first.installation_id != second.installation_id def test_worst_coverage_sort_cannot_disagree_with_one_decimal_display(): session_factory = setup_db() with session_factory() as session: _, _, first, first_snapshot = _installation(session, 1, coverage=0) _, _, second, second_snapshot = _installation(session, 2, coverage=0) first_snapshot.total_products = 79 first_snapshot.fiscally_complete = 5 second_snapshot.total_products = 16 second_snapshot.fiscally_complete = 1 session.commit() result = list_installations(session, sort="worst_coverage", page_size=10, now=NOW) displayed = [item["fiscal_completion_percent"] for item in result["items"]] assert displayed == sorted(displayed) assert displayed == [6.3, 6.3] assert {item["installation_id"] for item in result["items"]} == {first.installation_id, second.installation_id} def test_lowercase_required_blocker_field_reaches_attention_candidates(): session_factory = setup_db() with session_factory() as session: tenant, _, installation, _ = _installation(session, 1) blocker = _blocker(session, tenant, product="LOWER", field="cfop", index=120, installation_id=installation.id) attention = dashboard_summary(session, now=NOW)["attention_items"] assert any(item["link"] == f"/blockers/{blocker.id}" for item in attention)