function extend_approval_deadline_v1
Extends the deadline of an active approval cycle, validates permissions, logs the change, and notifies pending approvers of the new due date.
/tf/active/vicechatdev/CDocs/controllers/approval_controller_bis.py
1073 - 1180
complex
Purpose
This function allows authorized users (approval initiators or users with MANAGE_APPROVALS permission) to extend the deadline of an active approval cycle. It validates the new due date, updates the approval cycle, creates an audit trail entry, adds a comment explaining the extension, and sends email notifications to all pending approvers informing them of the deadline change.
Source Code
def extend_approval_deadline(
user: DocUser,
approval_uid: str,
new_due_date: datetime,
reason: Optional[str] = None
) -> Dict[str, Any]:
"""
Extend the deadline of an approval cycle.
Args:
user: The user extending the deadline
approval_uid: UID of the approval cycle
new_due_date: New due date for the approval
reason: Reason for extension
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 to extend deadline
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 extend the approval deadline")
# Check if approval is still active
if not approval_cycle.is_active:
raise BusinessRuleError(f"Cannot extend deadline of a completed approval cycle")
# Validate new due date
if new_due_date <= datetime.now():
raise ValidationError("New due date must be in the future")
# Set new due date
old_due_date = approval_cycle.due_date
approval_cycle.due_date = new_due_date
# Add comment with extension reason
if reason:
approval_cycle.add_comment(
commenter=user,
text=f"Deadline extended from {old_due_date.strftime('%Y-%m-%d')} to {new_due_date.strftime('%Y-%m-%d')}: {reason}",
properties={"comment_type": "DEADLINE_EXTENSION"}
)
# 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="APPROVAL_DEADLINE_EXTENDED",
details={
"approval_cycle_uid": approval_uid,
"old_due_date": old_due_date.isoformat() if old_due_date else None,
"new_due_date": new_due_date.isoformat(),
"reason": reason
}
)
# Send notifications to approvers
from CDocs.controllers.document_controller import get_document
document = get_document(document_uid=document_uid)
if document:
for assignment in approval_cycle.get_approver_assignments():
if assignment.status == 'PENDING':
approver = DocUser(uid=assignment.approver_uid)
if approver:
notifications.send_notification(
notification_type="APPROVAL_DEADLINE_EXTENDED",
users=approver.uid,
resource_uid=approval_uid,
resource_type="ApprovalCycle",
message=f"The approval deadline for {document.get('docNumber')} has been extended to {new_due_date.strftime('%Y-%m-%d')}",
details={
"document_uid": document_uid,
"document_number": document.get("docNumber"),
"document_title": document.get("title"),
"extended_by": user.name,
"approval_cycle_uid": approval_uid,
"new_due_date": new_due_date.isoformat()
},
send_email=True,
email_template="approval_deadline_extended"
)
return {
"success": True,
"message": "Approval deadline extended",
"new_due_date": new_due_date
}
except (ResourceNotFoundError, PermissionError, BusinessRuleError, ValidationError) as e:
logger.warning(f"Error extending approval deadline: {e}")
return {"success": False, "message": str(e)}
except Exception as e:
logger.error(f"Unexpected error extending approval deadline: {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 |
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 be either the approval cycle initiator or have MANAGE_APPROVALS permission.
approval_uid: String containing the unique identifier (UID) of the approval cycle whose deadline needs to be extended. Must correspond to an existing approval cycle.
new_due_date: datetime object representing the new deadline for the approval cycle. Must be a future date (after the current time).
reason: Optional string providing the justification for extending the deadline. If provided, it will be added as a comment to the approval cycle and included in notifications.
Return Value
Type: Dict[str, Any]
Returns a dictionary with keys: 'success' (boolean indicating if the operation succeeded), 'message' (string describing the outcome or error), and 'new_due_date' (datetime object of the new deadline, only present on success). On failure, only 'success' and 'message' are returned.
Dependencies
CDocstypingdatetimeloggingtraceback
Required Imports
from typing import Dict, Any, Optional
from datetime import datetime
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 ResourceNotFoundError, PermissionError, BusinessRuleError, ValidationError, log_controller_action
import logging
import traceback
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_uid exists to retrieve document details for notifications
Required (conditional)Usage Example
from datetime import datetime, timedelta
from CDocs.models.user_extensions import DocUser
from your_module import extend_approval_deadline
# Get the user extending the deadline
user = DocUser(uid='user123')
# Define the approval cycle UID and new deadline
approval_uid = 'approval_cycle_456'
new_due_date = datetime.now() + timedelta(days=7)
reason = 'Additional time needed for technical review'
# Extend the approval deadline
result = extend_approval_deadline(
user=user,
approval_uid=approval_uid,
new_due_date=new_due_date,
reason=reason
)
if result['success']:
print(f"Deadline extended to: {result['new_due_date']}")
else:
print(f"Error: {result['message']}")
Best Practices
- Always provide a reason parameter when extending deadlines to maintain clear audit trails
- Ensure the new_due_date is a timezone-aware datetime object if your system uses timezones
- Handle the returned dictionary properly, checking the 'success' flag before accessing 'new_due_date'
- The function is decorated with @log_controller_action('extend_approval_deadline'), so ensure this decorator is applied when using the function
- This function sends email notifications to all pending approvers, so ensure email configuration is properly set up
- The function catches and logs exceptions gracefully, returning error messages instead of raising exceptions
- Only users who initiated the approval or have MANAGE_APPROVALS permission can extend deadlines
- The new due date must be in the future; past dates will be rejected with a ValidationError
- Deadline extensions can only be applied to active approval cycles; completed cycles cannot be modified
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function extend_approval_deadline 94.4% similar
-
function extend_review_deadline 84.3% similar
-
function add_approver_to_active_approval_v1 69.5% similar
-
function add_approver_to_active_approval 64.4% similar
-
function close_approval_cycle_v1 64.2% similar