fix: REPROCESS_PRODUCTS resolved company=None for unified_fiscal/RTC

REPROCESS_PRODUCTS is not in SYNC_JOB_KINDS, so it fell to the else branch of execute_job and hardcoded company=None
for _unified_fiscal - a real gap, not a missing feature: the same deterministic, fail-closed company_context.resolve()
every sync job already uses is cheap (no full-table scan, confirmed against the real database) and applies just as
well to a one-off reprocess job. Now resolves the real company the same way; falls back to None only when the
company genuinely cannot be resolved yet, never a silent guess. Does not touch RTC rule logic.

Verified end-to-end against the real production database (dry-run, zero writes) that this was the last domain still
carrying the old bug - field_contract's post-NCM fiscal completion already bypassed it entirely by reading
Installation.company_uf/crt/company_contribuinte_ipi directly (populated via the 1.3.7 heartbeat fix).

1123 tests passed (tests + central/tests + agent/tests), 0 failed. Version 1.3.8 (single GTI_FISCAL_VERSION).
This commit is contained in:
gti
2026-09-27 21:32:28 -03:00
parent 7e83d17533
commit 4701ff8724
10 changed files with 90 additions and 18 deletions
+65
View File
@@ -261,6 +261,71 @@ def test_execute_job_success_summarizes_pipeline(monkeypatch):
assert result["writes_attempted"] == 0 # firebird_writes disabled by default in _config()
def test_reprocess_products_resolves_real_company_context_not_none(monkeypatch):
"""REPROCESS_PRODUCTS used to hardcode company=None for _unified_fiscal (it isn't in SYNC_JOB_KINDS). Company resolution is cheap and
deterministic (company_context.resolve, same as every sync job already uses) - it must never silently fall back to None when the company
genuinely resolves."""
config = _config()
products = [{"CODIGO": "000026", "PRODUTO": "x", "CLASSIFICACAO_FISCAL": "03055100", "IPI": None}]
decisions = [{"status": "EXACT_NCM", "ipi_status": "IPI_RESOLVED", "classification": {"ipi": {"rate_kind": "NUMERIC", "rate_numeric": 3.25}}, "dataset_versions": {"tipi_ipi": "v1"}}]
monkeypatch.setattr(service, "read_products", lambda env, codigos=None: products)
class FakeClient:
def __init__(self, *a, **k): pass
def classify_batch(self, items): return decisions
monkeypatch.setattr(service, "HubClient", FakeClient)
monkeypatch.setattr(service._firebird_reader, "read_company_context", lambda env: {"uf": "BA", "crt": "1", "company_code": "000001"})
captured = {}
real_unified = service._unified_fiscal
def spy_unified_fiscal(env, company, ncm_valid=None):
captured["company"] = company
return real_unified(env, company, ncm_valid)
monkeypatch.setattr(service, "_unified_fiscal", spy_unified_fiscal)
executor = _FakeExecutor()
state = _FakeState()
job = {"kind": "REPROCESS_PRODUCTS", "agent_id": 1, "payload": {"codigos": ["000026"]}}
result, error = service.execute_job(job, config, executor, state, {})
assert error is None
assert captured["company"] == {"crt": "1"} # real CRT, never None, when the company genuinely resolves
def test_reprocess_products_falls_back_to_none_only_when_company_unresolved(monkeypatch):
"""No guessing: when the company genuinely cannot be resolved (e.g. Firebird unreachable), company stays None - same as before."""
config = _config()
products = [{"CODIGO": "000026", "PRODUTO": "x", "CLASSIFICACAO_FISCAL": "03055100", "IPI": None}]
decisions = [{"status": "EXACT_NCM", "ipi_status": "IPI_RESOLVED", "classification": {"ipi": {"rate_kind": "NUMERIC", "rate_numeric": 3.25}}, "dataset_versions": {"tipi_ipi": "v1"}}]
monkeypatch.setattr(service, "read_products", lambda env, codigos=None: products)
class FakeClient:
def __init__(self, *a, **k): pass
def classify_batch(self, items): return decisions
monkeypatch.setattr(service, "HubClient", FakeClient)
def boom(env):
raise RuntimeError("firebird unavailable")
monkeypatch.setattr(service._firebird_reader, "read_company_context", boom)
captured = {}
real_unified = service._unified_fiscal
def spy_unified_fiscal(env, company, ncm_valid=None):
captured["company"] = company
return real_unified(env, company, ncm_valid)
monkeypatch.setattr(service, "_unified_fiscal", spy_unified_fiscal)
executor = _FakeExecutor()
state = _FakeState()
job = {"kind": "REPROCESS_PRODUCTS", "agent_id": 1, "payload": {"codigos": ["000026"]}}
result, error = service.execute_job(job, config, executor, state, {})
assert error is None
assert captured["company"] is None
class _FakeHubForLoop:
"""Simulates: heartbeat flaky twice then OK, one job then nothing, and captures completions."""