diff --git a/app/modules/accounting/cash_payment_ui.py b/app/modules/accounting/cash_payment_ui.py index a751bfe..b902336 100644 --- a/app/modules/accounting/cash_payment_ui.py +++ b/app/modules/accounting/cash_payment_ui.py @@ -307,6 +307,52 @@ async def start_cash_payment_cache(request: Request): db.close() +@router.post("/cache/cancel") +async def cancel_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) + job_id = str(form.get("job_id") or "").strip() + date_from = str(form.get("date_from") or "").strip() + if not job_id: + return JSONResponse({"ok": False, "error": "Extraction job id is required."}, status_code=400) + try: + parsed_from = date.fromisoformat(date_from) + except Exception: + return JSONResponse({"ok": False, "error": "Valid extraction From date is required."}, 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) + result = request_agent_command( + node.node_code, + "accounting_cash_payment_cache_cancel", + { + **_accounting_storage_payload(selected_client, _financial_year_for_date(parsed_from)), + "job_id": job_id, + }, + timeout_seconds=15, + ) + if not result.get("ok"): + return JSONResponse({"ok": False, "error": str(result.get("error") or "Could not cancel extraction.")}, status_code=409) + return JSONResponse({"ok": True, **(result.get("result") or {})}) + except Exception as exc: + return JSONResponse({"ok": False, "error": str(exc)}, status_code=502) + 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() diff --git a/app/modules/accounting/templates/accounting/cash_payment_review.html b/app/modules/accounting/templates/accounting/cash_payment_review.html index 4d9a16d..9146fa8 100644 --- a/app/modules/accounting/templates/accounting/cash_payment_review.html +++ b/app/modules/accounting/templates/accounting/cash_payment_review.html @@ -152,7 +152,10 @@

Only one day is requested from TallyPrime at a time. The agent waits about 3 seconds after every successful day. If Tally responds slowly, it cools for 20 seconds and retries only once. The tunnel heartbeat stays responsive because progress is read from SQLite, not from Tally.

-
+
+ + +