function extend_review_deadline
Extends the deadline for a document review cycle, validating permissions and business rules, then notifying active reviewers of the change.
/tf/active/vicechatdev/CDocs/controllers/review_controller.py
1347 - 1468
moderate
Purpose
This function manages the extension of review cycle deadlines in a document management system. It enforces permission checks (MANAGE_REVIEWS permission or document ownership), validates that the new deadline is valid (future date, later than current deadline), ensures the review is in an extendable state (PENDING or IN_PROGRESS), logs the change to an audit trail, and notifies all active reviewers via email about the deadline extension. This is critical for maintaining compliance and transparency in document review workflows.
Source Code
def extend_review_deadline(
user: DocUser,
review_uid: str,
new_due_date: datetime,
reason: Optional[str] = None
) -> Dict[str, Any]:
"""
Extend the deadline for a review cycle.
Args:
user: User extending the deadline
review_uid: UID of review cycle
new_due_date: New due date
reason: Optional reason for extension
Returns:
Dictionary with extension details
Raises:
ResourceNotFoundError: If review cycle not found
ValidationError: If validation fails
PermissionError: If user doesn't have permission
BusinessRuleError: If extension 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 manage reviews without MANAGE_REVIEWS permission")
raise PermissionError("You do not have permission to manage reviews")
logger.info(f"User {user.uid} has permission to manage reviews {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 is still active
if review_cycle.status not in ["PENDING", "IN_PROGRESS"]:
raise BusinessRuleError(f"Cannot extend deadline for review with status {review_cycle.status}")
# Validate new due date
if new_due_date <= datetime.now():
raise ValidationError("New due date must be in the future")
if review_cycle.due_date and new_due_date <= review_cycle.due_date:
raise ValidationError("New due date must be later than current due date")
# Check if user has permission
if not permissions.user_has_permission(user, "MANAGE_REVIEWS"):
# Check if user is the document owner or review initiator
document = ControlledDocument(uid=review_cycle.document_uid)
if not (document and document.owner_uid == user.uid) and review_cycle.initiated_by_uid != user.uid:
raise PermissionError("User is not authorized to extend this review deadline")
# Store old due date for audit
old_due_date = review_cycle.due_date
# Update review cycle
review_cycle.due_date = new_due_date
review_cycle.save()
# Log extension event
audit_trail.log_review_event(
event_type="REVIEW_DEADLINE_EXTENDED",
user=user,
review_uid=review_uid,
details={
"old_due_date": old_due_date.isoformat() if old_due_date else None,
"new_due_date": new_due_date.isoformat(),
"reason": reason
}
)
# Notify active reviewers
assignments = review_cycle.get_reviewer_assignments()
active_reviewer_uids = [a.reviewer_uid for a in assignments if a.status in ["PENDING", "ACTIVE"]]
if active_reviewer_uids:
document = ControlledDocument(uid=review_cycle.document_uid)
notifications.send_notification(
notification_type="REVIEW_DEADLINE_EXTENDED",
users=active_reviewer_uids,
resource_uid=review_cycle.uid,
resource_type="ReviewCycle",
message=f"Review deadline for {document.doc_number if document else 'document'} has been extended",
details={
"review_uid": review_uid,
"document_uid": document.uid if document else None,
"doc_number": document.doc_number if document else None,
"title": document.title if document else None,
"new_due_date": new_due_date.isoformat(),
"reason": reason
},
send_email=True,
email_template="review_deadline_extended",
email_data={
"app_url": settings.APP_URL,
"doc_uid": document.uid if document else None,
"review_uid": review_uid,
"old_due_date": old_due_date.isoformat() if old_due_date else None,
"new_due_date": new_due_date.isoformat(),
"reason": reason,
"extended_by": user.name
}
)
return {
"success": True,
"review_uid": review_uid,
"old_due_date": old_due_date,
"new_due_date": new_due_date,
"reason": reason,
"message": "Review deadline extended successfully"
}
except (ResourceNotFoundError, ValidationError, PermissionError, BusinessRuleError) as e:
# Re-raise known errors
raise
except Exception as e:
logger.error(f"Error extending review deadline: {e}")
raise BusinessRuleError(f"Failed to extend review deadline: {e}")
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
user |
DocUser | - | positional_or_keyword |
review_uid |
str | - | positional_or_keyword |
new_due_date |
datetime | - | positional_or_keyword |
reason |
Optional[str] | None | positional_or_keyword |
Parameter Details
user: DocUser object representing the user requesting the deadline extension. Must have MANAGE_REVIEWS permission, be the document owner, or be the review initiator to perform this action.
review_uid: String containing the unique identifier (UID) of the review cycle whose deadline needs to be extended. Must correspond to an existing ReviewCycle in the system.
new_due_date: datetime object representing the new deadline for the review cycle. Must be in the future and later than the current due_date. This will replace the existing due_date on the ReviewCycle.
reason: Optional string providing justification for the deadline extension. This is logged in the audit trail and included in notifications to reviewers. Can be None if no reason is provided.
Return Value
Type: Dict[str, Any]
Returns a dictionary with keys: 'success' (bool, always True on successful execution), 'review_uid' (str, the UID of the review cycle), 'old_due_date' (datetime or None, the previous deadline), 'new_due_date' (datetime, the new deadline), 'reason' (str or None, the provided reason), and 'message' (str, success confirmation message). On error, raises one of the documented exceptions instead of returning.
Dependencies
logginguuidostypingdatetimetracebackCDocs
Required Imports
from datetime import datetime
from typing import Dict, Any, Optional
from CDocs.models.user_extensions import DocUser
from CDocs.models.review import ReviewCycle, ReviewerAssignment
from CDocs.models.document import ControlledDocument
from CDocs.config import permissions
from CDocs.utils import audit_trail, notifications
from CDocs.controllers import ResourceNotFoundError, ValidationError, PermissionError, BusinessRuleError
import logging
Usage Example
from datetime import datetime, timedelta
from CDocs.models.user_extensions import DocUser
from CDocs.controllers.review_controller import extend_review_deadline
# Assume user and review_uid are already obtained
user = DocUser(uid='user123')
review_uid = 'review456'
new_deadline = datetime.now() + timedelta(days=7)
reason = 'Additional time needed for technical review'
try:
result = extend_review_deadline(
user=user,
review_uid=review_uid,
new_due_date=new_deadline,
reason=reason
)
print(f"Deadline extended successfully: {result['message']}")
print(f"Old deadline: {result['old_due_date']}")
print(f"New deadline: {result['new_due_date']}")
except PermissionError as e:
print(f"Permission denied: {e}")
except ValidationError as e:
print(f"Invalid input: {e}")
except ResourceNotFoundError as e:
print(f"Review not found: {e}")
except BusinessRuleError as e:
print(f"Business rule violation: {e}")
Best Practices
- Always provide a reason parameter when extending deadlines for audit trail completeness and transparency
- Ensure the user object has been properly authenticated before calling this function
- Handle all four exception types (ResourceNotFoundError, ValidationError, PermissionError, BusinessRuleError) in calling code
- The new_due_date must be timezone-aware if the system uses timezone-aware datetimes
- This function has a duplicate permission check at the beginning and later in the code - the first check will catch most permission issues early
- The function sends email notifications automatically, so ensure email configuration is properly set up before use
- Review cycles must be in PENDING or IN_PROGRESS status to be extendable - completed or cancelled reviews cannot be extended
- The function is decorated with log_controller_action, so all calls are automatically logged for audit purposes
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function extend_approval_deadline 89.4% similar
-
function extend_approval_deadline_v1 84.3% similar
-
function complete_review 66.9% similar
-
function close_review_cycle 66.9% similar
-
function cancel_review_cycle 64.7% similar