function update_review_comment
Updates an existing review comment's text and/or status with permission checks, audit logging, and notifications for resolved comments.
/tf/active/vicechatdev/CDocs/controllers/review_controller.py
658 - 824
complex
Purpose
This function manages the lifecycle of review comments in a document review system. It allows authorized users to modify comment text (author only) or change comment status (author, document owner, or admin). When a comment is marked as resolved, it records resolution metadata and sends notifications to relevant parties. The function enforces business rules such as preventing updates to comments in completed reviews and maintaining audit trails for compliance.
Source Code
def update_review_comment(
user: DocUser,
comment_uid: str,
comment_text: Optional[str] = None,
status: Optional[str] = None
) -> Dict[str, Any]:
"""
Update a review comment.
Args:
user: User updating the comment
comment_uid: UID of comment to update
comment_text: Optional new comment text
status: Optional new status (OPEN, RESOLVED, etc.)
Returns:
Dictionary with updated comment details
Raises:
ResourceNotFoundError: If comment not found
ValidationError: If validation fails
PermissionError: If user doesn't have permission
BusinessRuleError: If a business rule is violated
"""
try:
# Direct permission check at the beginning
logger.info(f"Checking if user {user.uid} has EDIT_REVIEW_COMMENT permission")
if not permissions.user_has_permission(user, ["EDIT_REVIEW_COMMENT"]):
logger.warning(f"Permission denied: User {user.uid} attempted to edit a comment without EDIT_REVIEW_COMMENT permission")
raise PermissionError("You do not have permission to edit comments")
logger.info(f"User {user.uid} has permission to create and initiate review cycle")
# Get comment instance
comment = ReviewComment(uid=comment_uid)
if not comment:
raise ResourceNotFoundError(f"Comment not found: {comment_uid}")
# Get review cycle
review_cycle = ReviewCycle(uid=comment.review_cycle_uid)
if not review_cycle:
raise ResourceNotFoundError(f"Review cycle not found for comment: {comment_uid}")
# Check if review is still active
if review_cycle.status not in ["PENDING", "IN_PROGRESS"]:
raise BusinessRuleError(f"Cannot update comments for review with status {review_cycle.status}")
# Check if user can edit this comment
can_edit = False
# User can edit their own comments
if comment.user_uid == user.uid:
can_edit = True
# Document owner can change status (but not text)
elif review_cycle.document_uid:
document = ControlledDocument(uid=review_cycle.document_uid)
if document and document.owner_uid == user.uid and comment_text is None:
can_edit = True
# Admins can edit any comment
elif permissions.user_has_permission(user, "MANAGE_REVIEWS"):
can_edit = True
if not can_edit:
raise PermissionError("User is not authorized to update this comment")
# Track changes
changes = {}
# Update comment text if provided
if comment_text is not None and comment_text != comment.comment_text:
# Only the author can change the text
if comment.user_uid != user.uid and not permissions.user_has_permission(user, "MANAGE_REVIEWS"):
raise PermissionError("Only the comment author can modify comment text")
old_text = comment.comment_text
comment.comment_text = comment_text
changes["comment_text"] = {"old": old_text, "new": comment_text}
# Update status if provided
if status is not None and status != comment.status:
# Validate status
if status not in settings.REVIEW_COMMENT_STATUSES:
raise ValidationError(f"Invalid comment status: {status}")
old_status = comment.status
comment.status = status
# Add resolution info if being resolved
if status == "RESOLVED" and old_status != "RESOLVED":
comment.resolved_by_uid = user.uid
comment.resolved_by_name = user.name
comment.resolved_date = datetime.now()
changes["status"] = {"old": old_status, "new": status}
# No changes
if not changes:
return {
"success": True,
"comment": comment.to_dict(),
"message": "No changes made to comment"
}
# Update modified timestamp
comment.modified_date = datetime.now()
# Save comment to database
comment.save()
# Log comment update event
audit_trail.log_review_event(
event_type="REVIEW_COMMENT_UPDATED",
user=user,
review_uid=review_cycle.uid,
details={
"comment_uid": comment.uid,
"changes": changes
}
)
# Send notifications if status changed
if "status" in changes and changes["status"]["new"] == "RESOLVED":
# Notify original comment author if different from resolver
if comment.user_uid != user.uid:
document = ControlledDocument(uid=review_cycle.document_uid)
notifications.send_notification(
notification_type="REVIEW_COMMENT_RESOLVED",
users=[comment.user_uid],
resource_uid=review_cycle.uid,
resource_type="ReviewCycle",
message=f"Your comment on {document.doc_number if document else 'document'} has been resolved",
details={
"doc_uid": document.uid, # Add doc_uid for URL generation
"doc_number": document.doc_number,
"title": document.title,
"review_uid": review_cycle.uid,
"comment_uid": comment.uid,
"comment_text": comment_text[:100] + "..." if len(comment_text) > 100 else comment_text,
"commenter_name": user.name,
"department": document.department,
"doc_type": document.doc_type,
"version_number": document.current_version.version_number if document.current_version else "N/A"
},
send_email=True,
email_template="review_comment_resolved",
email_data={
"app_url": settings.APP_URL,
"doc_uid": document.uid,
"review_uid": review_cycle.uid,
"comment_uid": comment.uid
}
)
return {
"success": True,
"comment": comment.to_dict(),
"changes": changes,
"message": "Comment updated successfully"
}
except (ResourceNotFoundError, ValidationError, PermissionError, BusinessRuleError) as e:
# Re-raise known errors
raise
except Exception as e:
logger.error(f"Error updating review comment: {e}")
raise BusinessRuleError(f"Failed to update review comment: {e}")
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
user |
DocUser | - | positional_or_keyword |
comment_uid |
str | - | positional_or_keyword |
comment_text |
Optional[str] | None | positional_or_keyword |
status |
Optional[str] | None | positional_or_keyword |
Parameter Details
user: DocUser object representing the authenticated user attempting to update the comment. Used for permission checks and audit logging. Must have EDIT_REVIEW_COMMENT permission at minimum.
comment_uid: Unique identifier (string) of the ReviewComment to be updated. Must correspond to an existing comment in the database or ResourceNotFoundError will be raised.
comment_text: Optional string containing new text for the comment. Only the original comment author or users with MANAGE_REVIEWS permission can modify this. Pass None to leave text unchanged.
status: Optional string representing the new status for the comment. Must be one of the values defined in settings.REVIEW_COMMENT_STATUSES (e.g., 'OPEN', 'RESOLVED'). Pass None to leave status unchanged. When set to 'RESOLVED', automatically records resolution metadata.
Return Value
Type: Dict[str, Any]
Returns a dictionary with keys: 'success' (boolean, always True on successful execution), 'comment' (dictionary representation of the updated ReviewComment object), 'changes' (dictionary mapping changed fields to their old and new values, e.g., {'status': {'old': 'OPEN', 'new': 'RESOLVED'}}), and 'message' (string describing the outcome). If no changes were made, the changes dict will be empty and message will indicate no modifications.
Dependencies
logginguuidostypingdatetimetracebackCDocs.dbCDocs.config.settingsCDocs.config.permissionsCDocs.models.documentCDocs.models.reviewCDocs.models.user_extensionsCDocs.utils.audit_trailCDocs.utils.notificationsCDocs.controllers
Required Imports
from typing import Dict, Any, Optional
from datetime import datetime
from CDocs.models.user_extensions import DocUser
from CDocs.models.review import ReviewComment, ReviewCycle
from CDocs.models.document import ControlledDocument
from CDocs.config import settings, permissions
from CDocs.utils import audit_trail, notifications
from CDocs.controllers import ResourceNotFoundError, ValidationError, PermissionError, BusinessRuleError, log_controller_action
import logging
Usage Example
from CDocs.models.user_extensions import DocUser
from CDocs.controllers.review_controller import update_review_comment
# Get the authenticated user
user = DocUser(uid='user123')
# Update comment text (only author can do this)
try:
result = update_review_comment(
user=user,
comment_uid='comment-abc-123',
comment_text='Updated comment with additional details',
status=None
)
print(f"Comment updated: {result['message']}")
print(f"Changes made: {result['changes']}")
except PermissionError as e:
print(f"Permission denied: {e}")
except ResourceNotFoundError as e:
print(f"Comment not found: {e}")
# Resolve a comment (document owner or author can do this)
try:
result = update_review_comment(
user=user,
comment_uid='comment-abc-123',
comment_text=None,
status='RESOLVED'
)
print(f"Comment resolved by {result['comment']['resolved_by_name']}")
except BusinessRuleError as e:
print(f"Cannot resolve: {e}")
Best Practices
- Always wrap calls in try-except blocks to handle ResourceNotFoundError, PermissionError, ValidationError, and BusinessRuleError exceptions
- Only the original comment author can modify comment text; document owners can only change status
- Comments can only be updated when the review cycle status is PENDING or IN_PROGRESS
- When resolving comments, the function automatically records resolver information and timestamp
- Pass None for parameters you don't want to change rather than fetching and re-passing existing values
- The function sends email notifications when comments are resolved, ensure notification system is properly configured
- All changes are logged to the audit trail for compliance and tracking purposes
- Users must have EDIT_REVIEW_COMMENT permission at minimum; MANAGE_REVIEWS permission grants full edit access
- The function uses the @log_controller_action decorator for automatic action logging
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function update_approval_comment 91.3% similar
-
function update_approval_comment_v1 84.6% similar
-
function add_review_comment 80.7% similar
-
function add_approval_comment 71.1% similar
-
function close_review_cycle 69.9% similar