Add full Tally ODBC export with SQLite progress

This commit is contained in:
A R R R Associates
2026-09-06 18:39:47 +05:30
parent 6411cb14fa
commit 9500668413
8 changed files with 400 additions and 24 deletions
+71 -1
View File
@@ -6,7 +6,7 @@ import re
from urllib.parse import quote
from fastapi import APIRouter, Form, Request
from fastapi.responses import RedirectResponse
from fastapi.responses import RedirectResponse, JSONResponse
from sqlalchemy import select
from app.core.db.common import CommonSessionLocal
@@ -197,6 +197,7 @@ def tally_tool(
unmapped: int = 0,
synced: int = 0,
transactions_synced: int = 0,
export_started: int = 0,
error: str = "",
):
db = CommonSessionLocal()
@@ -547,6 +548,75 @@ def sync_tally_transactions(
finally:
db.close()
@router.post("/full-export")
def start_full_accounting_export(
request: Request,
client_id: int = Form(...),
tally_guid: str = Form(...),
date_from: str = Form(...),
date_to: str = Form(...),
csrf_token: str = Form(...),
):
validate_csrf(request, csrf_token)
db = CommonSessionLocal()
try:
user, response = _require_partner(request, db, "accounting.tally.sync_transactions")
if response:
return response
client, _clients, scope = _find_visible_client(db, request, user, client_id)
if not client:
return _denied()
try:
start = date.fromisoformat(str(date_from or ""))
end = date.fromisoformat(str(date_to or ""))
if start > end:
raise ValueError("From Date cannot be after To Date.")
except Exception as exc:
return RedirectResponse(url=f"/tools/tally?client_id={client.id}&error={quote(str(exc))}", status_code=303)
node = get_active_storage_node_for_branch(db, scope.tenant_id, scope.branch_id)
if not node or not _node_online(node):
return RedirectResponse(url=f"/tools/tally?client_id={client.id}&error={quote('ERP Local Agent is offline for the active branch.')}", status_code=303)
result = request_agent_command(
node.node_code, "accounting_full_export_start",
{
**_accounting_storage_payload(client, _financial_year_for_date(start)),
"tally_guid": str(tally_guid or "").strip(),
"date_from": start.isoformat(), "date_to": end.isoformat(),
"requested_by_user_id": int(user.id), "timeout_seconds": 1800,
}, timeout_seconds=20,
)
if not result.get("ok"):
raise RuntimeError(str(result.get("error") or "Full Accounting Export could not be started."))
return RedirectResponse(url=f"/tools/tally?client_id={client.id}&refresh=1&export_started=1", status_code=303)
except Exception as exc:
return RedirectResponse(url=f"/tools/tally?client_id={client_id}&error={quote(str(exc))}", status_code=303)
finally:
db.close()
@router.get("/full-export/status")
def full_accounting_export_status(request: Request, client_id: int):
db = CommonSessionLocal()
try:
user, response = _require_partner(request, db, "accounting.tally.view")
if response:
return JSONResponse({"ok": False, "error": "Access denied."}, status_code=403)
client, _clients, scope = _find_visible_client(db, request, user, client_id)
if not client:
return JSONResponse({"ok": False, "error": "Client is not available."}, status_code=404)
node = get_active_storage_node_for_branch(db, scope.tenant_id, scope.branch_id)
if not node or not _node_online(node):
return JSONResponse({"ok": False, "error": "ERP Local Agent is offline."}, status_code=503)
result = request_agent_command(
node.node_code, "accounting_full_export_status", _accounting_storage_payload(client), timeout_seconds=10
)
if not result.get("ok"):
return JSONResponse({"ok": False, "error": str(result.get("error") or "Progress lookup failed.")}, status_code=500)
return JSONResponse({"ok": True, **(result.get("result") or {})})
finally:
db.close()
@router.get("/depreciation")
def depreciation_it_tool(
request: Request,