Add 'fiscal/' from commit '102ba84500dbd9655a0471288c3e278652593ca9'
git-subtree-dir: fiscal git-subtree-mainline:d95165fc8fgit-subtree-split:102ba84500
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
"""Persists the Agent's CFOP/IPPT write audit records (append-only). Mirrors central.app.rtc_audit's
|
||||
safety model for a separate, narrower capability - no candidate preview table (candidates are
|
||||
recomputed fresh from field_contract every job, never stored server-side), no rollback queue yet
|
||||
(rollback is operator-triggered later, out of scope for this pass)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from .events import record_event
|
||||
from .models import CfopIpptWriteAudit
|
||||
|
||||
MAX_AUDITS_PER_JOB = 2000
|
||||
WRITE_MODES = ("DISABLED", "DRY_RUN", "APPROVAL_REQUIRED", "ENABLED")
|
||||
ALLOWED_FIELDS = ("CFOP", "IPPT")
|
||||
|
||||
|
||||
def _clip(value, size):
|
||||
return None if value is None else str(value)[:size]
|
||||
|
||||
|
||||
def job_authorizations(installation) -> dict:
|
||||
"""What the authenticated job carries to the Agent. Decided centrally per installation; the Agent
|
||||
has no local switch. DISABLED unless an installation row explicitly says otherwise (server_default)."""
|
||||
mode = installation.cfop_ippt_write_mode if installation.cfop_ippt_write_mode in WRITE_MODES else "DISABLED"
|
||||
return {"cfop_ippt_write_mode": mode}
|
||||
|
||||
|
||||
def record_cfop_ippt_write_audits(session, *, tenant_id: int, installation, agent, job_id: int | None, cfop_ippt_apply: dict | None) -> int:
|
||||
"""Stores every applied/aborted write of the job. Never trusts the Agent for identity: tenant/installation/agent come from the authenticated context."""
|
||||
if not isinstance(cfop_ippt_apply, dict):
|
||||
return 0
|
||||
records = list(cfop_ippt_apply.get("applied") or []) + list(cfop_ippt_apply.get("aborted") or [])
|
||||
stored = applied = aborted = 0
|
||||
for item in records[:MAX_AUDITS_PER_JOB]:
|
||||
if not isinstance(item, dict) or item.get("field") not in ALLOWED_FIELDS:
|
||||
continue
|
||||
outcome = str(item.get("outcome", ""))[:16]
|
||||
session.add(CfopIpptWriteAudit(
|
||||
tenant_id=tenant_id, installation_id=installation.id, agent_id=agent.id, job_id=job_id,
|
||||
product_code=_clip(item.get("product_code"), 64) or "", field=item["field"], outcome=outcome,
|
||||
reason=_clip(item.get("reason") or item.get("reason_code"), 96), old_value=_clip(item.get("old_value"), 16), new_value=_clip(item.get("new_value"), 16),
|
||||
action="APPLY", written_at=_clip(item.get("timestamp"), 40)))
|
||||
stored += 1
|
||||
if outcome == "APPLIED":
|
||||
applied += 1
|
||||
else:
|
||||
aborted += 1
|
||||
if stored:
|
||||
record_event(session, tenant_id=tenant_id, installation_id=installation.id, agent_id=agent.id, severity="WARNING" if applied else "INFO", event_type="CFOP_IPPT_AUTO_APPLY", job_id=job_id,
|
||||
message=f"CFOP/IPPT: {applied} aplicado(s), {aborted} abortado(s)",
|
||||
context={"applied": applied, "aborted": aborted, "reasons": cfop_ippt_apply.get("aborted_reasons") or {}, "mode": cfop_ippt_apply.get("mode")})
|
||||
session.commit()
|
||||
return stored
|
||||
Reference in New Issue
Block a user