function send_notification
Sends in-app notifications to one or more users and optionally sends corresponding email notifications using templates.
/tf/active/vicechatdev/CDocs/utils/notifications.py
1132 - 1234
moderate
Purpose
This function provides a unified interface for sending notifications to users in a document management system. It handles both in-app notifications (stored in database) and email notifications. It supports flexible user input (DocUser objects or UID strings), resource linking, custom messages, and templated emails. The function is designed to notify users about various events like document updates, reviews, approvals, or system alerts.
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
"""
logger.info(f"Sending notification of type {notification_type} to users: {users}")
# 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.Mail 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)
logger.debug(f"Added details to template_data: {list(details.keys()) if details else 'None'}")
if email_data:
template_data.update(email_data)
logger.debug(f"Added email_data to template_data: {list(email_data.keys()) if email_data else 'None'}")
logger.debug(f"Email_data contents: {email_data}")
else:
logger.warning(f"No email_data provided for template '{email_template}'")
# Add message if provided
if message:
template_data['message'] = message
logger.debug(f"Final template_data keys for '{email_template}': {list(template_data.keys())}")
# Send email
logger.info(f"Sending email to {user_emails} with subject: {subject}")
gen_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 NOTIFICATION_TYPES dictionary. This determines the notification category and default subject line for emails.
users: Flexible input accepting a single user or list of users. Each user can be either a DocUser model instance or a string UID. The function normalizes this to extract UIDs and email addresses.
resource_uid: Optional string UID of the resource (e.g., document, review cycle) that this notification relates to. Used for linking notifications to specific resources in the system.
resource_type: Optional string describing the type of resource (e.g., 'document', 'review', 'approval'). Helps categorize what the notification is about.
message: Optional custom message text for the notification. Can be used as fallback email subject if template formatting fails.
details: Optional dictionary containing additional structured data about the notification. Used for subject line formatting and merged into email template data.
send_email: Boolean flag (default False) indicating whether to send email notifications in addition to in-app notifications.
email_template: Optional string name of the email template to use when send_email is True. Template should exist in the email system.
email_data: Optional dictionary containing data specifically for email template rendering. Merged with details dictionary, with email_data taking precedence.
Return Value
Type: List[str]
Returns a list of strings, where each string is a UID of a successfully created in-app notification. The list length corresponds to the number of users notified. Returns empty list if no notifications were created.
Dependencies
loggingtypingCDocssmtplibemail.mimemsalrequests
Required Imports
from typing import List, Union, Optional, Dict, Any
from CDocs.models.user_extensions import DocUser
from CDocs import db
from CDocs.config import settings
import logging
Conditional/Optional Imports
These imports are only needed under specific conditions:
from CDocs.controllers.document_controller import get_document_edit_url
Condition: May be used by email templates or notification creation logic
Optionalfrom models.review import ReviewCycle
Condition: If notifications relate to review cycles
Optionalfrom models.approval import Approval
Condition: If notifications relate to approval workflows
OptionalUsage Example
# Example 1: Simple in-app notification
notification_uids = send_notification(
notification_type='document_updated',
users='user123',
resource_uid='doc456',
resource_type='document',
message='Your document has been updated'
)
# Example 2: Notification with email to multiple users
from CDocs.models.user_extensions import DocUser
users = [DocUser(uid='user1', email='user1@example.com'), 'user2']
notification_uids = send_notification(
notification_type='review_assigned',
users=users,
resource_uid='review789',
resource_type='review',
message='You have been assigned a new review',
details={'document_name': 'Q4 Report', 'due_date': '2024-01-15'},
send_email=True,
email_template='review_assignment',
email_data={'reviewer_name': 'John Doe', 'document_link': 'https://app.example.com/doc/123'}
)
# Example 3: Bulk notification with template formatting
notification_uids = send_notification(
notification_type='approval_required',
users=['user1', 'user2', 'user3'],
resource_uid='approval101',
resource_type='approval',
details={'approver_count': 3, 'deadline': '2024-01-20'},
send_email=True,
email_template='approval_request',
email_data={'document_title': 'Budget Proposal 2024'}
)
Best Practices
- Always define notification_type in NOTIFICATION_TYPES dictionary before calling this function
- When using send_email=True, ensure email_template exists and email_data contains all required template variables
- The details dictionary is merged with email_data, with email_data taking precedence for duplicate keys
- User UIDs should exist in the database to retrieve email addresses when passing string UIDs
- Handle the returned notification_uids list to track which notifications were successfully created
- Use DocUser instances when possible to avoid additional database queries for email addresses
- The function logs extensively - ensure logging is configured appropriately for debugging
- Subject line formatting uses details dictionary with .format() - ensure keys match placeholders in NOTIFICATION_TYPES subject templates
- If email sending fails, in-app notifications are still created - implement error handling for email failures if needed
- Consider rate limiting or batching when sending notifications to large user lists
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function create_notification 74.8% similar
-
function notify_approval 68.8% similar
-
function notify_document_update 65.1% similar
-
function notify_review 64.3% similar
-
function get_user_notifications 54.6% similar