🔍 Code Extractor

function send_notification_v1

Maturity: 83

Sends in-app notifications to one or more users with optional email delivery, supporting both DocUser objects and user UID strings.

File:
/tf/active/vicechatdev/CDocs single class/utils/notifications.py
Lines:
940 - 1033
Complexity:
moderate

Purpose

This function provides a unified interface for sending notifications to users in a document management system. It creates in-app notifications in the database and optionally sends corresponding email notifications. It handles both single and multiple recipients, accepts either DocUser objects or user UID strings, retrieves user emails from the database when needed, and supports templated email content with dynamic data substitution.

Source Code

def send_notification(notification_type: str,
                     users: Union[List[Union[DocUser, str]], DocUser, str],
                     resource_uid: Optional[str] = None,
                     resource_type: Optional[str] = None,
                     message: Optional[str] = None,
                     details: Optional[Dict[str, Any]] = None,
                     send_email: bool = False,
                     email_template: Optional[str] = None,
                     email_data: Optional[Dict[str, Any]] = None) -> List[str]:
    """
    Send a notification to one or more users, optionally with email.
    
    Args:
        notification_type: Type of notification from NOTIFICATION_TYPES
        users: User(s) to notify (DocUser instance(s) or UID(s))
        resource_uid: Optional UID of resource this notification is about
        resource_type: Optional type of resource
        message: Optional message text
        details: Optional additional details
        send_email: Whether to also send email notification
        email_template: Template to use for email (if sending email)
        email_data: Data for email template (if sending email)
        
    Returns:
        List of created notification UIDs
    """
    # Ensure users is a list
    if not isinstance(users, list):
        users = [users]
        
    # Extract UIDs and emails
    user_uids = []
    user_emails = []
    for user in users:
        if isinstance(user, DocUser):
            user_uids.append(user.uid)
            if user.email:
                user_emails.append(user.email)
        else:
            user_uids.append(user)
            # Try to get email from database
            result = db.run_query(
                "MATCH (u:User {UID: $uid}) RETURN u.Email as email",
                {"uid": user}
            )
            if result and result[0].get('email'):
                user_emails.append(result[0]['email'])
    
    # Create in-app notifications
    notification_uids = []
    for user_uid in user_uids:
        notification_uid = create_notification(
            notification_type, user_uid, resource_uid, 
            resource_type, message, details
        )
        if notification_uid:
            notification_uids.append(notification_uid)
    
    # Send email if requested
    if send_email and user_emails:
        # Get notification info
        notification_info = NOTIFICATION_TYPES.get(notification_type, {})
        
        # Prepare subject
        subject = notification_info.get('subject', 'Notification from ' + settings.APP_NAME)
        
        # Format subject with details if available
        if details:
            try:
                subject = subject.format(**details)
            except KeyError:
                pass
                
        # Default to message as subject if formatting fails
        if subject == notification_info.get('subject') and message:
            subject = message
            
        # Send email
        if email_template:
            # Merge details and email_data
            template_data = {}
            if details:
                template_data.update(details)
            if email_data:
                template_data.update(email_data)
                
            # Add message if provided
            if message:
                template_data['message'] = message
                
            # Send email
            send_email(user_emails, subject, email_template, template_data)
    
    return notification_uids

Parameters

Name Type Default Kind
notification_type str - positional_or_keyword
users Union[List[Union[DocUser, str]], DocUser, str] - positional_or_keyword
resource_uid Optional[str] None positional_or_keyword
resource_type Optional[str] None positional_or_keyword
message Optional[str] None positional_or_keyword
details Optional[Dict[str, Any]] None positional_or_keyword
send_email bool False positional_or_keyword
email_template Optional[str] None positional_or_keyword
email_data Optional[Dict[str, Any]] None positional_or_keyword

Parameter Details

notification_type: String identifier for the type of notification, must match a key in the NOTIFICATION_TYPES configuration dictionary. This determines the notification category and default subject line.

users: Single user or list of users to notify. Can be DocUser instance(s), user UID string(s), or a mix. The function normalizes this to a list internally.

resource_uid: Optional unique identifier of the resource (document, review, approval, etc.) that this notification relates to. Used for linking notifications to specific resources.

resource_type: Optional string indicating the type of resource (e.g., 'document', 'review', 'approval'). Helps categorize notifications by resource type.

message: Optional custom message text for the notification. If provided and email subject formatting fails, this will be used as the email subject.

details: Optional dictionary containing additional structured data about the notification. Used for subject line formatting and passed to email templates.

