function add_approver_to_active_approval_v1
Adds a new approver to an active approval cycle with permission checks, validation, audit logging, and email notifications.
/tf/active/vicechatdev/CDocs/controllers/approval_controller_bis.py
1183 - 1291
complex
Purpose
This function manages the addition of approvers to ongoing document approval cycles. It validates permissions (either the initiator or users with MANAGE_APPROVALS permission), ensures the approval cycle is still active, verifies the new approver exists and isn't already assigned, adds them to the cycle with optional instructions and sequence order, logs the action in the audit trail, and sends email notifications to the newly assigned approver. It's designed for document management systems where approval workflows can be modified dynamically.
Source Code
def add_approver_to_active_approval(
user: DocUser,
approval_uid: str,
approver_uid: str,
instructions: Optional[str] = None,
sequence_order: Optional[int] = None
) -> Dict[str, Any]:
"""
Add a new approver to an active approval cycle.
Args:
user: The user adding the approver
approval_uid: UID of the approval cycle
approver_uid: UID of the user to add as approver
instructions: Instructions for the new approver
sequence_order: Sequence order for the new approver
Returns:
Dictionary with success flag and status
"""
try:
# Get approval cycle
approval_cycle = ApprovalCycle(uid=approval_uid)
if not approval_cycle:
raise ResourceNotFoundError("Approval cycle not found")
# Check if user has permission
is_initiator = approval_cycle._data.get('initiatedByUID') == user.uid
has_permission = permissions.user_has_permission(user, "MANAGE_APPROVALS")
if not (is_initiator or has_permission):
raise PermissionError("You do not have permission to add approvers")
# Check if approval is still active
if not approval_cycle.is_active:
raise BusinessRuleError(f"Cannot add approver to a {approval_cycle.status} approval cycle")
# Verify approver exists
approver = DocUser(uid=approver_uid)
if not approver or not approver.uid:
raise ValidationError(f"Invalid approver UID: {approver_uid}")
# Check if already an approver
if approval_cycle.is_approver(approver_uid):
raise BusinessRuleError(f"{approver.name} is already an approver for this document")
# Add approver
success = approval_cycle.add_approver(approver_uid, instructions=instructions)
if not success:
raise BusinessRuleError(f"Failed to add {approver.name} as approver")
# Update sequence order if provided and this is a sequential approval
assignment = approval_cycle.get_approver_assignment(approver_uid)
if assignment and sequence_order is not None and approval_cycle._data.get('sequential', False):
assignment.sequence_order = sequence_order
# Create audit trail entry
document_uid = approval_cycle.document_uid
if document_uid:
audit_trail.log_event(
user=user,
resource_uid=document_uid,
resource_type='ApprovalCycle',
event_type="APPROVER_ADDED",
details={
"approval_cycle_uid": approval_uid,
"approver_uid": approver_uid,
"approver_name": approver.name,
"sequence_order": sequence_order
}
)
# Send notification to new approver
from CDocs.controllers.document_controller import get_document
document = get_document(document_uid=document_uid)
if document:
notifications.send_notification(
notification_type="APPROVAL_ASSIGNED",
users=approver.uid,
resource_uid=approval_uid,
resource_type="ApprovalCycle",
message=f"You have been assigned to approve {document.get('title')}",
details={
"document_uid": document_uid,
"document_number": document.get("docNumber"),
"document_title": document.get("title"),
"approval_cycle_uid": approval_uid,
"due_date": approval_cycle.due_date.isoformat() if approval_cycle.due_date else None
},
send_email=True,
email_template="approval_assigned"
)
return {
"success": True,
"message": f"{approver.name} added as approver",
"approver_uid": approver_uid
}
except (ResourceNotFoundError, PermissionError, BusinessRuleError, ValidationError) as e:
logger.warning(f"Error adding approver: {e}")
return {"success": False, "message": str(e)}
except Exception as e:
logger.error(f"Unexpected error adding approver: {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 |
approval_uid |
str | - | positional_or_keyword |
approver_uid |
str | - | positional_or_keyword |
instructions |
Optional[str] | None | positional_or_keyword |
sequence_order |
Optional[int] | None | positional_or_keyword |
Parameter Details
user: DocUser object representing the authenticated user attempting to add the approver. Must have either initiated the approval cycle or possess MANAGE_APPROVALS permission.
approval_uid: String unique identifier (UID) of the approval cycle to which the approver will be added. Must reference an existing, active approval cycle.
approver_uid: String unique identifier (UID) of the user to be added as an approver. Must reference a valid DocUser who is not already an approver on this cycle.
instructions: Optional string containing specific instructions or guidance for the new approver about what to review or consider during approval. Defaults to None.
sequence_order: Optional integer specifying the position of this approver in sequential approval workflows. Only relevant if the approval cycle is configured as sequential. Defaults to None.
Return Value
Type: Dict[str, Any]
Returns a dictionary with keys: 'success' (boolean indicating operation success), 'message' (string describing the outcome or error), and 'approver_uid' (string UID of the added approver, only present on success). On failure, only 'success' and 'message' are returned.
Dependencies
CDocstypingdatetimeloggingtraceback
Required Imports
from typing import Dict, Any, Optional
from CDocs.models.user_extensions import DocUser
from CDocs.models.approval import ApprovalCycle
from CDocs.config import permissions
from CDocs.utils import audit_trail, notifications
from CDocs.controllers import log_controller_action, ResourceNotFoundError, PermissionError, BusinessRuleError, ValidationError
import logging
Conditional/Optional Imports
These imports are only needed under specific conditions:
from CDocs.controllers.document_controller import get_document
Condition: imported inside the function when document details are needed for notification purposes after successfully adding an approver
Required (conditional)import traceback
Condition: imported inside exception handler for detailed error logging when unexpected exceptions occur
Required (conditional)Usage Example
from CDocs.models.user_extensions import DocUser
from your_module import add_approver_to_active_approval
# Get the current user and approver
current_user = DocUser(uid='user123')
new_approver_uid = 'approver456'
# Add approver to an active approval cycle
result = add_approver_to_active_approval(
user=current_user,
approval_uid='approval789',
approver_uid=new_approver_uid,
instructions='Please review the technical specifications in section 3',
sequence_order=2
)
if result['success']:
print(f"Successfully added approver: {result['message']}")
print(f"Approver UID: {result['approver_uid']}")
else:
print(f"Failed to add approver: {result['message']}")
Best Practices
- Always check the returned 'success' flag before proceeding with dependent operations
- Ensure the user object passed has been properly authenticated before calling this function
- The function handles its own exception catching and returns structured error messages rather than raising exceptions
- For sequential approvals, provide sequence_order to maintain proper approval flow
- The function automatically sends email notifications; ensure email service is properly configured
- Audit trail entries are created automatically for compliance tracking
- The decorator log_controller_action should be present on the function for proper action logging
- This function modifies active approval cycles; ensure proper transaction handling in the calling context
- The function validates that the approval cycle is active before allowing modifications
- Permission checks are performed for both initiators and users with MANAGE_APPROVALS permission
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function add_approver_to_active_approval 92.1% similar
-
function remove_approver_from_active_approval_v1 79.3% similar
-
function create_approval_cycle 77.7% similar
-
function remove_approver_from_active_approval 75.5% similar
-
function complete_approval_v1 74.3% similar