Add Phase 4 standard accounting classification taxonomy
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter, Form, Request
|
||||
from fastapi.responses import RedirectResponse
|
||||
|
||||
from app.core.db.common import CommonSessionLocal
|
||||
from app.core.security.csrf import get_or_create_csrf_token, validate_csrf
|
||||
from app.core.security.session_auth import get_current_user
|
||||
from app.core.templating import templates
|
||||
from app.modules.accounting.taxonomy_service import ensure_standard_taxonomy, grouped_taxonomy, list_taxonomy, set_nature_active
|
||||
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.services import build_document_scope
|
||||
|
||||
|
||||
router = APIRouter(prefix="/tools/accounting/taxonomy", tags=["accounting-taxonomy-ui"])
|
||||
|
||||
|
||||
def _denied():
|
||||
from app.core.http_responses import ui_access_denied
|
||||
return ui_access_denied()
|
||||
|
||||
|
||||
def _require_partner_permission(request: Request, db, permission: str):
|
||||
user = get_current_user(request, db)
|
||||
if not user:
|
||||
return None, RedirectResponse(url="/login", status_code=303)
|
||||
roles = set(get_user_roles(db, user.id))
|
||||
if "Partner" not in roles:
|
||||
return None, _denied()
|
||||
try:
|
||||
require_permission(db, user, permission)
|
||||
except Exception:
|
||||
return None, _denied()
|
||||
return user, None
|
||||
|
||||
|
||||
def _context(request: Request, db, user, **extra):
|
||||
data = {
|
||||
"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),
|
||||
}
|
||||
data.update(extra)
|
||||
return data
|
||||
|
||||
|
||||
@router.get("")
|
||||
def accounting_taxonomy(request: Request, status: str = "all", group: str = "", updated: int = 0):
|
||||
db = CommonSessionLocal()
|
||||
try:
|
||||
user, response = _require_partner_permission(request, db, "accounting.taxonomy.view")
|
||||
if response:
|
||||
return response
|
||||
scope = build_document_scope(request, db, user)
|
||||
ensure_standard_taxonomy(db, scope.tenant_id, user.id)
|
||||
status = status if status in {"all", "active", "inactive"} else "all"
|
||||
allowed_groups = {"purchase", "expense", "repairs", "capital", "statutory", "finance", "review"}
|
||||
group = group if group in allowed_groups else ""
|
||||
rows = list_taxonomy(db, scope.tenant_id, status=status, group=group)
|
||||
all_rows = list_taxonomy(db, scope.tenant_id)
|
||||
counts = {
|
||||
"total": sum(1 for r in all_rows if r.is_posting_nature),
|
||||
"active": sum(1 for r in all_rows if r.is_posting_nature and r.is_active),
|
||||
"inactive": sum(1 for r in all_rows if r.is_posting_nature and not r.is_active),
|
||||
"capital": sum(1 for r in all_rows if r.is_posting_nature and r.capital_revenue == "capital"),
|
||||
}
|
||||
return templates.TemplateResponse(
|
||||
"modules/accounting/templates/accounting/taxonomy.html",
|
||||
_context(
|
||||
request,
|
||||
db,
|
||||
user,
|
||||
taxonomy_groups=grouped_taxonomy(rows),
|
||||
rows=rows,
|
||||
counts=counts,
|
||||
selected_status=status,
|
||||
selected_group=group,
|
||||
updated=updated,
|
||||
),
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
@router.post("/{nature_id}/active")
|
||||
def update_accounting_nature_active(
|
||||
nature_id: int,
|
||||
request: Request,
|
||||
csrf_token: str = Form(...),
|
||||
is_active: str = Form(...),
|
||||
status: str = Form("all"),
|
||||
group: str = Form(""),
|
||||
):
|
||||
db = CommonSessionLocal()
|
||||
try:
|
||||
user, response = _require_partner_permission(request, db, "accounting.taxonomy.manage")
|
||||
if response:
|
||||
return response
|
||||
validate_csrf(request, csrf_token)
|
||||
scope = build_document_scope(request, db, user)
|
||||
try:
|
||||
row = set_nature_active(
|
||||
db,
|
||||
tenant_id=scope.tenant_id,
|
||||
nature_id=nature_id,
|
||||
is_active=is_active.strip().lower() in {"1", "true", "yes", "on"},
|
||||
actor_user_id=user.id,
|
||||
)
|
||||
except ValueError:
|
||||
return _denied()
|
||||
if row is None:
|
||||
return _denied()
|
||||
query = f"?updated=1&status={status if status in {'all','active','inactive'} else 'all'}"
|
||||
if group:
|
||||
query += f"&group={group}"
|
||||
return RedirectResponse(url=f"/tools/accounting/taxonomy{query}", status_code=303)
|
||||
finally:
|
||||
db.close()
|
||||
Reference in New Issue
Block a user