Files
GTI_GERENCIADOR_FISCAL/fiscal/central/scripts/generate_control_panel_fixture.py
T
gti d21a9d1140 Add 'fiscal/' from commit '102ba84500dbd9655a0471288c3e278652593ca9'
git-subtree-dir: fiscal
git-subtree-mainline: d95165fc8f
git-subtree-split: 102ba84500
2026-09-29 14:43:23 -03:00

69 lines
5.4 KiB
Python

"""Generate explicit, deterministic non-production control-panel data."""
import argparse
import uuid
from datetime import datetime, timedelta, timezone
from central.app.config import settings
from central.app.db import SessionLocal
from central.app.models import Agent, AgentEvent, AgentSnapshot, BlockedProduct, Installation, Job, Tenant
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
def generate_fixture(session, agent_count=100, seed=7):
now = datetime.now(timezone.utc)
states = ["ONLINE"] * 50 + ["DEGRADED"] * 20 + ["OFFLINE"] * 15 + ["FAILED"] * 10 + ["UNKNOWN"] * 5
created = {"agents": 0, "events": 0, "blockers": 0, "jobs": 0}
for index in range(agent_count):
tenant = Tenant(name=f"Fixture Client {index:03d}"); session.add(tenant); session.flush()
agent_version = None if index % 17 == 0 else ("0.9.0" if index % 5 == 0 else "1.0.0rc1")
agent = Agent(tenant_id=tenant.id, name=f"fixture-agent-{index:03d}", token_hash=(f"fixture-{index:03d}".ljust(64, "0"))[:64], agent_version=agent_version); session.add(agent); session.flush()
state = states[index % len(states)]
last_seen = None if state == "UNKNOWN" else now - timedelta(seconds=10 if state in {"ONLINE", "DEGRADED"} else 10_000)
installation = Installation(agent_id=agent.id, tenant_id=tenant.id, installation_id=str(uuid.uuid5(uuid.NAMESPACE_DNS, f"fixture-{index}")), display_name=f"{tenant.name} - Servidor Principal", customer_code=f"F{index:03d}", hostname=f"srv-{index:03d}", company_name=f"Empresa {index:03d}", company_uf="BA", company_crt="1", last_seen_at=last_seen, last_status="IDLE")
session.add(installation); session.flush()
total_products = 5000 + index
safe_blocked = 1 if index % 2 == 0 else 0
failed_products = 1 if state == "FAILED" else 0
fiscally_complete = total_products - safe_blocked - failed_products
coverage_percent = round(fiscally_complete * 100 / total_products, 1)
snapshot = AgentSnapshot(installation_id=installation.id, total_products=total_products, fiscally_complete=fiscally_complete, safe_blocked=safe_blocked, failed_products=failed_products, coverage_percent=coverage_percent, blockers={"CFOP": index % 7, "ST": index % 5}, agent_health=state, version_drift="UNKNOWN" if agent_version is None else ("OUTDATED" if agent_version != "1.0.0rc1" else "CURRENT"), last_job_status="FAILED" if state in {"DEGRADED", "FAILED"} else "COMPLETED")
session.add(snapshot); created["agents"] += 1
failed = state in {"DEGRADED", "FAILED"}
job = Job(agent_id=agent.id, kind="REPROCESS_ALL", status="FAILED" if failed else "COMPLETED", payload={}, result_summary={"fixture": True}, error="fixture technical failure" if failed else None, started_at=now - timedelta(minutes=6) if failed else None, finished_at=now - timedelta(minutes=5) if failed else None)
session.add(job); session.flush()
created["jobs"] += 1
fixture_blocker = None
if index % 2 == 0:
fixture_blocker = BlockedProduct(tenant_id=tenant.id, installation_id=installation.id, company=tenant.name, product_code=f"P{index:06d}", description="Fixture product", blocker_type="CFOP", field="CFOP", reason_code="INSUFFICIENT_EVIDENCE", evidence_summary={"fixture": True}, input_fingerprint=f"{index:064d}", blocker_fingerprint=f"{index+1000:064d}")
session.add(fixture_blocker); session.flush()
created["blockers"] += 1
if index == 0:
session.add(BlockedProduct(tenant_id=tenant.id, installation_id=installation.id, company=tenant.name, product_code=fixture_blocker.product_code, description="Fixture product", blocker_type="TAX_RULE_MISSING", field="ST", reason_code="MISSING_REFERENCE", evidence_summary={"fixture": True}, input_fingerprint=f"{index+2000:064d}", blocker_fingerprint=f"{index+3000:064d}"))
created["blockers"] += 1
for event_index in range(5):
linked = event_index == 0
session.add(AgentEvent(tenant_id=tenant.id, installation_id=installation.id, agent_id=agent.id, severity="ERROR" if failed and linked else "INFO", event_type="JOB_FAILED" if failed and linked else "HEARTBEAT", message="Fixture job failed" if failed and linked else "Fixture operational event", structured_context={"fixture": True}, job_id=job.id if linked else None, product_code=fixture_blocker.product_code if linked and fixture_blocker else None, blocker_id=fixture_blocker.id if linked and fixture_blocker else None, occurred_at=now - timedelta(minutes=event_index)))
created["events"] += 1
session.commit()
return created
def main():
parser = argparse.ArgumentParser(); parser.add_argument("--database-url", default=None); parser.add_argument("--agents", type=int, default=100); parser.add_argument("--seed", type=int, default=7); parser.add_argument("--confirm-non-production", action="store_true")
args = parser.parse_args()
if settings.environment == "production" or not args.confirm_non_production:
raise SystemExit("refusing fixture generation without --confirm-non-production in non-production")
session_factory = SessionLocal
if args.database_url:
session_factory = sessionmaker(bind=create_engine(args.database_url))
with session_factory() as session:
print(generate_fixture(session, args.agents, args.seed))
if __name__ == "__main__":
main()