🔍 Code Extractor

function generate_audit_report

Maturity: 57

Generates a comprehensive audit report for a controlled document by aggregating document metadata, version history, review cycles, approvals, and categorized audit events.

File:
/tf/active/vicechatdev/CDocs/utils/audit_trail.py
Lines:
716 - 825
Complexity:
complex

Purpose

This function creates a detailed audit trail report for compliance and tracking purposes in a document management system. It retrieves document information from a Neo4j graph database, including all versions, review cycles, approvals, and historical events. The report organizes events by category and provides counts and summaries useful for regulatory audits, compliance reviews, and document lifecycle tracking.

Source Code

def generate_audit_report(document_uid: str) -> Dict[str, Any]:
    """
    Generate a comprehensive audit report for a document.
    
    Args:
        document_uid: UID of document
        
    Returns:
        Dictionary with audit report data
    """
    try:
        # Get document data
        query = """
        MATCH (d:ControlledDocument {UID: $doc_uid})
        OPTIONAL MATCH (d)-[:HAS_VERSION]->(v:DocumentVersion)
        OPTIONAL MATCH (d)-[:CURRENT_VERSION]->(cv:DocumentVersion)
        RETURN d, count(v) as versionCount, cv
        """
        
        doc_result = db.run_query(query, {"doc_uid": document_uid})
        if not doc_result:
            logger.error(f"Document not found: {document_uid}")
            return {"error": "Document not found"}
            
        document = doc_result[0]['d']
        version_count = doc_result[0]['versionCount']
        current_version = doc_result[0].get('cv')
        
        # Get all history events
        history = get_document_history(document_uid)
        
        # Organize events by category
        events_by_category = {}
        for event in history:
            category = event.get('eventCategory', 'OTHER')
            if category not in events_by_category:
                events_by_category[category] = []
            events_by_category[category].append(event)
            
        # Get review cycles
        query = """
        MATCH (d:ControlledDocument {UID: $doc_uid})-[:HAS_VERSION]->(v:DocumentVersion)
        MATCH (v)-[:FOR_REVIEW]->(r:ReviewCycle)
        OPTIONAL MATCH (r)-[:REVIEWED_BY]->(u:User)
        RETURN r.UID as reviewUID, r.status as status, r.startDate as startDate, 
               r.completionDate as completionDate, count(u) as reviewerCount
        ORDER BY r.startDate DESC
        """
        
        review_result = db.run_query(query, {"doc_uid": document_uid})
        reviews = [
            {
                'UID': record['reviewUID'],
                'status': record['status'],
                'startDate': record['startDate'],
                'completionDate': record['completionDate'],
                'reviewerCount': record['reviewerCount']
            }
            for record in review_result
        ]
        
        # Get approvals
        query = """
        MATCH (d:ControlledDocument {UID: $doc_uid})-[:HAS_VERSION]->(v:DocumentVersion)
        MATCH (v)-[:FOR_REVIEW]->(r:ReviewCycle)
        MATCH (r)-[:FOR_APPROVAL]->(a:Approval)
        OPTIONAL MATCH (a)-[:APPROVED_BY]->(u:User)
        RETURN a.UID as approvalUID, a.status as status, a.startDate as startDate, 
               a.completionDate as completionDate, count(u) as approverCount
        ORDER BY a.startDate DESC
        """
        
        approval_result = db.run_query(query, {"doc_uid": document_uid})
        approvals = [
            {
                'UID': record['approvalUID'],
                'status': record['status'],
                'startDate': record['startDate'],
                'completionDate': record['completionDate'],
                'approverCount': record['approverCount']
            }
            for record in approval_result
        ]
        
        # Build full report
        report = {
            'document': {
                'UID': document.get('UID'),
                'docNumber': document.get('docNumber'),
                'title': document.get('title'),
                'status': document.get('status'),
                'docType': document.get('docType'),
                'department': document.get('department'),
                'createdDate': document.get('createdDate')
            },
            'currentVersion': current_version,
            'versionCount': version_count,
            'reviews': reviews,
            'approvals': approvals,
            'eventCount': len(history),
            'eventsByCategory': events_by_category,
            'allEvents': history,
            'reportGeneratedAt': datetime.now()
        }
        
        return report
        
    except Exception as e:
        logger.error(f"Error generating audit report: {e}")
        return {"error": f"Error generating report: {e}"}

