🔍 Code Extractor

function get_approval_statistics_v1

Maturity: 54

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.

File:
/tf/active/vicechatdev/CDocs/controllers/approval_controller.py
Lines:
1683 - 1791
Complexity:
moderate

Purpose

This function provides system-wide analytics for approval workflows by querying the Neo4j database for ApprovalCycle and ApproverAssignment nodes. It calculates key metrics including total approvals, pending approvals, completed approvals (both approved and rejected), and approval rates at both the cycle and individual decision levels. The function is designed to support dashboard displays, reporting, and monitoring of approval system health and performance.

Source Code

def get_approval_statistics() -> Dict[str, Any]:
    """
    Get approval statistics for the system.
    
    Returns:
        Dictionary with approval statistics
    """
    try:
        query = """
        // Count all approval cycles
        MATCH (r:ApprovalCycle)
        WITH count(r) as total_approvals
        
        // Count pending and in-progress approvals
        OPTIONAL MATCH (r:ApprovalCycle)
        WHERE r.status = 'PENDING' OR r.status = 'IN_PROGRESS'
        WITH count(r) as pending_approvals, total_approvals
        
        // Count completed approvals with approved decision
        OPTIONAL MATCH (r:ApprovalCycle)
        WHERE r.status = 'COMPLETED' AND r.decision = 'APPROVED'
        WITH count(r) as approved_approvals, pending_approvals, total_approvals
        
        // Count completed approvals with rejected decision
        OPTIONAL MATCH (r:ApprovalCycle)
        WHERE r.status = 'COMPLETED' AND r.decision = 'REJECTED'
        WITH count(r) as rejected_approvals, approved_approvals, pending_approvals, total_approvals
        
        // Count approver assignments with approved decisions
        OPTIONAL MATCH (ra:ApproverAssignment)
        WHERE ra.status = 'COMPLETED' AND 
             (ra.decision = 'APPROVED' OR ra.decision = 'APPROVED_WITH_COMMENTS')
        WITH count(ra) as approved_decisions,
             rejected_approvals, approved_approvals, pending_approvals, total_approvals
        
        // Count approver assignments with rejected decisions
        OPTIONAL MATCH (ra:ApproverAssignment)
        WHERE ra.status = 'COMPLETED' AND ra.decision = 'REJECTED'
        WITH count(ra) as rejected_decisions,
             approved_decisions, rejected_approvals, approved_approvals, 
             pending_approvals, total_approvals
        
        RETURN {
            total_approvals: total_approvals,
            pending_approvals: pending_approvals,
            completed_approvals: (approved_approvals + rejected_approvals),
            approved_approvals: approved_approvals,
            rejected_approvals: rejected_approvals,
            approval_approval_rate: CASE 
                WHEN (approved_approvals + rejected_approvals) > 0 
                THEN 100.0 * approved_approvals / (approved_approvals + rejected_approvals)
                ELSE 0
                END,
            approved_decisions: approved_decisions,
            rejected_decisions: rejected_decisions,
            decision_approval_rate: CASE
                WHEN (approved_decisions + rejected_decisions) > 0
                THEN 100.0 * approved_decisions / (approved_decisions + rejected_decisions)
                ELSE 0
                END
        } as statistics
        """
        
        # Execute query
        result = db.run_query(query)
        
        if not result or len(result) == 0 or 'statistics' not in result[0]:
            # Return default statistics if query returned no results
            return {
                "success": True,
                "statistics": {
                    "total_approvals": 0,
                    "pending_approvals": 0,
                    "completed_approvals": 0,
                    "approved_approvals": 0,
                    "rejected_approvals": 0,
                    "approval_approval_rate": 0,
                    "approved_decisions": 0,
                    "rejected_decisions": 0,
                    "decision_approval_rate": 0
                }
            }
        
        # Return statistics from query
        return {
            "success": True,
            "statistics": result[0].get('statistics', {})
        }
        
    except Exception as e:
        logger.error(f"Error getting approval statistics: {e}")
        logger.error(traceback.format_exc())
        
        # Return error with default statistics
        return {
            "success": False,
            "statistics": {
                "total_approvals": 0,
                "pending_approvals": 0,
                "completed_approvals": 0,
                "approved_approvals": 0,
                "rejected_approvals": 0,
                "approval_approval_rate": 0,
                "approved_decisions": 0,
                "rejected_decisions": 0,
                "decision_approval_rate": 0
            },
            "error": str(e)
        }

