🔍 Code Extractor

function remove_training_assignment

Maturity: 58

Removes a training assignment relationship between a user and a controlled document in a Neo4j graph database, with audit logging and permission checks.

File:
/tf/active/vicechatdev/CDocs/controllers/training_controller.py
Lines:
450 - 564
Complexity:
moderate

Purpose

This function is used in a document management system to revoke a training requirement for a specific user on a controlled document. It parses a composite assignment UID (user_uid-document_uid), validates the assignment exists, deletes the REQUIRES_TRAINING relationship in Neo4j, and logs the removal event for audit purposes. This is typically used by administrators managing training compliance requirements.

Source Code

def remove_training_assignment(
    user: DocUser,
    assignment_uid: str
) -> Dict[str, Any]:
    """
    Remove a training assignment.
    
    Args:
        user: Admin user removing the assignment
        assignment_uid: Assignment UID (format: user_uid-document_uid)
        
    Returns:
        Dictionary with operation status
    """
    try:
        # Parse the assignment_uid to get user and document UIDs
        parts = assignment_uid.split('-')
        if len(parts) < 8:  # UUID has 5 parts, so we need at least 8 for user-document
            return {
                "success": False,
                "message": "Invalid assignment ID format"
            }
        
        # Find the split point - UUID format is 8-4-4-4-12 characters
        # So we look for a pattern that matches this
        user_uid = None
        document_uid = None
        
        for i in range(1, len(parts)):
            potential_user_uid = '-'.join(parts[:i])
            potential_document_uid = '-'.join(parts[i:])
            
            # Check if both parts look like UUIDs (36 characters)
            if len(potential_user_uid) == 36 and len(potential_document_uid) == 36:
                user_uid = potential_user_uid
                document_uid = potential_document_uid
                break
        
        if not user_uid or not document_uid:
            return {
                "success": False,
                "message": "Could not parse assignment ID"
            }
        
        # Check if assignment exists
        check_query = """
        MATCH (u:User {UID: $user_uid})-[r:REQUIRES_TRAINING]->(d:ControlledDocument {UID: $document_uid})
        RETURN r, u.Name as user_name, d.title as doc_title
        """
        
        result = db.run_query(check_query, {
            'user_uid': user_uid,
            'document_uid': document_uid
        })
        
        if not result:
            return {
                "success": False,
                "message": "Training assignment not found"
            }
        
        assignment_data = result[0]
        user_name = assignment_data.get('user_name', 'Unknown')
        doc_title = assignment_data.get('doc_title', 'Unknown Document')
        
        # Remove the training assignment relationship
        remove_query = """
        MATCH (u:User {UID: $user_uid})-[r:REQUIRES_TRAINING]->(d:ControlledDocument {UID: $document_uid})
        DELETE r
        RETURN count(r) as deleted_count
        """
        
        remove_result = db.run_query(remove_query, {
            'user_uid': user_uid,
            'document_uid': document_uid
        })
        
        if not remove_result or remove_result[0].get('deleted_count', 0) == 0:
            return {
                "success": False,
                "message": "Failed to remove training assignment"
            }
        
        # Log removal event
        audit_trail.log_event(
            event_type="TRAINING_REMOVED",
            user=user.uid,
            resource_uid=document_uid,
            resource_type="ControlledDocument",
            details={
                "assignment_uid": assignment_uid,
                "assigned_user_uid": user_uid,
                "assigned_user_name": user_name,
                "document_title": doc_title,
                "removed_by": user.name,
                "removal_date": datetime.now().isoformat()
            }
        )
        
        return {
            "success": True,
            "message": f"Training assignment removed for {user_name} - {doc_title}",
            "removed_assignment": {
                "user_name": user_name,
                "document_title": doc_title,
                "assignment_uid": assignment_uid
            }
        }
        
    except Exception as e:
        logger.error(f"Error removing training assignment {assignment_uid}: {e}")
        return {
            "success": False,
            "message": f"Failed to remove training assignment: {e}"
        }

Parameters

