🔍 Code Extractor

function add_approval_comment_v1

Maturity: 75

Adds a comment to an approval cycle with optional location information, page references, and reply threading. Validates user permissions, logs audit trails, and sends notifications to other approvers for issue-type comments.

File:
/tf/active/vicechatdev/CDocs/controllers/approval_controller_bis.py
Lines:
419 - 540
Complexity:
moderate

Purpose

This function enables users to add comments to document approval cycles within a controlled document management system. It supports different comment types (GENERAL, ISSUE), threaded replies, page-specific annotations, and location-based comments. The function enforces permission checks to ensure only authorized approvers or users with MANAGE_APPROVALS permission can comment. It automatically creates audit trail entries and sends email notifications to other approvers when issues are raised, facilitating collaborative document review and approval workflows.

Source Code

def add_approval_comment(
    user: DocUser,
    approval_uid: str,
    comment_text: str,
    comment_type: str = "GENERAL",
    page_number: Optional[int] = None,
    location_info: Optional[Dict[str, Any]] = None,
    parent_comment_uid: Optional[str] = None
) -> Dict[str, Any]:
    """
    Add a comment to an approval cycle.
    
    Args:
        user: The user adding the comment
        approval_uid: UID of the approval cycle
        comment_text: Text of the comment
        comment_type: Type of comment
        page_number: Page number the comment applies to
        location_info: Location information for the comment
        parent_comment_uid: UID of parent comment if this is a reply
        
    Returns:
        Dictionary with success flag and comment information
    """
    try:
        # Get approval cycle
        approval_cycle = ApprovalCycle(uid=approval_uid)
        if not approval_cycle:
            raise ResourceNotFoundError("Approval cycle not found")
            
        # Verify user is an approver or has permissions
        is_approver = approval_cycle.is_approver(user.uid)
        has_permission = permissions.user_has_permission(user, "MANAGE_APPROVALS")
        
        if not (is_approver or has_permission):
            raise PermissionError("You do not have permission to comment on this approval")
            
        # Additional properties for the comment
        properties = {
            "comment_type": comment_type,
            "created_at": datetime.now()
        }
        
        if page_number is not None:
            properties["page_number"] = page_number
            
        if location_info:
            properties.update(location_info)
            
        if parent_comment_uid:
            properties["parent_comment_uid"] = parent_comment_uid
            
        # Add the comment
        comment = approval_cycle.add_comment(
            commenter=user,
            text=comment_text,
            requires_resolution=comment_type == "ISSUE",
            properties=properties
        )
        
        if not comment:
            raise BusinessRuleError("Failed to add comment")
            
        # 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='ApporvalCycle',
                event_type="APPROVAL_COMMENT_ADDED",
                details={
                    "approval_cycle_uid": approval_uid,
                    "comment_uid": comment.uid,
                    "comment_type": comment_type
                }
            )
            
        # Send notifications to other approvers if this is an issue comment
        if comment_type == "ISSUE":
            from CDocs.controllers.document_controller import get_document
            document_uid = approval_cycle.document_uid
            document = get_document(document_uid=document_uid) if document_uid else None
            
            for assignment in approval_cycle.get_approver_assignments():
                if assignment.approver_uid != user.uid:
                    approver = DocUser(uid=assignment.approver_uid)
                    if approver:
                        notifications.send_notification(
                            notification_type="APPROVAL_COMMENT_ADDED",
                            users=approver.uid,
                            resource_uid=approval_uid,
                            resource_type="ApprovalCycle",
                            message=f"{user.name} commented: {comment_text[:50]}{'...' if len(comment_text) > 50 else ''}",
                            details={
                                "document_uid": document_uid,
                                "document_number": document.get("docNumber") if document else None,
                                "document_title": document.get("title") if document else None,
                                "approval_cycle_uid": approval_uid,
                                "comment_uid": comment.uid,
                                "comment_type": comment_type
                            },
                            send_email=True,
                            email_template="approval_comment_added"
                        )
        
        return {
            "success": True,
            "message": "Comment added successfully",
            "comment_uid": comment.uid,
            "approval_uid": approval_uid
        }
        
    except (ResourceNotFoundError, PermissionError, BusinessRuleError) as e:
        logger.warning(f"Error adding approval comment: {e}")
        return {"success": False, "message": str(e)}
        
    except Exception as e:
        logger.error(f"Unexpected error adding approval comment: {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
comment_text str - positional_or_keyword
comment_type str 'GENERAL' positional_or_keyword
page_number Optional[int] None positional_or_keyword
location_info Optional[Dict[str, Any]] None positional_or_keyword
parent_comment_uid Optional[str] None positional_or_keyword

Parameter Details

user: DocUser object representing the authenticated user adding the comment. Must be either an approver on the cycle or have MANAGE_APPROVALS permission.

approval_uid: Unique identifier (string) of the approval cycle to which the comment will be added. Must reference an existing ApprovalCycle.

comment_text: The actual text content of the comment. Can be of any length, though notifications truncate to 50 characters for preview.

comment_type: Type classification of the comment. Defaults to 'GENERAL'. When set to 'ISSUE', the comment requires resolution and triggers notifications to all other approvers. Expected values: 'GENERAL', 'ISSUE', or other custom types.

page_number: Optional integer specifying which page of the document this comment applies to. Useful for page-specific annotations in multi-page documents.

location_info: Optional dictionary containing spatial or contextual location information for the comment (e.g., coordinates, highlighted text ranges, section references). Structure depends on client implementation.

parent_comment_uid: Optional string UID of another comment. When provided, creates a threaded reply relationship, allowing nested comment discussions.

Return Value

Type: Dict[str, Any]

Returns a dictionary with keys: 'success' (boolean indicating operation success), 'message' (string describing the result or error), 'comment_uid' (string UID of the newly created comment, only present on success), and 'approval_uid' (string UID of the approval cycle, only present on success). On failure, only 'success' (False) and 'message' (error description) are returned.

Dependencies

  • CDocs
  • typing
  • datetime
  • logging
  • traceback

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 log_controller_action, ResourceNotFoundError, PermissionError, BusinessRuleError
import logging
import traceback

Conditional/Optional Imports

These imports are only needed under specific conditions:

from CDocs.controllers.document_controller import get_document

Condition: only when comment_type is 'ISSUE' and notifications need to be sent with document details

Required (conditional)

Usage Example

from CDocs.models.user_extensions import DocUser
from CDocs.controllers.approval_controller import add_approval_comment

# Get the current user
user = DocUser(uid='user_123')

# Add a general comment
result = add_approval_comment(
    user=user,
    approval_uid='approval_456',
    comment_text='This section looks good to me.',
    comment_type='GENERAL',
    page_number=5
)

if result['success']:
    print(f"Comment added: {result['comment_uid']}")
else:
    print(f"Error: {result['message']}")

# Add an issue comment with location info
issue_result = add_approval_comment(
    user=user,
    approval_uid='approval_456',
    comment_text='This calculation appears incorrect.',
    comment_type='ISSUE',
    page_number=12,
    location_info={'x': 150, 'y': 300, 'width': 200, 'height': 50}
)

# Add a reply to an existing comment
reply_result = add_approval_comment(
    user=user,
    approval_uid='approval_456',
    comment_text='I agree, we should revise this.',
    parent_comment_uid='comment_789'
)

Best Practices

  • Always check the 'success' field in the returned dictionary before accessing 'comment_uid' or 'approval_uid'
  • Use comment_type='ISSUE' sparingly as it triggers email notifications to all approvers
  • Provide page_number and location_info when adding comments about specific document locations for better context
  • Handle PermissionError gracefully in the UI to inform users they lack necessary permissions
  • The function is decorated with @log_controller_action, so all invocations are automatically logged
  • When implementing threaded replies, ensure parent_comment_uid references a valid existing comment
  • Comment text in notifications is truncated to 50 characters, so ensure important information is at the beginning
  • The function catches and logs all exceptions, returning error messages instead of raising them, so check return values rather than using try-except blocks
  • For ISSUE type comments, ensure email infrastructure is properly configured as notifications will be sent synchronously

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function add_approval_comment 92.5% similar

    Adds a comment to an approval cycle for a controlled document, with support for threaded comments, different comment types, and automatic notifications to relevant stakeholders.

    From: /tf/active/vicechatdev/CDocs/controllers/approval_controller.py
  • function add_review_comment 80.3% similar

    Adds a comment to a document review cycle with support for threaded comments, different comment types, and location-based annotations.

    From: /tf/active/vicechatdev/CDocs/controllers/review_controller.py
  • function update_approval_comment_v1 79.3% similar

    Updates an existing approval comment in a document approval workflow, allowing modification of comment text and status (e.g., marking as resolved) with permission checks and audit logging.

    From: /tf/active/vicechatdev/CDocs/controllers/approval_controller_bis.py
  • function update_approval_comment 76.6% similar

    Updates an approval comment's text and/or status with permission checks, audit logging, and notifications for resolved comments.

    From: /tf/active/vicechatdev/CDocs/controllers/approval_controller.py
  • function add_approver_to_active_approval_v1 68.3% similar

    Adds a new approver to an active approval cycle with permission checks, validation, audit logging, and email notifications.

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