Return Value

Type: Dict[str, Any]

Returns a dictionary with structure: {'success': bool, 'statistics': dict, 'error': str (optional)}. The 'statistics' dictionary contains: 'total_approvals' (int: total count of approval cycles), 'pending_approvals' (int: cycles with PENDING or IN_PROGRESS status), 'completed_approvals' (int: sum of approved and rejected cycles), 'approved_approvals' (int: cycles with COMPLETED status and APPROVED decision), 'rejected_approvals' (int: cycles with COMPLETED status and REJECTED decision), 'approval_approval_rate' (float: percentage of approved cycles out of completed cycles), 'approved_decisions' (int: approver assignments with APPROVED or APPROVED_WITH_COMMENTS decisions), 'rejected_decisions' (int: approver assignments with REJECTED decisions), 'decision_approval_rate' (float: percentage of approved decisions out of total decisions). On error, 'success' is False and 'error' contains the error message, with default zero values for all statistics.

Dependencies

  • logging
  • uuid
  • os
  • typing
  • datetime
  • traceback
  • CDocs
  • CDocs.config
  • CDocs.models.document
  • CDocs.models.approval
  • CDocs.models.user_extensions
  • CDocs.utils
  • CDocs.controllers
  • CDocs.controllers.share_controller
  • CDocs.db
  • CDocs.utils.notifications
  • CDocs.controllers.document_controller

Required Imports

import logging
import traceback
from typing import Dict, Any
from CDocs import db
from CDocs.controllers import log_controller_action

Usage Example

from CDocs.controllers import log_controller_action
from CDocs import db
import logging

# Ensure logger is configured
logger = logging.getLogger(__name__)

# Decorate and call the function
@log_controller_action('get_approval_statistics')
def get_approval_statistics():
    # Function implementation here
    pass

# Call the function
result = get_approval_statistics()

if result['success']:
    stats = result['statistics']
    print(f"Total Approvals: {stats['total_approvals']}")
    print(f"Pending Approvals: {stats['pending_approvals']}")
    print(f"Approval Rate: {stats['approval_approval_rate']:.2f}%")
    print(f"Decision Approval Rate: {stats['decision_approval_rate']:.2f}%")
else:
    print(f"Error: {result.get('error', 'Unknown error')}")

Best Practices

  • Always check the 'success' field in the returned dictionary before accessing statistics
  • The function returns default zero values for all statistics on error, ensuring consistent response structure
  • Approval rates are calculated as percentages (0-100) and return 0 when there are no completed approvals to avoid division by zero
  • The function uses OPTIONAL MATCH clauses to handle cases where no data exists in the database
  • Error details are logged using the logger and included in the response for debugging
  • The decorator log_controller_action should be applied to track function execution
  • Consider caching results if calling frequently, as the Cypher query performs multiple database scans
  • The function distinguishes between approval cycle-level statistics and individual approver decision statistics
  • Ensure proper Neo4j database connection and error handling at the db.run_query level

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function get_approval_statistics 83.8% similar

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

    From: /tf/active/vicechatdev/CDocs/controllers/approval_controller_bis.py
  • function get_review_statistics 83.1% 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_system_stats 73.5% similar

    Retrieves comprehensive system statistics from a Neo4j graph database for display on an admin dashboard, including user counts, document counts, review cycles, and approval metrics.

    From: /tf/active/vicechatdev/CDocs/controllers/admin_controller.py
  • function get_approval_cycle 69.9% 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_document_stats 65.8% similar

    Retrieves aggregated statistics about controlled documents from a Neo4j database, including status and type distributions for visualization in charts.

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