Parameters

Name Type Default Kind
document_uid str - positional_or_keyword

Parameter Details

document_uid: Unique identifier (UID) string for the controlled document. This should be a valid UID that exists in the Neo4j database as a ControlledDocument node. The function will return an error if the document is not found.

Return Value

Type: Dict[str, Any]

Returns a dictionary containing comprehensive audit report data. On success, includes keys: 'document' (metadata dict with UID, docNumber, title, status, docType, department, createdDate), 'currentVersion' (current DocumentVersion node data or None), 'versionCount' (integer count of versions), 'reviews' (list of review cycle dicts with UID, status, dates, reviewerCount), 'approvals' (list of approval dicts with UID, status, dates, approverCount), 'eventCount' (total number of audit events), 'eventsByCategory' (dict mapping category names to lists of events), 'allEvents' (complete list of all historical events), and 'reportGeneratedAt' (datetime of report generation). On error, returns a dict with single 'error' key containing error message string.

Dependencies

  • logging
  • uuid
  • typing
  • datetime
  • json
  • CDocs.db
  • CDocs.config
  • CDocs.db.schema_manager
  • CDocs.models.user_extensions

Required Imports

from typing import Dict, Any
from datetime import datetime
import logging
from CDocs import db

Usage Example

from typing import Dict, Any
from datetime import datetime
import logging
from CDocs import db

# Assuming logger and get_document_history are available
logger = logging.getLogger(__name__)

# Generate audit report for a specific document
document_uid = "DOC-12345-ABCD"
report = generate_audit_report(document_uid)

if "error" in report:
    print(f"Error generating report: {report['error']}")
else:
    print(f"Document: {report['document']['title']}")
    print(f"Total versions: {report['versionCount']}")
    print(f"Total events: {report['eventCount']}")
    print(f"Reviews: {len(report['reviews'])}")
    print(f"Approvals: {len(report['approvals'])}")
    
    # Access events by category
    for category, events in report['eventsByCategory'].items():
        print(f"{category}: {len(events)} events")
    
    # Report generation timestamp
    print(f"Report generated at: {report['reportGeneratedAt']}")

Best Practices

  • Always check for 'error' key in returned dictionary before accessing report data
  • Ensure the document_uid exists in the database before calling this function to avoid unnecessary database queries
  • The function depends on get_document_history() being available in the same module - ensure this dependency is satisfied
  • Consider caching report results for frequently accessed documents to reduce database load
  • The function uses multiple database queries which may be slow for documents with extensive history - consider pagination for large datasets
  • Ensure proper error logging is configured as the function logs errors using module-level logger
  • The reportGeneratedAt timestamp is in server local time - consider timezone handling for distributed systems
  • Review cycles and approvals are ordered by startDate DESC, with most recent first
  • Events are categorized using 'eventCategory' field - ensure audit events have this field populated for proper categorization

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function get_document_audit_trail 79.4% similar

    Retrieves the complete audit trail for a controlled document from a Neo4j graph database, including timestamps, user actions, and event details.

    From: /tf/active/vicechatdev/document_controller_backup.py
  • function get_document_history 77.9% similar

    Retrieves the complete audit history for a document by querying events across document, version, review, comment, and approval nodes in a Neo4j graph database.

    From: /tf/active/vicechatdev/CDocs/utils/audit_trail.py
  • function get_document 67.2% similar

    Retrieves comprehensive details of a controlled document by its UID, with optional inclusion of version history, review cycles, and approval cycles.

    From: /tf/active/vicechatdev/document_controller_backup.py
  • function get_document_with_relationships 66.1% similar

    Retrieves a complete document from Neo4j graph database along with all its related entities including versions, reviews, approvals, and authors.

    From: /tf/active/vicechatdev/CDocs/db/db_operations.py
  • function get_document_training_info 65.7% similar

    Retrieves comprehensive training information for a specific controlled document, including training configuration, assigned users, completion status, and statistics.

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