fix: close task 2 operational review findings
This commit is contained in:
@@ -5,7 +5,7 @@ from sqlalchemy.pool import StaticPool
|
||||
|
||||
from central.app.jobs import claim_next_job, complete_job, create_job, fail_job
|
||||
from central.app.main import create_app
|
||||
from central.app.models import Agent, Base, Job, Tenant
|
||||
from central.app.models import Agent, Base, BlockedProduct, Job, Tenant
|
||||
|
||||
|
||||
def _make_agent(session):
|
||||
@@ -133,8 +133,9 @@ def test_reprocess_products_requires_codigos():
|
||||
|
||||
|
||||
def test_blocker_registry_api_deduplicates_and_resolves():
|
||||
client, _ = _client()
|
||||
client, engine = _client()
|
||||
headers = {"Authorization": "Bearer test-token"}
|
||||
assert client.post("/v1/agents/heartbeat", json={"status": "IDLE", "installation_id": "00000000-0000-4000-8000-000000000001"}, headers=headers).status_code == 200
|
||||
summary = {"blocked_products": [{"company": "C", "product_code": "P1", "blocker_type": "BLOCKED_MISSING_EVIDENCE", "field": "CFOP", "reason_code": "MISSING", "input_fingerprint": "v1", "evidence_summary": {"source": "ERP"}}]}
|
||||
created = client.post("/v1/jobs", json={"kind": "REPROCESS_PRODUCTS", "payload": {"codigos": ["P1"]}}, headers=headers)
|
||||
job_id = created.json()["job_id"]
|
||||
@@ -143,6 +144,8 @@ def test_blocker_registry_api_deduplicates_and_resolves():
|
||||
listed = client.get("/v1/blockers?field=CFOP", headers=headers)
|
||||
assert listed.status_code == 200
|
||||
assert len(listed.json()["blockers"]) == 1
|
||||
with Session(engine) as session:
|
||||
assert session.query(BlockedProduct).one().installation_id is not None
|
||||
blocker_id = listed.json()["blockers"][0]["id"]
|
||||
resolved = client.post(f"/v1/blockers/{blocker_id}/resolve", json={"resolution_source": "TEST"}, headers=headers)
|
||||
assert resolved.json()["resolved"] is True
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
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
|
||||
@@ -51,9 +54,10 @@ def _installation(session, index, *, health="ONLINE", coverage=80, blocked=0, ve
|
||||
return tenant, agent, installation, snapshot
|
||||
|
||||
|
||||
def _blocker(session, tenant, *, product, field="CFOP", blocker_type="BLOCKED_MISSING_EVIDENCE", index=0):
|
||||
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}",
|
||||
@@ -153,8 +157,8 @@ 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)
|
||||
_blocker(session, tenant, product="P2", field="CFOP", index=2)
|
||||
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)
|
||||
@@ -170,7 +174,7 @@ 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)
|
||||
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()
|
||||
@@ -188,3 +192,91 @@ def test_blocker_detail_contains_context_events_jobs_and_resolution_audit():
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user