From 3a4370d35e5c36045c2242f9cb6049df4563901e Mon Sep 17 00:00:00 2001 From: A R R R Associates Date: Thu, 3 Sep 2026 23:15:43 +0530 Subject: [PATCH] Route cash payment review through local agent with safe progress --- app/modules/accounting/cash_payment_ui.py | 2 +- .../accounting/cash_payment_review.html | 67 ++++++++++++++++++- app/modules/documents/agent_package.py | 2 +- .../erp_local_agent/__init__.py | 2 +- .../erp_local_agent/commands.py | 34 +++++++++- 5 files changed, 99 insertions(+), 8 deletions(-) diff --git a/app/modules/accounting/cash_payment_ui.py b/app/modules/accounting/cash_payment_ui.py index e15d06f..14f2b11 100644 --- a/app/modules/accounting/cash_payment_ui.py +++ b/app/modules/accounting/cash_payment_ui.py @@ -196,7 +196,7 @@ def cash_payment_review( "split_window_days": int(setting.split_window_days), "near_limit_percent": float(setting.near_limit_percent), }, - timeout_seconds=120, + timeout_seconds=300, ) if result.get("ok"): review = (result.get("result") or {}).get("cash_payment_review") diff --git a/app/modules/accounting/templates/accounting/cash_payment_review.html b/app/modules/accounting/templates/accounting/cash_payment_review.html index 470ca02..7b2a934 100644 --- a/app/modules/accounting/templates/accounting/cash_payment_review.html +++ b/app/modules/accounting/templates/accounting/cash_payment_review.html @@ -20,8 +20,8 @@ {% if page_mode != 'allocation' %}
-

Tax Payment Compliance Review

-
+

Cash Payment Compliance Review

+
-
+

Safe-paced mode reads Tally in monthly batches with a short pause between requests to reduce load on TallyPrime.

@@ -63,6 +63,9 @@ {% if review %}
+ {% if review.safe_paced_mode %} +
Completed in safe-paced mode using {{ review.tally_request_batches or 0 }} Tally voucher batch(es), with approximately {{ review.tally_pause_ms or 0 }} ms pause between batches.
+ {% endif %}
{% for label, value in [('Vouchers reviewed', review.summary.vouchers_reviewed), ('Cash payments', review.summary.cash_payment_vouchers), ('Single-voucher exceptions', review.summary.single_voucher_exceptions), ('Same-day exceptions', review.summary.same_day_exceptions), ('Possible split patterns', review.summary.possible_split_patterns)] %}
{{ label }}
{{ value }}
@@ -115,5 +118,63 @@ {% endif %}
{% endif %} + + + {% endblock %} diff --git a/app/modules/documents/agent_package.py b/app/modules/documents/agent_package.py index e3f0d9c..84ff2e2 100644 --- a/app/modules/documents/agent_package.py +++ b/app/modules/documents/agent_package.py @@ -4,7 +4,7 @@ import io from pathlib import Path import zipfile -ERP_LOCAL_AGENT_VERSION = "1.22.5" +ERP_LOCAL_AGENT_VERSION = "1.22.6" ERP_LOCAL_AGENT_NAME = "ERP Local Agent" RUNTIME_ROOT = Path(__file__).resolve().parent / "local_agent_runtime" _DETERMINISTIC_ZIP_TIMESTAMP = (2026, 1, 1, 0, 0, 0) diff --git a/app/modules/documents/local_agent_runtime/erp_local_agent/__init__.py b/app/modules/documents/local_agent_runtime/erp_local_agent/__init__.py index 38f20f2..20e759f 100644 --- a/app/modules/documents/local_agent_runtime/erp_local_agent/__init__.py +++ b/app/modules/documents/local_agent_runtime/erp_local_agent/__init__.py @@ -1,2 +1,2 @@ -__version__ = "1.22.5" +__version__ = "1.22.6" AGENT_NAME = "ERP Local Agent" diff --git a/app/modules/documents/local_agent_runtime/erp_local_agent/commands.py b/app/modules/documents/local_agent_runtime/erp_local_agent/commands.py index 9f1adae..43428a5 100644 --- a/app/modules/documents/local_agent_runtime/erp_local_agent/commands.py +++ b/app/modules/documents/local_agent_runtime/erp_local_agent/commands.py @@ -1,7 +1,8 @@ from __future__ import annotations -from datetime import datetime, timezone +from datetime import datetime, timezone, date as _dt_date, timedelta as _timedelta import re +import time from typing import Any from . import __version__ @@ -661,7 +662,13 @@ class AgentCommandProcessor: if not 1 <= near_limit_percent <= 100: raise ValueError("Near-limit percentage must be between 1 and 100.") + # TallyPrime is intentionally queried in a paced manner. A full-year XML + # voucher export in one request can make desktop Tally unresponsive on + # larger books. Load masters once, pause briefly, then read vouchers in + # month-sized batches with a small gap between calls. + pace_seconds = 0.75 ledger_masters = self.tally.export_master_collection(company_name, "ledgers") + time.sleep(pace_seconds) cash_ledgers = set() for ledger in ledger_masters: name = str(ledger.get("name") or "").strip() @@ -672,7 +679,27 @@ class AgentCommandProcessor: if not cash_ledgers: cash_ledgers.add("cash") - vouchers = self.tally.export_vouchers(company_name, date_from, date_to) + try: + scan_from = _dt_date.fromisoformat(date_from) + scan_to = _dt_date.fromisoformat(date_to) + except ValueError as exc: + raise ValueError("Cash payment review dates must be valid YYYY-MM-DD dates.") from exc + if scan_to < scan_from: + raise ValueError("Cash payment review To date cannot be before From date.") + + vouchers = [] + batch_count = 0 + cursor = scan_from + while cursor <= scan_to: + next_month = (cursor.replace(day=28) + _timedelta(days=4)).replace(day=1) + batch_to = min(scan_to, next_month - _timedelta(days=1)) + batch = self.tally.export_vouchers(company_name, cursor.isoformat(), batch_to.isoformat()) + vouchers.extend(batch or []) + batch_count += 1 + cursor = batch_to + _timedelta(days=1) + if cursor <= scan_to: + time.sleep(pace_seconds) + payments = [] for voucher in vouchers: if str(voucher.get("is_cancelled") or "").strip().lower() in {"yes", "true", "1"}: @@ -798,6 +825,9 @@ class AgentCommandProcessor: "possible_split_payments": split_patterns, "cash_payments": payments, "read_only": True, + "safe_paced_mode": True, + "tally_request_batches": batch_count, + "tally_pause_ms": int(pace_seconds * 1000), "review_note": "Possible split-payment patterns are review indicators only and do not determine tax treatment.", }, "agent": self._agent_info(),