feat: enrichment Hub API, feature flags UI/gating, NCM refresher, Agent enrichment worker with tests

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
gti
2026-09-25 18:47:35 -03:00
co-authored by Claude Sonnet 5
parent 27f992d9e0
commit 5deebea14e
22 changed files with 1118 additions and 23 deletions
+9 -3
View File
@@ -7,7 +7,8 @@ Field decisions: AUTO_FILL_SAFE | SUGGESTION_ONLY | CONFLICT | INSUFFICIENT_EVID
"""
from __future__ import annotations
from datetime import date, datetime
import time
from datetime import date
from sqlalchemy import select
@@ -79,7 +80,7 @@ def _fiscal_decisions(session, ncm_eval: dict, gtin_kb_verified: bool, current:
if not _empty(current, "CEST"):
out["CEST"] = _field(ALREADY, reason="campo já preenchido")
elif decision["cest_status"] == "CEST_CONFIRMED" and len(cest) == 1 and ncm["status"] == AUTO:
out["CEST"] = _field(AUTO, cest[0], "CEST_OFFICIAL_UNIQUE_MAPPING", ncm["kb_status"], [f"NCM {ncm_for_engine}"])
out["CEST"] = _field(AUTO, normalize_code(cest[0]), "CEST_OFFICIAL_UNIQUE_MAPPING", ncm["kb_status"], [f"NCM {ncm_for_engine}"])
elif decision["cest_status"] == "NO_CEST_MAPPING_FOUND":
out["CEST"] = _field(NA, reason="NCM sem mapeamento de CEST no dataset oficial")
else:
@@ -96,7 +97,8 @@ def _fiscal_decisions(session, ncm_eval: dict, gtin_kb_verified: bool, current:
return out
def resolve(session, gateway: ProviderGateway, *, gtin_raw, description, current: dict | None = None, client_label: str | None = None, allow_external: bool = True) -> dict:
def resolve(session, gateway: ProviderGateway, *, gtin_raw, description, current: dict | None = None, client_label: str | None = None, allow_external: bool = True, budget_s: float | None = None) -> dict:
started = time.monotonic()
"""Returns {state, gtin_status, gtin, fields:{...}, providers:[...], retry_at, dataset_versions}. Never raises for provider trouble."""
current = {k: v for k, v in (current or {}).items()}
g = normalize_gtin(gtin_raw)
@@ -117,6 +119,10 @@ def resolve(session, gateway: ProviderGateway, *, gtin_raw, description, current
found, pending = [], []
if allow_external:
for provider in gateway.providers:
if budget_s is not None and time.monotonic() - started > budget_s:
result["providers"].append({"provider": provider.name, "state": "SKIPPED", "reason": "TIME_BUDGET", "from_cache": False})
pending.append(type("P", (), {"reason": "TIME_BUDGET", "retry_at": None})())
continue
out = gateway.lookup(provider, query)
result["providers"].append({"provider": out.provider, "state": out.state, "reason": out.reason, "from_cache": out.from_cache})
if out.state in ("FOUND", "CACHE_HIT") and out.product: