Add Phase 19 bank accounting and reconciliation workflow

This commit is contained in:
A R R R Associates
2026-08-24 15:23:49 +05:30
parent 67ebd587e9
commit 769add8cb8
17 changed files with 1363 additions and 10 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ import io
from pathlib import Path
import zipfile
ERP_LOCAL_AGENT_VERSION = "1.18.0"
ERP_LOCAL_AGENT_VERSION = "1.19.0"
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)
@@ -1,2 +1,2 @@
__version__ = "1.18.0"
__version__ = "1.19.0"
AGENT_NAME = "ERP Local Agent"
@@ -48,6 +48,8 @@ class AgentCommandProcessor:
result = self._post_purchase_voucher(payload)
elif action == "accounting_bank_posting_preflight":
result = self._bank_posting_preflight(payload)
elif action == "accounting_bank_reconciliation_extract":
result = self._bank_reconciliation_extract(payload)
elif action == "accounting_post_bank_voucher":
result = self._post_bank_voucher(payload)
elif action == "accounting_native_voucher_preflight":
@@ -83,7 +85,7 @@ class AgentCommandProcessor:
return {
"name": "ERP Local Agent", "version": __version__,
"tally_capability": True, "accounting_act_capability": True,
"tally_mapping_capability": True, "tally_master_sync_capability": True, "chart_of_accounts_capability": True, "native_voucher_engine_capability": True, "stock_item_native_voucher_capability": True,
"tally_mapping_capability": True, "tally_master_sync_capability": True, "chart_of_accounts_capability": True, "native_voucher_engine_capability": True, "stock_item_native_voucher_capability": True, "bank_reconciliation_read_capability": True,
"tally_transaction_sync_capability": True,
"historical_learning_read_capability": True,
"purchase_posting_preflight_capability": True,
@@ -492,6 +494,57 @@ class AgentCommandProcessor:
}
def _bank_reconciliation_extract(self, payload: dict[str, Any]) -> dict[str, Any]:
company, company_name = self._resolve_open_company(payload)
bank_ledger_name = str(payload.get("bank_ledger_name") or "").strip()
if not bank_ledger_name:
raise ValueError("Bank ledger is required for reconciliation.")
ledgers = self.tally.bank_posting_ledgers(company_name)
bank_names = {
str(row.get("name") or "").strip().casefold()
for row in (ledgers.get("bank_ledgers") or [])
if str(row.get("name") or "").strip()
}
if bank_ledger_name.casefold() not in bank_names:
raise ValueError(
f"'{bank_ledger_name}' is not a Tally Bank Accounts ledger in the open company."
)
date_from = str(payload.get("date_from") or "").strip()
date_to = str(payload.get("date_to") or "").strip()
vouchers = self.tally.export_vouchers(company_name, date_from, date_to)
filtered = []
target = bank_ledger_name.casefold()
for voucher in vouchers:
entries = list(voucher.get("ledger_entries") or [])
if not any(
str(entry.get("ledger_name") or "").strip().casefold() == target
for entry in entries
):
continue
filtered.append(
{
key: value
for key, value in voucher.items()
if key != "raw_xml"
}
)
return {
"company_name": company_name,
"company_guid": str(company.get("guid") or ""),
"bank_ledger_name": bank_ledger_name,
"date_from": date_from,
"date_to": date_to,
"voucher_count": len(filtered),
"vouchers": filtered,
"read_only": True,
"agent": self._agent_info(),
}
def _bank_posting_preflight(self, payload: dict[str, Any]) -> dict[str, Any]:
company, company_name = self._resolve_open_company(payload)
ledgers = self.tally.bank_posting_ledgers(company_name)