🔍 Code Extractor

function extend_review_deadline

Maturity: 68

Extends the deadline for a document review cycle, validating permissions and business rules, then notifying active reviewers of the change.

File:
/tf/active/vicechatdev/CDocs/controllers/review_controller.py
Lines:
1347 - 1468
Complexity:
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

  • logging
  • uuid
  • os
  • typing
  • datetime
  • traceback
  • CDocs

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

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function extend_approval_deadline 89.4% similar

    Extends the deadline for an active approval cycle, validating permissions and business rules, then notifying affected approvers.

    From: /tf/active/vicechatdev/CDocs/controllers/approval_controller.py
  • function extend_approval_deadline_v1 84.3% similar

    Extends the deadline of an active approval cycle, validates permissions, logs the change, and notifies pending approvers of the new due date.

    From: /tf/active/vicechatdev/CDocs/controllers/approval_controller_bis.py
  • function complete_review 66.9% similar

    Completes a document review cycle by submitting a reviewer's decision (APPROVED/REJECTED), updating review status, managing sequential review workflows, and triggering notifications.

    From: /tf/active/vicechatdev/CDocs/controllers/review_controller.py
  • function close_review_cycle 66.9% similar

    Closes a completed review cycle for a controlled document, with optional document status update, permission validation, and stakeholder notifications.

    From: /tf/active/vicechatdev/CDocs/controllers/review_controller.py
  • function cancel_review_cycle 64.7% similar

    Cancels an active review cycle for a controlled document, updating the review status, notifying reviewers, and reverting the document status if necessary.

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