function add_reviewer_to_active_review
Adds a reviewer to an active review cycle with optional sequence ordering and instructions, handling permissions, notifications, and audit logging.
/tf/active/vicechatdev/CDocs/controllers/review_controller.py
1471 - 1613
complex
Purpose
This function manages the addition of reviewers to document review cycles in a controlled document management system. It validates permissions, checks review cycle status, prevents duplicate reviewer assignments, optionally sets sequence order for sequential reviews, sends notifications to the new reviewer, updates document sharing permissions, and logs the action for audit purposes. It is designed to be used in document review workflows where multiple reviewers may need to be assigned to review document versions.
Source Code
def add_reviewer_to_active_review(
user: DocUser,
review_uid: str,
reviewer_uid: str,
sequence_order: Optional[int] = None,
instructions: Optional[str] = None # New parameter
) -> Dict[str, Any]:
"""
Add a reviewer to an active review cycle.
Args:
user: User adding the reviewer
review_uid: UID of review cycle
reviewer_uid: UID of user to add as reviewer
sequence_order: Optional sequence order for sequential reviews
Returns:
Dictionary with addition details
Raises:
ResourceNotFoundError: If review cycle not found
ValidationError: If validation fails
PermissionError: If user doesn't have permission
BusinessRuleError: If addition is not allowed
"""
try:
# Direct permission check at the beginning
logger.info(f"Checking if user {user.uid} has MANAGE_REVIEWS permission")
if not permissions.user_has_permission(user, "MANAGE_REVIEWS"):
logger.warning(f"Permission denied: User {user.uid} attempted to add reviewer without MANAGE_REVIEWS permission")
raise PermissionError("You do not have permission to add reviewers")
logger.info(f"User {user.uid} has permission to add reviewer to review cycle {review_uid}")
# Get review cycle instance
review_cycle = ReviewCycle(uid=review_uid)
if not review_cycle:
raise ResourceNotFoundError(f"Review cycle not found: {review_uid}")
# Check if review status allows adding reviewers
if review_cycle.status not in ["PENDING", "IN_PROGRESS"]:
raise BusinessRuleError(f"Cannot add reviewers to review with status {review_cycle.status}")
# Validate reviewer UID
reviewer = DocUser(uid=reviewer_uid)
if not reviewer or not reviewer.uid:
raise ValidationError(f"Invalid reviewer: {reviewer_uid}")
# Check if already a reviewer
if review_cycle.is_reviewer(reviewer_uid):
raise BusinessRuleError(f"User {reviewer_uid} is already a reviewer for this review cycle")
# Add reviewer using the model method - this creates the relationship and assignment
success = review_cycle.add_reviewer(reviewer)
if not success:
raise BusinessRuleError(f"Failed to add reviewer {reviewer_uid}")
# If sequence order provided (for sequential reviews), update it
assignment = review_cycle.get_reviewer_assignment(reviewer_uid)
if assignment:
if sequence_order is not None:
assignment.sequence_order = sequence_order
# Set reviewer-specific instructions if provided
if instructions is not None:
assignment.instructions = instructions
assignment.save()
# Log the reviewer addition
audit_trail.log_review_event(
event_type="REVIEW_UPDATED",
user=user,
review_uid=review_uid,
details={
"action": "reviewer_added",
"reviewer_uid": reviewer_uid,
"reviewer_name": reviewer.name,
"sequence_order": sequence_order
}
)
# Send notification to new reviewer
try:
# Get document info for the notification
document = None
document_version = review_cycle.document_version
if document_version:
document = document_version.document
notifications.send_notification(
notification_type="REVIEW_ASSIGNED",
users=[reviewer_uid],
resource_uid=review_uid,
resource_type="ReviewCycle",
message=f"You have been added as a reviewer",
details={
"review_uid": review_uid,
"document_uid": document.uid if document else None,
"doc_number": document.doc_number if document else "Unknown",
"title": document.title if document else "Unknown Document",
"due_date": review_cycle.due_date.isoformat() if review_cycle.due_date else None
},
send_email=True,
email_template="review_assigned",
email_data={
"app_url": settings.APP_URL,
"doc_uid": document.uid if document else None,
"review_uid": review_uid,
"due_date": review_cycle.due_date.isoformat() if review_cycle.due_date else None,
"instructions": instructions,
"assigned_by": user.name
}
)
except Exception as notif_err:
logger.error(f"Error sending reviewer notification: {notif_err}")
# Continue even if notification fails
# Update sharing permissions for document based on new review cycle
from CDocs.controllers.share_controller import manage_document_permissions
document = ControlledDocument(uid=document.uid)
permission_result = manage_document_permissions(document)
return {
"success": True,
"review_uid": review_uid,
"reviewer": {
"uid": reviewer.uid,
"name": reviewer.name,
"email": reviewer.email
},
"assignment": assignment.to_dict() if assignment else None,
"message": f"Reviewer {reviewer.name} added successfully"
}
except (ResourceNotFoundError, ValidationError, PermissionError, BusinessRuleError) as e:
# Re-raise known errors
raise
except Exception as e:
logger.error(f"Error adding reviewer to review cycle: {e}")
logger.error(traceback.format_exc())
raise BusinessRuleError(f"Failed to add reviewer: {e}")
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
user |
DocUser | - | positional_or_keyword |
review_uid |
str | - | positional_or_keyword |
reviewer_uid |
str | - | positional_or_keyword |
sequence_order |
Optional[int] | None | positional_or_keyword |
instructions |
Optional[str] | None | positional_or_keyword |
Parameter Details
user: DocUser object representing the user performing the action. Must have MANAGE_REVIEWS permission. Used for permission checks and audit logging.
review_uid: String UID (unique identifier) of the review cycle to which the reviewer will be added. Must correspond to an existing ReviewCycle with status 'PENDING' or 'IN_PROGRESS'.
reviewer_uid: String UID of the user to be added as a reviewer. Must correspond to a valid DocUser and cannot already be a reviewer on this review cycle.
sequence_order: Optional integer specifying the order in which this reviewer should review (for sequential review workflows). If None, no specific order is enforced. Used to set the sequence_order field on the ReviewerAssignment.
instructions: Optional string containing specific instructions for this reviewer. If provided, these instructions are stored in the ReviewerAssignment and included in the notification email sent to the reviewer.
Return Value
Type: Dict[str, Any]
Returns a dictionary with keys: 'success' (boolean, always True if no exception), 'review_uid' (string, the review cycle UID), 'reviewer' (dict with 'uid', 'name', 'email' of added reviewer), 'assignment' (dict representation of the ReviewerAssignment object or None), and 'message' (string confirmation message). If any error occurs, raises an exception instead of returning.
Dependencies
logginguuidostypingdatetimetracebackCDocsCDocs.configCDocs.models.documentCDocs.models.reviewCDocs.models.user_extensionsCDocs.utilsCDocs.controllersCDocs.controllers.document_controllerCDocs.controllers.share_controllerCDocs.db
Required Imports
import logging
import traceback
from typing import Dict, Any, Optional
from CDocs.config import settings, permissions
from CDocs.models.document import ControlledDocument
from CDocs.models.review import ReviewCycle
from CDocs.models.user_extensions import DocUser
from CDocs.utils import audit_trail, notifications
from CDocs.controllers import PermissionError, ResourceNotFoundError, ValidationError, BusinessRuleError
from CDocs.controllers.share_controller import manage_document_permissions
Conditional/Optional Imports
These imports are only needed under specific conditions:
from CDocs.controllers.share_controller import manage_document_permissions
Condition: imported within the function body for updating document permissions after reviewer addition
Required (conditional)Usage Example
from CDocs.models.user_extensions import DocUser
from CDocs.controllers.review_controller import add_reviewer_to_active_review
# Get the user performing the action
acting_user = DocUser(uid='user123')
# Add a reviewer to a review cycle
result = add_reviewer_to_active_review(
user=acting_user,
review_uid='review456',
reviewer_uid='reviewer789',
sequence_order=2,
instructions='Please focus on technical accuracy and compliance with standards'
)
print(f"Reviewer added: {result['reviewer']['name']}")
print(f"Assignment details: {result['assignment']}")
Best Practices
- Ensure the acting user has MANAGE_REVIEWS permission before calling this function
- Only call this function for review cycles with status 'PENDING' or 'IN_PROGRESS'
- Verify that the reviewer_uid corresponds to a valid user before calling
- Handle all four exception types: ResourceNotFoundError, ValidationError, PermissionError, and BusinessRuleError
- Be aware that notification failures are logged but do not cause the function to fail
- Use sequence_order parameter only for sequential review workflows where order matters
- Provide clear instructions parameter to help reviewers understand their specific responsibilities
- The function automatically updates document sharing permissions, so no additional permission management is needed
- All actions are logged to the audit trail automatically for compliance tracking
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function remove_reviewer_from_active_review 78.1% similar
-
function add_approver_to_active_approval 77.1% similar
-
function add_review_comment 74.3% similar
-
function complete_review 71.5% similar
-
function add_approver_to_active_approval_v1 70.5% similar