🔍 Code Extractor

function clone_document_v1

Maturity: 81

Clones an existing controlled document by creating a new document with optional content copying, metadata inheritance, and audit trail logging.

File:
/tf/active/vicechatdev/CDocs single class/controllers/document_controller.py
Lines:
2112 - 2240
Complexity:
complex

Purpose

This function enables document duplication within a controlled document management system. It creates a new document based on an existing source document, optionally copying its content and version history. The function supports customization of the cloned document's title, type, and department, while maintaining audit trails and enforcing permissions. It handles the complete workflow including document creation, content transfer, version management, and error recovery with automatic cleanup on failure.

Source Code

def clone_document(
    user: DocUser,
    document_uid: str,
    new_title: Optional[str] = None,
    doc_type: Optional[str] = None,
    department: Optional[str] = None,
    include_content: bool = True,
    clone_as_new_revision: bool = False
) -> Dict[str, Any]:
    """
    Clone an existing document as a new document or new revision.
    
    Args:
        user: User cloning the document
        document_uid: UID of the source document
        new_title: Title for the cloned document (defaults to "Copy of [original]")
        doc_type: Document type code for the new document (defaults to same as original)
        department: Department code for the new document (defaults to same as original)
        include_content: Whether to include the content of the original document
        clone_as_new_revision: Whether to create as a new revision of the same document
        
    Returns:
        Dictionary with cloned document details
    """
    try:
        # Get the source document
        source_document = ControlledDocument(uid=document_uid)
        if not source_document:
            raise ResourceNotFoundError(f"Document {document_uid} not found")
            
        # Get current version
        current_version = source_document.current_version
        if not current_version and include_content:
            raise BusinessRuleError("Document has no current version to clone")
        
        # Use original title if none provided
        if not new_title:
            new_title = f"Copy of {source_document.title}"
        
        # Use original document type and department if none provided
        if not doc_type:
            doc_type = source_document.doc_type
        
        if not department:
            department = source_document.department
            
        # Create new document
        new_document = ControlledDocument.create(
            title=new_title,
            doc_type=doc_type,
            department=department,
            owner=user,
            properties={
                "description": f"Cloned from {source_document.doc_number}: {source_document.title}",
                "status": "DRAFT",
                "revision" : "0.0"
            }
        )
        
        if not new_document:
            raise BusinessRuleError("Failed to create new document")
            
        # Copy content if requested
        if include_content and current_version:
            # Download content from source document
            content_result = download_document_version(
                user=user,
                document_uid=document_uid,
                version_uid=current_version.uid if current_version else None
            )
            
            if not content_result or 'content' not in content_result:
                raise BusinessRuleError("Failed to download source document content")
                
            # Create initial version for new document
            file_content = content_result['content']
            file_name = content_result.get('file_name', 'document.pdf')
            
            # Create version for new document
            version_result = create_document_version(
                user=user,
                document_uid=new_document.uid,
                file_content=file_content,
                file_name=file_name,
                comment="Initial version created from cloned document"
            )
            
            if not version_result or 'UID' not in version_result:
                # If version creation fails, delete the new document to clean up
                db.delete_node(new_document.uid, cascade=True)
                raise BusinessRuleError("Failed to create document version")
        
        # Log cloning event
        audit_trail.log_document_lifecycle_event(
            event_type="DOCUMENT_CLONED",
            user=user,
            document_uid=new_document.uid,
            details={
                "source_document_uid": document_uid,
                "source_document_number": source_document.doc_number,
                "include_content": include_content
            }
        )
        
        # Return success with new document details
        return {
            "success": True,
            "message": "Document cloned successfully",
            "document": {
                "uid": new_document.uid,
                "doc_number": new_document.doc_number,
                "title": new_document.title,
                "version_uid" : version_result.get('UID') if version_result else None
            }
        }
        
    except (ResourceNotFoundError, ValidationError, PermissionError, BusinessRuleError) as e:
        logger.error(f"Error cloning document: {str(e)}")
        return {
            "success": False,
            "message": str(e)
        }
    except Exception as e:
        logger.error(f"Unexpected error cloning document: {str(e)}")
        logger.error(traceback.format_exc())
        return {
            "success": False,
            "message": f"An unexpected error occurred: {str(e)}"
        }

Parameters

Name Type Default Kind
user DocUser - positional_or_keyword
document_uid str - positional_or_keyword
new_title Optional[str] None positional_or_keyword
doc_type Optional[str] None positional_or_keyword
department Optional[str] None positional_or_keyword
include_content bool True positional_or_keyword
clone_as_new_revision bool False positional_or_keyword

Parameter Details

