Fix live Purchase and Sales historical Tally sync

This commit is contained in:
A R R R Associates
2026-08-23 11:48:09 +05:30
parent 395f4eed1a
commit 6910b5b6b5
8 changed files with 293 additions and 68 deletions
@@ -13,6 +13,7 @@ from app.core.templating import templates
from app.modules.accounting.historical_learning_models import AccountingHistoricalLearningRun
from app.modules.accounting.historical_learning_service import active_natures, classifiable_ledgers, evidence_rows, ingest_completed_run, ledger_mappings, party_suggestions, remove_ledger_mapping, save_ledger_mapping
from app.modules.accounting.ui import _accounting_storage_payload, _find_visible_client, _require_partner, _visible_clients
from app.modules.accounting.historical_sync_support import eligible_tally_workstations, resolve_workstation_company, workstation_companies
from app.modules.core.rbac.deps import get_user_permissions, get_user_roles
from app.modules.core.rbac.permission_guard import require_permission
from app.modules.documents.agent_jobs import enqueue_agent_job
@@ -31,17 +32,6 @@ def _fy_dates():
return date(y,4,1).isoformat(), today.isoformat()
def _companies(workstation):
try: rows=json.loads(workstation.tally_companies_json or "[]")
except Exception: rows=[]
return rows if isinstance(rows,list) else []
def _workstations(db, tenant_id: int, branch_id: int | None):
stmt=select(ERPWorkstationAgent).where(ERPWorkstationAgent.tenant_id==tenant_id, ERPWorkstationAgent.is_active.is_(True))
if branch_id is not None: stmt=stmt.where(ERPWorkstationAgent.branch_id==branch_id)
return list(db.execute(stmt.order_by(ERPWorkstationAgent.last_seen_at_utc.desc())).scalars().all())
def _sync_runs(db, tenant_id: int, client_id: int):
runs=list(db.execute(select(AccountingHistoricalLearningRun).where(AccountingHistoricalLearningRun.tenant_id==tenant_id, AccountingHistoricalLearningRun.client_id==client_id).order_by(AccountingHistoricalLearningRun.id.desc()).limit(10)).scalars().all())
@@ -59,7 +49,7 @@ def historical_learning(request: Request, client_id: int | None=None, collected:
clients,scope=_visible_clients(db,request,user)
selected=next((c for c in clients if client_id and int(c.id)==int(client_id)),None)
runs=[]; evid=[]; ledgers=[]; suggestions=[]; mappings=[]
workstations=_workstations(db, scope.tenant_id, scope.branch_id)
workstations=eligible_tally_workstations(db, scope.tenant_id, scope.branch_id)
if selected:
runs=_sync_runs(db,scope.tenant_id,selected.id)
evid=evidence_rows(db,scope.tenant_id,selected.id)
@@ -69,7 +59,7 @@ def historical_learning(request: Request, client_id: int | None=None, collected:
df,dt=_fy_dates()
return templates.TemplateResponse("modules/accounting/templates/accounting/historical_learning.html", {
"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),
"title":"Historical Tally Learning","clients":clients,"selected_client":selected,"workstations":workstations,"workstation_companies":{w.id:_companies(w) for w in workstations},
"title":"Historical Tally Learning","clients":clients,"selected_client":selected,"workstations":workstations,"workstation_companies":{w.id:workstation_companies(w) for w in workstations},
"runs":runs,"evidence":evid,"classifiable_ledgers":ledgers,"suggestions":suggestions,"mappings":mappings,"natures":active_natures(db,scope.tenant_id),
"date_from":df,"date_to":dt,"collected":bool(collected),"mapped":bool(mapped),"error":error,
})
@@ -84,14 +74,29 @@ def collect(request: Request, client_id: int=Form(...), workstation_id: int=Form
if response:return response
client,_,scope=_find_visible_client(db,request,user,client_id)
if not client:return _denied()
workstation=db.get(ERPWorkstationAgent,workstation_id)
if not workstation or not workstation.is_active or workstation.tenant_id!=scope.tenant_id or (scope.branch_id is not None and workstation.branch_id!=scope.branch_id): return _denied()
guid=str(tally_guid or "").strip()
if not guid: return RedirectResponse(url=f"/tools/accounting/historical-learning?client_id={client_id}&error=company_required",status_code=303)
payload=_accounting_storage_payload(client); payload.update({"tenant_id":scope.tenant_id,"requested_by_user_id":user.id,"tally_guid":guid,"date_from":date_from,"date_to":date_to,"voucher_scope":"purchase"})
if not guid:
return RedirectResponse(url=f"/tools/accounting/historical-learning?client_id={client_id}&error=company_required",status_code=303)
workstation, company = resolve_workstation_company(
db,
workstation_id=workstation_id,
tenant_id=scope.tenant_id,
branch_id=scope.branch_id,
tally_guid=guid,
)
payload=_accounting_storage_payload(client); payload.update({
"tenant_id":scope.tenant_id,
"requested_by_user_id":user.id,
"tally_guid":guid,
"company_name":str(company.get("name") or company_name or "").strip(),
"date_from":date_from,
"date_to":date_to,
"voucher_scope":"purchase",
"refresh_transactions":True,
})
job=enqueue_agent_job(db,workstation_agent_id=workstation.id,action="accounting_historical_evidence",payload=payload,priority=6,max_attempts=2,created_by_user_id=user.id)
db.flush()
run=AccountingHistoricalLearningRun(tenant_id=scope.tenant_id,client_id=client.id,workstation_agent_id=workstation.id,agent_job_id=job.id,tally_guid=guid,company_name=company_name or "",date_from=date_from or None,date_to=date_to or None,status="queued",requested_by_user_id=user.id)
run=AccountingHistoricalLearningRun(tenant_id=scope.tenant_id,client_id=client.id,workstation_agent_id=workstation.id,agent_job_id=job.id,tally_guid=guid,company_name=str(company.get("name") or company_name or ""),date_from=date_from or None,date_to=date_to or None,status="queued",requested_by_user_id=user.id)
db.add(run); db.commit()
return RedirectResponse(url=f"/tools/accounting/historical-learning?client_id={client_id}&collected=1",status_code=303)
except Exception as exc: