🔍 Code Extractor

function get_approval_statistics

Maturity: 59

Retrieves and calculates approval cycle statistics for a specified date range, including counts by status, average completion time, and overdue approvals.

File:
/tf/active/vicechatdev/CDocs/controllers/approval_controller_bis.py
Lines:
1403 - 1493
Complexity:
moderate

Purpose

This function provides comprehensive reporting statistics for approval cycles within a document management system. It queries a Neo4j graph database to aggregate approval data, including total approvals, status breakdowns (approved, rejected, in progress, cancelled), average completion time in days, and current overdue approvals. The function enforces permission checks to ensure only authorized users can view reports and provides default date ranges if not specified.

Source Code

def get_approval_statistics(
    user: DocUser,
    date_from: Optional[datetime] = None,
    date_to: Optional[datetime] = None
) -> Dict[str, Any]:
    """
    Get approval statistics for reporting.
    
    Args:
        user: The requesting user
        date_from: Start date for statistics
        date_to: End date for statistics
        
    Returns:
        Dictionary with approval statistics
    """
    try:
        # Check permissions
        if not permissions.user_has_permission(user, "VIEW_REPORTS"):
            raise PermissionError("You do not have permission to view approval statistics")
            
        # Set default date range if not provided
        if not date_to:
            date_to = datetime.now()
            
        if not date_from:
            date_from = date_to - timedelta(days=30)  # Last 30 days by default
            
        # Query statistics
        result = db.run_query(
            """
            MATCH (a:ApprovalCycle)
            WHERE a.createdAt >= $date_from AND a.createdAt <= $date_to
            RETURN 
                count(a) as total_approvals,
                sum(CASE WHEN a.status = 'APPROVED' THEN 1 ELSE 0 END) as approved_count,
                sum(CASE WHEN a.status = 'REJECTED' THEN 1 ELSE 0 END) as rejected_count,
                sum(CASE WHEN a.status = 'IN_APPROVAL' THEN 1 ELSE 0 END) as in_progress_count,
                sum(CASE WHEN a.status = 'CANCELLED' THEN 1 ELSE 0 END) as cancelled_count,
                avg(CASE 
                    WHEN a.completionDate IS NOT NULL 
                    THEN duration.between(a.createdAt, a.completionDate).days 
                    ELSE null 
                END) as avg_completion_days
            """,
            {
                "date_from": date_from,
                "date_to": date_to
            }
        )
        
        # Process statistics
        stats = result[0] if result else {}
        
        # Get overdue approvals
        overdue_query = db.run_query(
            """
            MATCH (a:ApprovalCycle)
            WHERE a.status = 'IN_APPROVAL' AND a.dueDate < datetime()
            RETURN count(a) as overdue_count
            """
        )
        
        overdue_count = overdue_query[0]['overdue_count'] if overdue_query else 0
        
        return {
            "success": True,
            "statistics": {
                "total_approvals": stats.get('total_approvals', 0),
                "approved_count": stats.get('approved_count', 0),
                "rejected_count": stats.get('rejected_count', 0),
                "in_progress_count": stats.get('in_progress_count', 0),
                "cancelled_count": stats.get('cancelled_count', 0),
                "overdue_count": overdue_count,
                "avg_completion_days": stats.get('avg_completion_days', 0)
            },
            "period": {
                "from": date_from.isoformat(),
                "to": date_to.isoformat()
            }
        }
        
    except PermissionError as e:
        logger.warning(f"Permission error getting approval statistics: {e}")
        return {"success": False, "message": str(e)}
        
    except Exception as e:
        logger.error(f"Unexpected error getting approval statistics: {e}")
        import traceback
        logger.error(traceback.format_exc())
        return {"success": False, "message": "An unexpected error occurred"}

Parameters

Name Type Default Kind
user DocUser - positional_or_keyword
date_from Optional[datetime] None positional_or_keyword
date_to Optional[datetime] None positional_or_keyword

Parameter Details

user: A DocUser object representing the requesting user. Must have 'VIEW_REPORTS' permission to access approval statistics. Used for authorization checks.

date_from: Optional datetime object specifying the start date for the statistics query. If not provided, defaults to 30 days before date_to. Filters ApprovalCycle nodes by their createdAt timestamp.

date_to: Optional datetime object specifying the end date for the statistics query. If not provided, defaults to the current datetime. Filters ApprovalCycle nodes by their createdAt timestamp.

Return Value

Type: Dict[str, Any]

Returns a dictionary with structure: {'success': bool, 'statistics': dict, 'period': dict, 'message': str}. On success, 'statistics' contains total_approvals, approved_count, rejected_count, in_progress_count, cancelled_count, overdue_count, and avg_completion_days. The 'period' key contains ISO-formatted 'from' and 'to' dates. On failure, returns {'success': False, 'message': error_description}.

Dependencies

  • typing
  • datetime
  • logging
  • traceback
  • CDocs

Required Imports

from typing import Dict, Any, Optional
from datetime import datetime, timedelta
import logging
from CDocs import db
from CDocs.config import permissions
from CDocs.models.user_extensions import DocUser
from CDocs.controllers import log_controller_action, PermissionError

Conditional/Optional Imports

These imports are only needed under specific conditions:

import traceback

Condition: only used in exception handling for detailed error logging

Optional

Usage Example

from datetime import datetime, timedelta
from CDocs.models.user_extensions import DocUser
from CDocs.controllers import get_approval_statistics

# Get statistics for the last 30 days (default)
user = DocUser.get_by_id('user123')
stats = get_approval_statistics(user)

if stats['success']:
    print(f"Total approvals: {stats['statistics']['total_approvals']}")
    print(f"Approved: {stats['statistics']['approved_count']}")
    print(f"Average completion: {stats['statistics']['avg_completion_days']} days")

# Get statistics for a custom date range
date_from = datetime(2024, 1, 1)
date_to = datetime(2024, 1, 31)
stats = get_approval_statistics(user, date_from, date_to)

if not stats['success']:
    print(f"Error: {stats['message']}")

Best Practices

  • Always check the 'success' field in the returned dictionary before accessing statistics data
  • Ensure the user object has the 'VIEW_REPORTS' permission before calling this function to avoid PermissionError
  • Use appropriate date ranges to avoid performance issues with large datasets; the default 30-day range is recommended
  • The function is decorated with @log_controller_action, so all calls are automatically logged for audit purposes
  • Handle both PermissionError and general Exception cases when calling this function
  • The avg_completion_days calculation only includes completed approval cycles (those with completionDate set)
  • Overdue count is calculated separately and represents current overdue approvals, not historical ones within the date range

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function get_approval_statistics_v1 83.8% similar

    Retrieves comprehensive approval statistics from a Neo4j graph database, including counts of total, pending, completed, approved, and rejected approval cycles and decisions, along with calculated approval rates.

    From: /tf/active/vicechatdev/CDocs/controllers/approval_controller.py
  • function get_review_statistics 69.5% similar

    Retrieves comprehensive review statistics from a Neo4j graph database, including counts of review cycles, approval rates, and reviewer decisions.

    From: /tf/active/vicechatdev/CDocs/controllers/review_controller.py
  • function get_approval_cycle 68.4% similar

    Retrieves detailed information about an approval cycle by its UID, with optional inclusion of comments and associated document details.

    From: /tf/active/vicechatdev/CDocs/controllers/approval_controller.py
  • function get_user_pending_approvals 66.8% similar

    Retrieves all pending approval assignments for a specific user, with optional filtering by completion status and date range, returning structured approval data for UI display.

    From: /tf/active/vicechatdev/CDocs/controllers/approval_controller.py
  • function get_user_assigned_approvals 64.5% similar

    Retrieves and paginates approval cycles assigned to a specific user, with optional filtering by status and completion state.

    From: /tf/active/vicechatdev/CDocs/controllers/approval_controller_bis.py
← Back to Browse