🔍 Code Extractor

class ReviewComment

Maturity: 53

A model class representing a comment made during document review, with support for resolution tracking and database persistence.

File:
/tf/active/vicechatdev/CDocs/models/review.py
Lines:
22 - 216
Complexity:
moderate

Purpose

ReviewComment manages review comments in a document management system. It handles creation, storage, and retrieval of comments made during review cycles, including tracking whether comments require resolution, storing resolution text and dates, and maintaining relationships with review cycles and commenters. The class provides database persistence through Neo4j and integrates with the DocUser model for commenter information.

Source Code

class ReviewComment(BaseModel):
    """Model representing a comment made during document review."""
    
    def __init__(self, data: Optional[Dict[str, Any]] = None, uid: Optional[str] = None):
        """
        Initialize a review comment.
        
        Args:
            data: Dictionary of comment properties
            uid: Comment UID to load from database (if data not provided)
        """
        if data is None and uid is not None:
            # Fetch comment data from database
            data = db.get_node_by_uid(uid)
            
        super().__init__(data or {})
    
    @classmethod
    def create(cls, review_cycle_uid: str, 
              commenter: Union[DocUser, str], 
              text: str,
              requires_resolution: bool = False,
              properties: Optional[Dict[str, Any]] = None) -> Optional['ReviewComment']:
        """
        Create a new review comment.
        
        Args:
            review_cycle_uid: UID of the review cycle this comment belongs to
            commenter: User making the comment or their UID
            text: Comment text
            requires_resolution: Whether this comment requires resolution
            properties: Additional properties for the comment
            
        Returns:
            New ReviewComment instance or None if creation failed
        """
        try:
            # Prepare properties
            props = properties or {}
            props.update({
                'text': text,
                'timestamp': datetime.now(),
                'requiresResolution': requires_resolution,
                'commenterUID': commenter.uid if isinstance(commenter, DocUser) else commenter
            })
            
            # Create the comment node first
            comment_uid = str(uuid.uuid4())
            props['UID'] = comment_uid
            
            # Create node in database
            success = db.create_node(NodeLabels.REVIEW_COMMENT, props)
            
            if not success:
                logger.error(f"Failed to create review comment for review cycle {review_cycle_uid}")
                return None
            
            # Create relationship: Comment -> COMMENTED_ON -> Review Cycle
            rel_success = db.create_relationship(
                comment_uid, 
                review_cycle_uid,
                RelTypes.COMMENTED_ON
            )
            
            if not rel_success:
                logger.error(f"Failed to create relationship between comment {comment_uid} and review cycle {review_cycle_uid}")
                # Clean up the orphaned comment node
                db.delete_node(comment_uid)
                return None
                
            # Create the comment instance
            comment = cls(props)
            
            return comment
            
        except Exception as e:
            logger.error(f"Error creating review comment: {e}")
            return None

    def save(self) -> bool:
        """Save changes to database."""
        try:
            # If node doesn't exist, create it
            if not db.node_exists(self.uid):
                created = db.create_node_with_uid(
                    NodeLabels.REVIEW_COMMENT,
                    self._data,
                    self.uid
                )
                
                if created and self._data.get('review_cycle_uid'):
                    # Create relationship between comment and review cycle
                    db.create_relationship(
                        self.uid,
                        self._data['review_cycle_uid'],
                        RelTypes.COMMENTED_ON
                    )
                return created
            
            # Otherwise update existing node
            return db.update_node(self.uid, self._data)
        except Exception as e:
            logger.error(f"Error saving review comment: {e}")
            return False
    
    @property
    def text(self) -> str:
        """Get comment text."""
        return self._data.get('text', '')
    
    @property
    def timestamp(self) -> Optional[datetime]:
        """Get when comment was made."""
        return self._data.get('timestamp')
    
    @property
    def requires_resolution(self) -> bool:
        """Whether comment requires resolution."""
        return self._data.get('requiresResolution', False)
    
    @property
    def resolution(self) -> Optional[str]:
        """Get resolution text."""
        return self._data.get('resolution')
    
    @resolution.setter
    def resolution(self, text: str) -> None:
        """Set resolution text."""
        self._data['resolution'] = text
        self._data['resolutionDate'] = datetime.now()
        db.update_node(self.uid, {
            'resolution': text,
            'resolutionDate': self._data['resolutionDate']
        })
    
    @property
    def resolution_date(self) -> Optional[datetime]:
        """Get when comment was resolved."""
        return self._data.get('resolutionDate')
    
    @property
    def is_resolved(self) -> bool:
        """Whether comment has been resolved."""
        return self.resolution is not None
    
    @property
    def commenter_uid(self) -> Optional[str]:
        """Get UID of user who made the comment."""
        return self._data.get('commenterUID')
    
    @property
    def commenter(self) -> Optional[DocUser]:
        """Get user who made the comment."""
        commenter_uid = self.commenter_uid
        if commenter_uid:
            return DocUser(uid=commenter_uid)
        return None
    
    @property
    def review_cycle_uid(self) -> Optional[str]:
        """Get the UID of the review cycle this comment belongs to."""
        # First check if we already have it in properties
        if self._data.get('review_cycle_uid'):
            return self._data.get('review_cycle_uid')
        
        # Otherwise query the database
        result = db.run_query(
            """
            MATCH (c:ReviewComment {UID: $uid})-[:COMMENTED_ON]->(r:ReviewCycle)
            RETURN r.UID as review_uid
            """,
            {"uid": self.uid}
        )
        
        if result and 'review_uid' in result[0]:
            # Cache it for future use
            self._data['review_cycle_uid'] = result[0]['review_uid']
            return result[0]['review_uid']
            
        return None
    
    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary representation."""
        result = super().to_dict()
        
        # Add commenter information if available
        commenter = self.commenter
        if commenter:
            result['commenter'] = {
                'UID': commenter.uid,
                'name': commenter.name,
                'email': commenter.email
            }
            
        return result

Parameters

Name Type Default Kind
bases BaseModel -

Parameter Details

data: Optional dictionary containing comment properties (text, timestamp, requiresResolution, commenterUID, etc.). If provided, initializes the comment with these properties. If None and uid is provided, data will be fetched from database.

uid: Optional unique identifier string for the comment. If provided without data, the comment will be loaded from the database using this UID.

Return Value

The __init__ method returns a ReviewComment instance. The create() class method returns a new ReviewComment instance if successful, or None if creation failed. The save() method returns a boolean indicating success. Properties return their respective types (str, datetime, bool, DocUser, etc.).

Class Interface

Methods

__init__(self, data: Optional[Dict[str, Any]] = None, uid: Optional[str] = None)

Purpose: Initialize a review comment instance, either from provided data or by loading from database using UID

Parameters:

  • data: Dictionary of comment properties to initialize with
  • uid: Comment UID to load from database if data not provided

Returns: None (constructor)

create(cls, review_cycle_uid: str, commenter: Union[DocUser, str], text: str, requires_resolution: bool = False, properties: Optional[Dict[str, Any]] = None) -> Optional['ReviewComment']

Purpose: Create a new review comment in the database with proper relationships to review cycle

Parameters:

  • review_cycle_uid: UID of the review cycle this comment belongs to
  • commenter: DocUser instance or UID string of the user making the comment
  • text: The comment text content
  • requires_resolution: Boolean flag indicating if this comment needs to be resolved (default False)
  • properties: Additional properties to store with the comment

Returns: New ReviewComment instance if successful, None if creation failed

save(self) -> bool

Purpose: Persist comment changes to the database, creating node if it doesn't exist or updating if it does

Returns: Boolean indicating whether save operation was successful

text(self) -> str property

Purpose: Get the comment text content

Returns: String containing the comment text, empty string if not set

timestamp(self) -> Optional[datetime] property

Purpose: Get the datetime when the comment was created

Returns: datetime object of when comment was made, or None if not set

requires_resolution(self) -> bool property

Purpose: Check if this comment requires resolution

Returns: Boolean indicating whether comment requires resolution (default False)

resolution(self) -> Optional[str] property

Purpose: Get the resolution text for this comment

Returns: String containing resolution text, or None if not resolved

resolution(self, text: str) -> None property

Purpose: Set the resolution text and automatically update resolution date in database

Parameters:

  • text: The resolution text to set

Returns: None (setter automatically persists to database)

resolution_date(self) -> Optional[datetime] property

Purpose: Get the datetime when the comment was resolved

Returns: datetime object of when comment was resolved, or None if not resolved

is_resolved(self) -> bool property

Purpose: Check if the comment has been resolved

Returns: Boolean indicating whether comment has resolution text set

commenter_uid(self) -> Optional[str] property

Purpose: Get the UID of the user who made the comment

Returns: String UID of the commenter, or None if not set

commenter(self) -> Optional[DocUser] property

Purpose: Get the DocUser instance of the user who made the comment

Returns: DocUser instance of the commenter, or None if commenter UID not set

review_cycle_uid(self) -> Optional[str] property

Purpose: Get the UID of the review cycle this comment belongs to, querying database if needed and caching result

Returns: String UID of the review cycle, or None if relationship not found

to_dict(self) -> Dict[str, Any]

Purpose: Convert the comment to a dictionary representation including commenter information

Returns: Dictionary containing all comment data plus nested commenter information (UID, name, email)

Attributes

Name Type Description Scope
_data Dict[str, Any] Internal dictionary storing all comment properties (inherited from BaseModel) instance
uid str Unique identifier for the comment (inherited from BaseModel) instance

Dependencies

  • logging
  • uuid
  • typing
  • datetime
  • CDocs.db
  • CDocs.config
  • CDocs.db.schema_manager
  • CDocs.models.base
  • CDocs.models.user_extensions
  • CDocs.models.document

Required Imports

import logging
import uuid
from typing import Dict, List, Any, Optional, Union, Set
from datetime import datetime, timedelta
from CDocs import db
from CDocs.config import settings
from CDocs.db.schema_manager import NodeLabels, RelTypes
from CDocs.models.base import BaseModel, register_model
from CDocs.models.user_extensions import DocUser

Usage Example

# Create a new review comment
comment = ReviewComment.create(
    review_cycle_uid='cycle-123',
    commenter='user-456',
    text='This section needs clarification',
    requires_resolution=True
)

# Load existing comment from database
existing_comment = ReviewComment(uid='comment-789')

# Access comment properties
print(comment.text)
print(comment.timestamp)
print(comment.requires_resolution)

# Get commenter information
commenter = comment.commenter
if commenter:
    print(f'Comment by: {commenter.name}')

# Resolve a comment
if comment.requires_resolution:
    comment.resolution = 'Updated section with additional details'
    comment.save()

# Check resolution status
if comment.is_resolved:
    print(f'Resolved on: {comment.resolution_date}')

# Convert to dictionary for serialization
comment_dict = comment.to_dict()

Best Practices

  • Always use the create() class method to create new comments rather than direct instantiation, as it handles database relationships properly
  • Check return values from create() and save() methods for None/False to handle failures gracefully
  • Use the resolution property setter to resolve comments, as it automatically updates the resolution date and persists to database
  • The class automatically handles database synchronization when setting the resolution property
  • Load comments by UID when you need to work with existing comments: ReviewComment(uid='comment-id')
  • The commenter property performs a database lookup, so cache the result if using multiple times
  • The review_cycle_uid property caches its result after first lookup to avoid repeated database queries
  • Call save() after modifying comment properties (except resolution which auto-saves) to persist changes
  • The class inherits from BaseModel, so it has access to uid and _data attributes from the parent class
  • Failed comment creation automatically cleans up orphaned nodes to maintain database integrity

Similar Components

AI-powered semantic similarity - components with related functionality:

  • class ApprovalComment 80.4% similar

    Model class representing a comment made during a document approval cycle, with support for resolution tracking and database persistence.

    From: /tf/active/vicechatdev/CDocs/models/approval_bis.py
  • class ApprovalComment_v1 80.1% similar

    A model class representing a comment made during a document approval cycle, with support for resolution tracking and database persistence.

    From: /tf/active/vicechatdev/CDocs/models/approval.py
  • class ReviewerAssignment 64.6% similar

    Model class representing a reviewer assignment within a review cycle, managing reviewer information, status, decisions, and lifecycle tracking for document review processes.

    From: /tf/active/vicechatdev/CDocs/models/review.py
  • class ReviewCycle 63.7% similar

    Model representing a review cycle for a document version.

    From: /tf/active/vicechatdev/CDocs/models/review.py
  • function add_review_comment 62.6% 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
← Back to Browse