Add SQLite cached slow Tally extraction for cash payment review
This commit is contained in:
@@ -5,7 +5,7 @@ from decimal import Decimal, InvalidOperation
|
||||
from urllib.parse import quote
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import RedirectResponse
|
||||
from fastapi.responses import RedirectResponse, JSONResponse
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.core.db.common import CommonSessionLocal
|
||||
@@ -146,7 +146,8 @@ def cash_payment_review(
|
||||
tally_guid: str = "",
|
||||
date_from: str = "",
|
||||
date_to: str = "",
|
||||
run: int = 0,
|
||||
job_id: str = "",
|
||||
analyze: int = 0,
|
||||
saved: int = 0,
|
||||
error: str = "",
|
||||
):
|
||||
@@ -169,6 +170,7 @@ def cash_payment_review(
|
||||
end_text = date_to or today.isoformat()
|
||||
live_result = None
|
||||
review = None
|
||||
cache_job = None
|
||||
command_error = error or ""
|
||||
|
||||
if selected_client and node and online:
|
||||
@@ -183,28 +185,39 @@ def cash_payment_review(
|
||||
live_result = status_response.get("result") or {}
|
||||
else:
|
||||
command_error = str(status_response.get("error") or "Local Agent status failed.")
|
||||
if run and tally_guid:
|
||||
result = request_agent_command(
|
||||
|
||||
if job_id:
|
||||
status = request_agent_command(
|
||||
node.node_code,
|
||||
"accounting_cash_payment_compliance",
|
||||
"accounting_cash_payment_cache_status",
|
||||
{
|
||||
**_accounting_storage_payload(selected_client, _financial_year_for_date(date.fromisoformat(start_text))),
|
||||
"tally_guid": str(tally_guid),
|
||||
"date_from": start_text,
|
||||
"date_to": end_text,
|
||||
"job_id": str(job_id),
|
||||
},
|
||||
timeout_seconds=20,
|
||||
)
|
||||
if status.get("ok"):
|
||||
cache_job = (status.get("result") or {}).get("job")
|
||||
else:
|
||||
command_error = str(status.get("error") or "Could not read cash-payment cache status.")
|
||||
|
||||
if analyze and job_id and cache_job and cache_job.get("status") == "completed":
|
||||
result = request_agent_command(
|
||||
node.node_code,
|
||||
"accounting_cash_payment_cache_analyze",
|
||||
{
|
||||
**_accounting_storage_payload(selected_client, _financial_year_for_date(date.fromisoformat(start_text))),
|
||||
"job_id": str(job_id),
|
||||
"cash_limit": float(setting.cash_limit),
|
||||
"split_window_days": int(setting.split_window_days),
|
||||
"near_limit_percent": float(setting.near_limit_percent),
|
||||
"tally_batch_days": 7,
|
||||
"tally_pause_seconds": 1.5,
|
||||
"tally_retry_pause_seconds": 3.0,
|
||||
},
|
||||
timeout_seconds=900,
|
||||
timeout_seconds=120,
|
||||
)
|
||||
if result.get("ok"):
|
||||
review = (result.get("result") or {}).get("cash_payment_review")
|
||||
else:
|
||||
command_error = str(result.get("error") or "Cash payment review failed.")
|
||||
command_error = str(result.get("error") or "Cash payment SQLite analysis failed.")
|
||||
except Exception as exc:
|
||||
command_error = str(exc)
|
||||
|
||||
@@ -223,6 +236,8 @@ def cash_payment_review(
|
||||
date_to=end_text,
|
||||
setting=setting,
|
||||
review=review,
|
||||
cache_job=cache_job,
|
||||
active_job_id=str(job_id or ""),
|
||||
saved=bool(saved),
|
||||
command_error=command_error,
|
||||
allocation_plan=None,
|
||||
@@ -233,6 +248,96 @@ def cash_payment_review(
|
||||
db.close()
|
||||
|
||||
|
||||
@router.post("/cache/start")
|
||||
async def start_cash_payment_cache(request: Request):
|
||||
form = await request.form()
|
||||
validate_csrf(request, str(form.get("csrf_token") or ""))
|
||||
db = CommonSessionLocal()
|
||||
try:
|
||||
user, response = _require_partner(request, db, "accounting.tally.view")
|
||||
if response:
|
||||
return JSONResponse({"ok": False, "error": "Access denied."}, status_code=403)
|
||||
clients, scope = _visible_clients(db, request, user)
|
||||
try:
|
||||
client_id = int(form.get("client_id") or 0)
|
||||
except Exception:
|
||||
client_id = 0
|
||||
selected_client = next((row for row in clients if int(row.id) == client_id), None)
|
||||
if not selected_client:
|
||||
return JSONResponse({"ok": False, "error": "Select a valid client."}, status_code=400)
|
||||
tally_guid = str(form.get("tally_guid") or "").strip()
|
||||
date_from = str(form.get("date_from") or "").strip()
|
||||
date_to = str(form.get("date_to") or "").strip()
|
||||
try:
|
||||
parsed_from = date.fromisoformat(date_from)
|
||||
parsed_to = date.fromisoformat(date_to)
|
||||
if parsed_to < parsed_from:
|
||||
raise ValueError("To date cannot be before From date.")
|
||||
except Exception as exc:
|
||||
return JSONResponse({"ok": False, "error": str(exc)}, status_code=400)
|
||||
if not tally_guid:
|
||||
return JSONResponse({"ok": False, "error": "Select a mapped Tally company."}, status_code=400)
|
||||
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=409)
|
||||
setting = _setting(db, _tenant_id(request, user))
|
||||
try:
|
||||
result = request_agent_command(
|
||||
node.node_code,
|
||||
"accounting_cash_payment_cache_start",
|
||||
{
|
||||
**_accounting_storage_payload(selected_client, _financial_year_for_date(parsed_from)),
|
||||
"tally_guid": tally_guid,
|
||||
"date_from": date_from,
|
||||
"date_to": date_to,
|
||||
"cash_limit": float(setting.cash_limit),
|
||||
"split_window_days": int(setting.split_window_days),
|
||||
"near_limit_percent": float(setting.near_limit_percent),
|
||||
"tally_pause_seconds": 3.0,
|
||||
"requested_by_user_id": int(user.id),
|
||||
},
|
||||
timeout_seconds=30,
|
||||
)
|
||||
except Exception as exc:
|
||||
return JSONResponse({"ok": False, "error": str(exc)}, status_code=502)
|
||||
if not result.get("ok"):
|
||||
return JSONResponse({"ok": False, "error": str(result.get("error") or "Could not start Tally extraction.")}, status_code=409)
|
||||
return JSONResponse({"ok": True, **(result.get("result") or {})})
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
@router.get("/cache/progress")
|
||||
def cash_payment_cache_progress(request: Request, client_id: int, job_id: str, date_from: str):
|
||||
db = CommonSessionLocal()
|
||||
try:
|
||||
user, response = _require_partner(request, db, "accounting.tally.view")
|
||||
if response:
|
||||
return JSONResponse({"ok": False, "error": "Access denied."}, status_code=403)
|
||||
clients, scope = _visible_clients(db, request, user)
|
||||
selected_client = next((row for row in clients if int(row.id) == int(client_id)), None)
|
||||
if not selected_client:
|
||||
return JSONResponse({"ok": False, "error": "Client not found."}, 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=409)
|
||||
try:
|
||||
fy = _financial_year_for_date(date.fromisoformat(date_from))
|
||||
result = request_agent_command(
|
||||
node.node_code,
|
||||
"accounting_cash_payment_cache_status",
|
||||
{**_accounting_storage_payload(selected_client, fy), "job_id": str(job_id)},
|
||||
timeout_seconds=20,
|
||||
)
|
||||
except Exception as exc:
|
||||
return JSONResponse({"ok": False, "error": str(exc)}, status_code=502)
|
||||
if not result.get("ok"):
|
||||
return JSONResponse({"ok": False, "error": str(result.get("error") or "Could not read extraction progress.")}, status_code=409)
|
||||
return JSONResponse({"ok": True, **(result.get("result") or {})})
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
@router.get("/allocation")
|
||||
def cash_payment_allocation(
|
||||
request: Request,
|
||||
@@ -263,6 +368,8 @@ def cash_payment_allocation(
|
||||
date_to="",
|
||||
setting=setting,
|
||||
review=None,
|
||||
cache_job=None,
|
||||
active_job_id="",
|
||||
saved=False,
|
||||
command_error=error or "",
|
||||
allocation_plan=None,
|
||||
@@ -383,6 +490,8 @@ async def cash_payment_allocation_plan(request: Request):
|
||||
date_to="",
|
||||
setting=setting,
|
||||
review=None,
|
||||
cache_job=None,
|
||||
active_job_id="",
|
||||
saved=False,
|
||||
command_error="",
|
||||
allocation_plan=plan,
|
||||
|
||||
Reference in New Issue
Block a user