Switch GST operator agent to custom protocol launch

This commit is contained in:
A R R R Associates
2026-09-11 12:40:00 +05:30
parent a32132348d
commit b361a66e44
7 changed files with 181 additions and 287 deletions
@@ -144,12 +144,12 @@ def extract_gstr3b_itc(data) -> dict[str, float]:
return totals
router = APIRouter(prefix="/tools/accounting/gst-reconciliation", tags=["accounting-gst-reconciliation-ui"])
_TOKEN_PURPOSE = "gst_lightweight_operator_v2"
_TOKEN_PURPOSE = "gst_lightweight_operator_v3"
_TOKEN_MINUTES = 15
_UPLOAD_ROOT = Path(tempfile.gettempdir()) / "audit_firm_gst_operator_uploads"
_OPERATOR_AGENT_VERSION = "1.0.1"
_OPERATOR_AGENT_PORT = 8791
_OPERATOR_AGENT_VERSION = "1.1.0"
_OPERATOR_RUNTIME_ROOT = Path(__file__).resolve().parent / "gst_operator_agent_runtime"
_OPERATOR_PACKAGE_FILES = ("gst_operator_agent.py", "requirements.txt", "README.txt", "install_gst_operator_agent.ps1", "uninstall_gst_operator_agent.ps1")
def _fy_bounds(fy: str) -> tuple[date, date]:
@@ -414,7 +414,7 @@ def page(request: Request, client_id: int | None = None, registration_id: int |
"request":request,"current_user":user,"current_user_roles":get_user_roles(db,user.id),"current_user_permissions":get_user_permissions(db,user.id),"csrf_token":get_or_create_csrf_token(request),
"clients":clients,"selected_client":selected,"registrations":registrations,"selected_registration":selected_reg,"credentials":credentials,"node":node,"node_online":_node_online(node) if node else False,
"period":period,"financial_year":financial_year,"download_mode":download_mode,"operator_job":operator_job,"gst_login_url":GST_LOGIN_URL,
"operator_agent_version":_OPERATOR_AGENT_VERSION,"operator_agent_port":_OPERATOR_AGENT_PORT,
"operator_agent_version":_OPERATOR_AGENT_VERSION,
"message":message,"error":error,"title":"GST Return Reconciliation",
})
finally:
@@ -432,9 +432,11 @@ def download_operator_agent(request: Request):
return JSONResponse({"ok": False, "error": "GST Operator Agent runtime is missing from this ERP build."}, status_code=404)
memory = io.BytesIO()
with zipfile.ZipFile(memory, "w", zipfile.ZIP_DEFLATED, compresslevel=6) as archive:
for path in sorted(_OPERATOR_RUNTIME_ROOT.rglob("*")):
if path.is_file() and "__pycache__" not in path.parts:
archive.write(path, Path("ARRR_GST_Operator_Agent") / path.relative_to(_OPERATOR_RUNTIME_ROOT))
for name in _OPERATOR_PACKAGE_FILES:
path = _OPERATOR_RUNTIME_ROOT / name
if not path.is_file():
return JSONResponse({"ok": False, "error": f"GST Operator Agent package file is missing: {name}"}, status_code=500)
archive.write(path, Path("ARRR_GST_Operator_Agent") / name)
memory.seek(0)
headers = {"Content-Disposition": f'attachment; filename="ARRR_GST_Operator_Agent_{_OPERATOR_AGENT_VERSION}.zip"'}
return StreamingResponse(memory, media_type="application/zip", headers=headers)
@@ -484,8 +486,8 @@ def start_download(
})
log_access(db,request,user,cred,"use_for_gst_download",reason=f"GST returns {financial_year}: {','.join(return_types)}",fields="username,secret",success=True)
db.commit()
request.session["gst_operator_job"]={"token":token,"job_id":jti,"periods":periods,"return_types":return_types}
return _redirect(client_id,registration_id=registration_id,period=period,financial_year=financial_year,download_mode=download_mode,message="GST download prepared. The lightweight GST Operator Agent on this computer will open the visible GST browser and autofill the selected Credential Vault login. Complete CAPTCHA/OTP there; downloaded return data will then be transferred to the configured client storage.")
request.session["gst_operator_job"]={"job_id":jti,"periods":periods,"return_types":return_types,"launch_url":"arrrgst://start?"+urlencode({"token":token})}
return _redirect(client_id,registration_id=registration_id,period=period,financial_year=financial_year,download_mode=download_mode,message="GST download prepared. Windows will launch the lightweight GST Operator Agent through the ARRR GST protocol. The agent will open the visible GST browser and autofill the selected Credential Vault login. Complete CAPTCHA/OTP there; downloaded return data will then be transferred to the configured client storage.")
except Exception as exc:
db.rollback(); return _redirect(client_id,registration_id=registration_id,period=period,financial_year=financial_year,download_mode=download_mode,error=str(exc))
finally: