122 lines
4.4 KiB
Python
122 lines
4.4 KiB
Python
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()
|