Unify accounting analysis on Client FY mirror registry
This commit is contained in:
@@ -190,6 +190,39 @@ def _accounting_storage_payload(client, financial_year: str | None = None, *, db
|
||||
own_db.close()
|
||||
|
||||
|
||||
def _analysis_accounting_storage_payload(
|
||||
client,
|
||||
financial_year: str | None = None,
|
||||
*,
|
||||
db=None,
|
||||
tenant_id: int | None = None,
|
||||
) -> dict:
|
||||
"""Return the authoritative registered Client/FY mirror payload for analysis jobs.
|
||||
|
||||
Analytical procedures must never silently fall back to a deterministic folder.
|
||||
The fallback remains available to bootstrap/sync/write workflows through
|
||||
``_accounting_storage_payload``. Requiring a registry row here guarantees that
|
||||
every analysis is tied to the same Client/FY/version selected by
|
||||
``AccountingMirrorRegistry``.
|
||||
"""
|
||||
payload = _accounting_storage_payload(
|
||||
client,
|
||||
financial_year,
|
||||
db=db,
|
||||
tenant_id=tenant_id,
|
||||
)
|
||||
if not bool(payload.get("mirror_registered")):
|
||||
fy_value = str(payload.get("financial_year") or financial_year or "").strip()
|
||||
raise ValueError(
|
||||
f"No registered Accounting Mirror is available for FY {fy_value}. "
|
||||
"Create or register the Client/FY mirror from Tally Accounting first."
|
||||
)
|
||||
if not str(payload.get("accounting_relative_dir") or "").strip():
|
||||
raise ValueError("The registered Accounting Mirror has no storage path.")
|
||||
payload["analysis_source"] = "accounting_mirror_registry"
|
||||
return payload
|
||||
|
||||
|
||||
def _client_registrations(db, client, tenant_id: int):
|
||||
rows = db.execute(
|
||||
select(ClientRegistration, RegistrationType)
|
||||
@@ -535,7 +568,7 @@ def download_analysis_report(
|
||||
node.node_code,
|
||||
"accounting_analysis_get",
|
||||
{
|
||||
**_accounting_storage_payload(client, financial_year),
|
||||
**_analysis_accounting_storage_payload(client, financial_year, db=db, tenant_id=scope.tenant_id),
|
||||
"run_id": int(analysis_run_id),
|
||||
},
|
||||
timeout_seconds=30,
|
||||
@@ -1109,7 +1142,7 @@ def depreciation_it_tool(
|
||||
|
||||
if selected_client and node and online:
|
||||
selected_fy=_financial_year_for_date(date.fromisoformat(start_text))
|
||||
storage_payload=_accounting_storage_payload(selected_client,selected_fy)
|
||||
storage_payload=_analysis_accounting_storage_payload(selected_client,selected_fy,db=db,tenant_id=scope.tenant_id)
|
||||
try:
|
||||
status_response=request_agent_command(
|
||||
node.node_code,"accounting_mirror_status",storage_payload,timeout_seconds=20
|
||||
@@ -1124,7 +1157,7 @@ def depreciation_it_tool(
|
||||
prior_start=date(prior_start_year,4,1)
|
||||
prior_end=date(prior_start_year+1,3,31)
|
||||
prior_fy=_financial_year_for_date(prior_start)
|
||||
prior_payload=_accounting_storage_payload(selected_client,prior_fy)
|
||||
prior_payload=_analysis_accounting_storage_payload(selected_client,prior_fy,db=db,tenant_id=scope.tenant_id)
|
||||
prior_response=request_agent_command(
|
||||
node.node_code,"accounting_mirror_status",prior_payload,timeout_seconds=20
|
||||
)
|
||||
@@ -1222,7 +1255,7 @@ async def calculate_it_depreciation(request: Request):
|
||||
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/depreciation?client_id={client.id}&fy_start={start.isoformat()}&fy_end={end.isoformat()}&error={quote('ERP Local Agent is offline for the active branch.')}",status_code=303)
|
||||
try:
|
||||
result=request_agent_command(node.node_code,"accounting_calculate_it_depreciation",{**_accounting_storage_payload(client, _financial_year_for_date(start)),"fy_start":start.isoformat(),"fy_end":end.isoformat(),"assignments":assignments,"depreciation_expense_ledger":str(form.get("depreciation_expense_ledger") or ""),"depreciation_reserve_ledger":str(form.get("depreciation_reserve_ledger") or ""),"financial_year":_financial_year_for_date(start),"requested_by_user_id":int(user.id)},timeout_seconds=120)
|
||||
result=request_agent_command(node.node_code,"accounting_calculate_it_depreciation",{**_analysis_accounting_storage_payload(client, _financial_year_for_date(start), db=db, tenant_id=scope.tenant_id),"fy_start":start.isoformat(),"fy_end":end.isoformat(),"assignments":assignments,"depreciation_expense_ledger":str(form.get("depreciation_expense_ledger") or ""),"depreciation_reserve_ledger":str(form.get("depreciation_reserve_ledger") or ""),"financial_year":_financial_year_for_date(start),"requested_by_user_id":int(user.id)},timeout_seconds=120)
|
||||
if not result.get("ok"): raise RuntimeError(str(result.get("error") or "Income-tax depreciation calculation failed."))
|
||||
dep=(result.get("result") or {}).get("depreciation") or {}; rid=int(dep.get("run_id"))
|
||||
except Exception as exc:
|
||||
@@ -1255,7 +1288,7 @@ async def approve_it_depreciation(request: Request):
|
||||
try:
|
||||
result = request_agent_command(
|
||||
node.node_code, "accounting_approve_it_depreciation",
|
||||
{**_accounting_storage_payload(client, _financial_year_for_date(approval_fy_start)), "run_id": run_id, "approved_by_user_id": int(user.id), "approval_note": str(form.get("approval_note") or "")},
|
||||
{**_analysis_accounting_storage_payload(client, _financial_year_for_date(approval_fy_start), db=db, tenant_id=scope.tenant_id), "run_id": run_id, "approved_by_user_id": int(user.id), "approval_note": str(form.get("approval_note") or "")},
|
||||
timeout_seconds=30,
|
||||
)
|
||||
if not result.get("ok"): raise RuntimeError(str(result.get("error") or "Approval failed."))
|
||||
@@ -1293,7 +1326,7 @@ async def post_it_depreciation_to_tally(request: Request):
|
||||
try:
|
||||
result = request_agent_command(
|
||||
node.node_code, "accounting_post_it_depreciation",
|
||||
{**_accounting_storage_payload(client, _financial_year_for_date(posting_fy_start)), "run_id": run_id, "posted_by_user_id": int(user.id)},
|
||||
{**_analysis_accounting_storage_payload(client, _financial_year_for_date(posting_fy_start), db=db, tenant_id=scope.tenant_id), "run_id": run_id, "posted_by_user_id": int(user.id)},
|
||||
timeout_seconds=120,
|
||||
)
|
||||
if not result.get("ok"): raise RuntimeError(str(result.get("error") or "Tally write-back failed."))
|
||||
|
||||
Reference in New Issue
Block a user