send_email: Boolean flag indicating whether to send email notifications in addition to in-app notifications. Defaults to False.

email_template: Optional string identifier for the email template to use when sending emails. Required if send_email is True and you want formatted emails.

email_data: Optional dictionary containing additional data to pass to the email template. Merged with 'details' parameter, with email_data taking precedence on key conflicts.

Return Value

Type: List[str]

Returns a list of strings containing the UIDs of successfully created in-app notifications. Each UID corresponds to one notification created for one user. If notification creation fails for any user, that UID will not be included in the list. An empty list indicates no notifications were created.

Dependencies

  • logging
  • os
  • json
  • uuid
  • typing
  • datetime
  • re
  • base64
  • email.mime.multipart
  • email.mime.text
  • email.mime.application
  • smtplib
  • msal
  • requests
  • CDocs
  • CDocs.config
  • CDocs.models.user_extensions
  • CDocs.utils
  • models.review
  • models.approval

Required Imports

from typing import Dict, List, Any, Optional, Union
from CDocs.models.user_extensions import DocUser
from CDocs import db
from CDocs.config import settings

Usage Example

# Example 1: Send simple in-app notification to single user
notification_uids = send_notification(
    notification_type='document_updated',
    users='user_123',
    resource_uid='doc_456',
    resource_type='document',
    message='Your document has been updated'
)

# Example 2: Send notification with email to multiple users
from CDocs.models.user_extensions import DocUser

user1 = DocUser(uid='user_123', email='user1@example.com')
user2 = DocUser(uid='user_456', email='user2@example.com')

notification_uids = send_notification(
    notification_type='review_assigned',
    users=[user1, user2],
    resource_uid='review_789',
    resource_type='review',
    message='You have been assigned to review a document',
    details={'document_name': 'Project Plan', 'due_date': '2024-01-15'},
    send_email=True,
    email_template='review_assignment',
    email_data={'reviewer_name': 'John Doe', 'document_url': 'https://app.example.com/doc/789'}
)

# Example 3: Mixed user types
notification_uids = send_notification(
    notification_type='approval_required',
    users=[user1, 'user_789'],  # Mix of DocUser and UID string
    resource_uid='approval_101',
    resource_type='approval',
    details={'approver': 'Jane Smith', 'deadline': '2024-01-20'}
)

Best Practices

  • Always ensure NOTIFICATION_TYPES dictionary contains the notification_type key before calling this function to avoid missing subject lines
  • When using send_email=True, provide email_template for properly formatted emails rather than relying on plain message text
  • Be aware of the naming conflict: the parameter 'send_email' (bool) shadows the function 'send_email()' called internally - this is a code smell that should be refactored
  • The function silently continues if email retrieval fails for string UIDs, so verify user UIDs exist in database beforehand for critical notifications
  • Use 'details' parameter for data that should be available to both in-app notifications and email templates
  • Use 'email_data' parameter for email-specific data that shouldn't be stored in the in-app notification
  • Check the returned list length to verify all notifications were created successfully
  • The function requires create_notification() to be defined elsewhere - ensure this dependency is available
  • Subject line formatting uses Python's str.format() with details dict - ensure detail keys match template placeholders

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function send_notification 97.6% similar

    Sends in-app notifications to one or more users and optionally sends corresponding email notifications using templates.

    From: /tf/active/vicechatdev/CDocs/utils/notifications.py
  • function create_notification 74.6% similar

    Creates an in-app notification for a user in a graph database, linking it to the user and optionally to a related resource.

    From: /tf/active/vicechatdev/CDocs/utils/notifications.py
  • function notify_approval_v1 67.9% similar

    Sends approval notifications to designated approvers for a document version, supporting multiple notification types (requested, reminder, overdue, completed, rejected, signed) with email and in-app notifications.

    From: /tf/active/vicechatdev/CDocs single class/utils/notifications.py
  • function notify_approval 67.3% similar

    Sends approval notifications to designated approvers for a document version, supporting multiple notification types (requested, reminder, overdue, completed, rejected, signed) with email and in-app notifications.

    From: /tf/active/vicechatdev/CDocs/utils/notifications.py
  • function notify_document_update 65.8% similar

    Sends notifications to interested users when a controlled document is created, updated, or has a status/version change. Identifies relevant users through database queries and dispatches notifications via the send_notification function.

    From: /tf/active/vicechatdev/CDocs single class/utils/notifications.py
← Back to Browse