Name Type Default Kind
user DocUser - positional_or_keyword
assignment_uid str - positional_or_keyword

Parameter Details

user: DocUser object representing the administrator performing the removal operation. Must have MANAGE_TRAINING permission (enforced by decorator). Used for audit logging to track who removed the assignment.

assignment_uid: String in format 'user_uid-document_uid' where both UIDs are 36-character UUIDs (format: 8-4-4-4-12). This composite identifier uniquely identifies the training assignment relationship to be removed. Example: '550e8400-e29b-41d4-a716-446655440000-660e8400-e29b-41d4-a716-446655440001'

Return Value

Type: Dict[str, Any]

Returns a dictionary with operation status. On success: {'success': True, 'message': str, 'removed_assignment': {'user_name': str, 'document_title': str, 'assignment_uid': str}}. On failure: {'success': False, 'message': str} with error description. The 'message' field provides human-readable feedback, and 'removed_assignment' contains details about what was removed.

Dependencies

  • typing
  • datetime
  • logging
  • traceback
  • CDocs.config
  • CDocs.models.document
  • CDocs.models.user_extensions
  • CDocs.models.training
  • CDocs.utils
  • CDocs.db
  • CDocs.controllers

Required Imports

from typing import Dict, Any
from datetime import datetime
import logging
from CDocs.models.user_extensions import DocUser
from CDocs.utils import audit_trail
from CDocs.db import db_operations as db
from CDocs.controllers import require_permission, log_controller_action

Usage Example

from CDocs.models.user_extensions import DocUser
from your_module import remove_training_assignment

# Assuming admin_user is already authenticated and has MANAGE_TRAINING permission
admin_user = DocUser(uid='admin-uid-123', name='Admin User')

# Composite assignment UID format: user_uid-document_uid
assignment_uid = '550e8400-e29b-41d4-a716-446655440000-660e8400-e29b-41d4-a716-446655440001'

result = remove_training_assignment(
    user=admin_user,
    assignment_uid=assignment_uid
)

if result['success']:
    print(f"Successfully removed: {result['message']}")
    print(f"User: {result['removed_assignment']['user_name']}")
    print(f"Document: {result['removed_assignment']['document_title']}")
else:
    print(f"Error: {result['message']}")

Best Practices

  • Always check the 'success' field in the returned dictionary before processing results
  • The assignment_uid must be exactly in the format 'user_uid-document_uid' with both being valid 36-character UUIDs
  • Ensure the calling user has MANAGE_TRAINING permission before invoking (enforced by decorator)
  • The function performs audit logging automatically - no additional logging needed for compliance
  • Handle exceptions gracefully as the function catches all exceptions and returns error messages in the response dictionary
  • The function validates assignment existence before deletion to prevent silent failures
  • Use the returned 'removed_assignment' data for UI feedback or further processing
  • The function is idempotent-safe: attempting to remove a non-existent assignment returns a clear error message rather than throwing an exception

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function get_training_assignment 79.8% similar

    Retrieves a specific training assignment for a user from a Neo4j graph database, validating user authorization and parsing a composite UID format.

    From: /tf/active/vicechatdev/CDocs/controllers/training_controller.py
  • function complete_user_training_by_uid 74.6% similar

    Completes a user's training assignment for a controlled document by updating the training relationship status, recording completion date and score, and logging the event to the audit trail.

    From: /tf/active/vicechatdev/CDocs/controllers/training_controller.py
  • function get_document_training_assignments 72.2% similar

    Retrieves training assignments and configuration for a specific controlled document, including assigned users and training requirements.

    From: /tf/active/vicechatdev/CDocs/controllers/training_controller.py
  • function disable_document_training 69.3% similar

    Disables the training requirement for a specific controlled document, verifying user permissions and logging the action to the audit trail.

    From: /tf/active/vicechatdev/CDocs/controllers/training_controller.py
  • function assign_user_training 68.6% similar

    Assigns training requirements to multiple users for a specific controlled document, validating permissions, document training status, and user existence before creating assignments.

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