user: DocUser object representing the authenticated user performing the clone operation. Must have CREATE_DOCUMENT permission as enforced by the decorator.

document_uid: String containing the unique identifier (UID) of the source document to be cloned. Must reference an existing document in the system.

new_title: Optional string for the cloned document's title. If None, defaults to 'Copy of [original title]'. Used to distinguish the clone from the original.

doc_type: Optional string code representing the document type classification for the new document. If None, inherits the doc_type from the source document.

department: Optional string code representing the department ownership for the new document. If None, inherits the department from the source document.

include_content: Boolean flag (default True) indicating whether to copy the actual file content from the source document's current version to the new document. If False, only metadata is cloned.

clone_as_new_revision: Boolean flag (default False) intended to create the clone as a new revision of the same document rather than a separate document. Note: This parameter is declared but not currently implemented in the function logic.

Return Value

Type: Dict[str, Any]

Returns a dictionary with keys: 'success' (bool indicating operation success), 'message' (str with status/error message), and optionally 'document' (dict containing 'uid', 'doc_number', 'title', and 'version_uid' of the cloned document). On failure, only 'success' and 'message' keys are present.

Dependencies

  • logging
  • uuid
  • os
  • tempfile
  • typing
  • datetime
  • io
  • panel
  • shutil
  • traceback
  • json
  • re
  • CDocs
  • config
  • random

Required Imports

from typing import Dict, Any, Optional
import traceback
import logging
from CDocs import db
from CDocs.config import settings
from CDocs.models.document import ControlledDocument
from CDocs.models.user_extensions import DocUser
from CDocs.utils import audit_trail
from CDocs.controllers import require_permission, log_controller_action, transaction
from CDocs.controllers import ResourceNotFoundError, ValidationError, PermissionError, BusinessRuleError
from CDocs.controllers.document_controller import download_document_version, create_document_version

Usage Example

from CDocs.models.user_extensions import DocUser
from CDocs.controllers.document_controller import clone_document

# Get authenticated user
user = DocUser.get_by_username('john.doe')

# Clone a document with default settings (includes content)
result = clone_document(
    user=user,
    document_uid='doc-12345-abcde'
)

if result['success']:
    print(f"Document cloned successfully: {result['document']['doc_number']}")
    print(f"New UID: {result['document']['uid']}")
else:
    print(f"Clone failed: {result['message']}")

# Clone with custom title and without content
result = clone_document(
    user=user,
    document_uid='doc-12345-abcde',
    new_title='Modified Copy of Original',
    doc_type='PROCEDURE',
    department='ENGINEERING',
    include_content=False
)

# Access cloned document details
if result['success']:
    cloned_uid = result['document']['uid']
    cloned_doc_number = result['document']['doc_number']

Best Practices

  • Always check the 'success' key in the returned dictionary before accessing the 'document' key to avoid KeyError exceptions
  • The function is decorated with @transaction, so database operations are automatically rolled back on failure
  • The function is decorated with @require_permission('CREATE_DOCUMENT'), so ensure the user has appropriate permissions before calling
  • When include_content=True, ensure the source document has a current version, otherwise a BusinessRuleError will be raised
  • The function automatically cleans up (deletes) the newly created document if version creation fails, preventing orphaned documents
  • The clone_as_new_revision parameter is currently not implemented in the function logic despite being declared
  • Audit trail events are automatically logged for successful cloning operations with source document details
  • Use specific exception handling for ResourceNotFoundError, ValidationError, PermissionError, and BusinessRuleError for granular error management
  • The function uses download_document_version and create_document_version helper functions which must be available in the same module
  • Default title format 'Copy of [original]' helps users identify cloned documents; consider providing custom titles for clarity

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function clone_document 94.6% similar

    Clones an existing controlled document, creating a new document with optional content copying, custom properties, and FileCloud integration.

    From: /tf/active/vicechatdev/CDocs/controllers/document_controller.py
  • function clone_document_v2 93.3% similar

    Clones an existing controlled document to create either a new independent document or a new revision of the same document, optionally including the document's content.

    From: /tf/active/vicechatdev/document_controller_backup.py
  • function create_document_version_v4 70.0% similar

    Creates a new controlled document in a document management system with specified properties, type, department, and status.

    From: /tf/active/vicechatdev/document_controller_backup.py
  • function create_document_version_v3 68.4% similar

    Creates a new version of a controlled document by generating version metadata, storing the file in FileCloud, updating the document's revision number, and creating an audit trail entry.

    From: /tf/active/vicechatdev/CDocs/controllers/document_controller.py
  • function create_document_version_v5 67.6% similar

    Creates a new controlled document in the CDocs system with specified metadata, content, and properties, returning a status dictionary with the created document details.

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