nexus-5/core/services/events.py
2026-01-26 11:09:40 -05:00

1633 lines
56 KiB
Python

"""
Event publishing service for the notification system.
Creates Event records that can trigger notifications.
"""
from typing import Any, Optional, Dict, Set
from django.contrib.contenttypes.models import ContentType
from channels.db import database_sync_to_async
from core.models.events import Event
from core.models.enums import EventTypeChoices
from core.services.metadata import MetadataEnricher
# Mission-critical events that are ALWAYS created (regardless of notification rules)
# These events are essential for audit trails, compliance, and business operations
MISSION_CRITICAL_EVENTS: Set[EventTypeChoices] = {
# Service delivery (customer-facing)
EventTypeChoices.SERVICE_COMPLETED,
EventTypeChoices.SERVICE_CANCELLED,
EventTypeChoices.SERVICE_SESSION_CLOSED,
# Project milestones
EventTypeChoices.PROJECT_COMPLETED,
EventTypeChoices.PROJECT_CANCELLED,
EventTypeChoices.PROJECT_SESSION_CLOSED,
# Issues requiring attention
EventTypeChoices.ACCOUNT_PUNCHLIST_CREATED,
EventTypeChoices.PROJECT_PUNCHLIST_CREATED,
EventTypeChoices.PUNCHLIST_STATUS_CHANGED,
# Financial events (compliance/audit)
EventTypeChoices.INVOICE_GENERATED,
EventTypeChoices.INVOICE_SENT,
EventTypeChoices.INVOICE_PAID,
EventTypeChoices.INVOICE_OVERDUE,
EventTypeChoices.INVOICE_CANCELLED,
EventTypeChoices.LABOR_RATE_CREATED,
EventTypeChoices.LABOR_RATE_UPDATED,
EventTypeChoices.LABOR_RATE_DELETED,
EventTypeChoices.REVENUE_RATE_CREATED,
EventTypeChoices.REVENUE_RATE_UPDATED,
EventTypeChoices.REVENUE_RATE_DELETED,
# Reporting & documentation (legal/compliance)
EventTypeChoices.REPORT_SUBMITTED,
EventTypeChoices.REPORT_APPROVED,
EventTypeChoices.SESSION_IMAGE_UPLOADED,
EventTypeChoices.SESSION_VIDEO_UPLOADED,
# Account & access management (security/audit)
EventTypeChoices.CUSTOMER_CREATED,
EventTypeChoices.CUSTOMER_DELETED,
EventTypeChoices.CUSTOMER_STATUS_CHANGED,
EventTypeChoices.ACCOUNT_CREATED,
EventTypeChoices.ACCOUNT_DELETED,
EventTypeChoices.ACCOUNT_STATUS_CHANGED,
EventTypeChoices.TEAM_PROFILE_CREATED,
EventTypeChoices.TEAM_PROFILE_DELETED,
EventTypeChoices.TEAM_PROFILE_ROLE_CHANGED,
EventTypeChoices.CUSTOMER_PROFILE_CREATED,
EventTypeChoices.CUSTOMER_PROFILE_DELETED,
EventTypeChoices.CUSTOMER_PROFILE_ACCESS_GRANTED,
EventTypeChoices.CUSTOMER_PROFILE_ACCESS_REVOKED,
# Schedule changes (operational impact)
EventTypeChoices.SCHEDULE_CREATED,
EventTypeChoices.SCHEDULE_DELETED,
EventTypeChoices.SCHEDULE_FREQUENCY_CHANGED,
EventTypeChoices.SERVICES_BULK_GENERATED,
}
class EventPublisher:
"""
Service for publishing events to the event management system.
Events are stored in the database and can trigger notifications via Celery tasks.
"""
@staticmethod
async def publish(
event_type: EventTypeChoices,
entity_type: str,
entity_id: str,
triggered_by: Optional[Any] = None,
metadata: Optional[Dict[str, Any]] = None
) -> Optional[Event]:
"""
Publish an event to the event management system.
For mission-critical events, the event is always created.
For non-critical events, the event is only created if there are active notification rules.
Args:
event_type: Type of event (from EventTypeChoices enum)
entity_type: Type of entity (e.g., 'Project', 'Report', 'Invoice')
entity_id: UUID of the entity that triggered this event
triggered_by: Profile instance (TeamProfile or CustomerProfile) that triggered the event
metadata: Additional event metadata (e.g., old_status, new_status, changed_fields)
Returns:
Event: The created Event instance, or None if event was skipped
Example:
await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_CREATED,
entity_type='Project',
entity_id=project.id,
triggered_by=team_profile,
metadata={'status': 'ACTIVE'})
"""
# Check if event is mission-critical
is_critical = event_type in MISSION_CRITICAL_EVENTS
# For non-critical events, check if there are any active notification rules
if not is_critical:
from core.models.events import NotificationRule
has_rules = await database_sync_to_async(
lambda: NotificationRule.objects.filter(
is_active=True,
event_types__contains=[event_type]
).exists()
)()
if not has_rules:
# Skip event creation - no rules configured for this event type
return None
# Enrich metadata with domain-appropriate fields
enriched_metadata = await MetadataEnricher.enrich(
event_type=event_type,
entity_type=entity_type,
entity_id=entity_id,
existing_metadata=metadata
)
event_data = {
'event_type': event_type,
'entity_type': entity_type,
'entity_id': entity_id,
'metadata': enriched_metadata,
}
# Set a generic foreign key for triggered_by if provided
if triggered_by:
content_type = await database_sync_to_async(ContentType.objects.get_for_model)(triggered_by)
event_data['triggered_by_content_type'] = content_type
event_data['triggered_by_object_id'] = triggered_by.id
# Create the event
event = await database_sync_to_async(Event.objects.create)(**event_data)
# Queue notification processing task
# Note: .delay() is non-blocking and doesn't need sync_to_async wrapping
from core.tasks.notifications import process_event_notifications
process_event_notifications.delay(str(event.id))
return event
@staticmethod
def publish_sync(
event_type: EventTypeChoices,
entity_type: str,
entity_id: str,
triggered_by: Optional[Any] = None,
metadata: Optional[Dict[str, Any]] = None
) -> Optional[Event]:
"""
Synchronous version of publish() for use in non-async contexts.
For mission-critical events, the event is always created.
For non-critical events, the event is only created if there are active notification rules.
Args:
event_type: Type of event (from EventTypeChoices enum)
entity_type: Type of entity (e.g., 'Project', 'Report', 'Invoice')
entity_id: UUID of the entity that triggered this event
triggered_by: Profile instance (TeamProfile or CustomerProfile) that triggered the event
metadata: Additional event metadata
Returns:
Event: The created Event instance, or None if event was skipped
"""
# Check if event is mission-critical
is_critical = event_type in MISSION_CRITICAL_EVENTS
# For non-critical events, check if there are any active notification rules
if not is_critical:
from core.models.events import NotificationRule
has_rules = NotificationRule.objects.filter(
is_active=True,
event_types__contains=[event_type]
).exists()
if not has_rules:
# Skip event creation - no rules configured for this event type
return None
event_data = {
'event_type': event_type,
'entity_type': entity_type,
'entity_id': entity_id,
'metadata': metadata or {},
}
# Set a generic foreign key for triggered_by if provided
if triggered_by:
content_type = ContentType.objects.get_for_model(triggered_by)
event_data['triggered_by_content_type'] = content_type
event_data['triggered_by_object_id'] = triggered_by.id
# Create the event
event = Event.objects.create(**event_data)
# Queue notification processing task
from core.tasks.notifications import process_event_notifications
process_event_notifications.delay(str(event.id))
return event
# ========================================
# Convenience functions for common event types
# ========================================
# Customer events
async def publish_customer_created(customer_id: str, triggered_by=None, metadata=None):
"""Publish CUSTOMER_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_CREATED,
entity_type='Customer',
entity_id=customer_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_customer_updated(customer_id: str, triggered_by=None, metadata=None):
"""Publish CUSTOMER_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_UPDATED,
entity_type='Customer',
entity_id=customer_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_customer_deleted(customer_id: str, triggered_by=None, metadata=None):
"""Publish CUSTOMER_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_DELETED,
entity_type='Customer',
entity_id=customer_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_customer_status_changed(customer_id: str, old_status: str, new_status: str, triggered_by=None):
"""Publish CUSTOMER_STATUS_CHANGED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_STATUS_CHANGED,
entity_type='Customer',
entity_id=customer_id,
triggered_by=triggered_by,
metadata={'old_status': old_status, 'new_status': new_status}
)
# Account events
async def publish_account_created(account_id: str, triggered_by=None, metadata=None):
"""Publish ACCOUNT_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_CREATED,
entity_type='Account',
entity_id=account_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_account_updated(account_id: str, triggered_by=None, metadata=None):
"""Publish ACCOUNT_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_UPDATED,
entity_type='Account',
entity_id=account_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_account_deleted(account_id: str, triggered_by=None, metadata=None):
"""Publish ACCOUNT_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_DELETED,
entity_type='Account',
entity_id=account_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_account_status_changed(account_id: str, old_status: str, new_status: str, triggered_by=None):
"""Publish ACCOUNT_STATUS_CHANGED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_STATUS_CHANGED,
entity_type='Account',
entity_id=account_id,
triggered_by=triggered_by,
metadata={'old_status': old_status, 'new_status': new_status}
)
# Service events
async def publish_service_created(service_id: str, triggered_by=None, metadata=None):
"""Publish SERVICE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_CREATED,
entity_type='Service',
entity_id=service_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_service_updated(service_id: str, triggered_by=None, metadata=None):
"""Publish SERVICE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_UPDATED,
entity_type='Service',
entity_id=service_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_service_deleted(service_id: str, triggered_by=None, metadata=None):
"""Publish SERVICE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_DELETED,
entity_type='Service',
entity_id=service_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_service_status_changed(service_id: str, old_status: str, new_status: str, triggered_by=None):
"""Publish SERVICE_STATUS_CHANGED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_STATUS_CHANGED,
entity_type='Service',
entity_id=service_id,
triggered_by=triggered_by,
metadata={'old_status': old_status, 'new_status': new_status}
)
async def publish_service_completed(service_id: str, triggered_by=None, metadata=None):
"""Publish SERVICE_COMPLETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_COMPLETED,
entity_type='Service',
entity_id=service_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_service_cancelled(service_id: str, triggered_by=None, metadata=None):
"""Publish SERVICE_CANCELLED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_CANCELLED,
entity_type='Service',
entity_id=service_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_service_team_assigned(service_id: str, team_member_id: str, team_member_name: str, triggered_by=None):
"""Publish SERVICE_TEAM_ASSIGNED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_TEAM_ASSIGNED,
entity_type='Service',
entity_id=service_id,
triggered_by=triggered_by,
metadata={'team_member_id': team_member_id, 'team_member_name': team_member_name}
)
async def publish_service_team_unassigned(service_id: str, team_member_id: str, team_member_name: str, triggered_by=None):
"""Publish SERVICE_TEAM_UNASSIGNED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_TEAM_UNASSIGNED,
entity_type='Service',
entity_id=service_id,
triggered_by=triggered_by,
metadata={'team_member_id': team_member_id, 'team_member_name': team_member_name}
)
async def publish_service_dispatched(service_id: str, triggered_by=None, metadata=None):
"""Publish SERVICE_DISPATCHED event (admin assigned to service)"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_DISPATCHED,
entity_type='Service',
entity_id=service_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_services_bulk_generated(account_id: str, count: int, month: str, triggered_by=None):
"""Publish SERVICES_BULK_GENERATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICES_BULK_GENERATED,
entity_type='Account',
entity_id=account_id,
triggered_by=triggered_by,
metadata={'count': count, 'month': month}
)
# Schedule events
async def publish_schedule_created(schedule_id: str, triggered_by=None, metadata=None):
"""Publish SCHEDULE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SCHEDULE_CREATED,
entity_type='Schedule',
entity_id=schedule_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_schedule_updated(schedule_id: str, triggered_by=None, metadata=None):
"""Publish SCHEDULE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SCHEDULE_UPDATED,
entity_type='Schedule',
entity_id=schedule_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_schedule_deleted(schedule_id: str, triggered_by=None, metadata=None):
"""Publish SCHEDULE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SCHEDULE_DELETED,
entity_type='Schedule',
entity_id=schedule_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_schedule_frequency_changed(schedule_id: str, old_frequency: str, new_frequency: str, triggered_by=None):
"""Publish SCHEDULE_FREQUENCY_CHANGED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SCHEDULE_FREQUENCY_CHANGED,
entity_type='Schedule',
entity_id=schedule_id,
triggered_by=triggered_by,
metadata={'old_frequency': old_frequency, 'new_frequency': new_frequency}
)
# Project events
async def publish_project_created(project_id: str, triggered_by=None, metadata=None):
"""Publish PROJECT_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_CREATED,
entity_type='Project',
entity_id=project_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_project_updated(project_id: str, triggered_by=None, metadata=None):
"""Publish PROJECT_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_UPDATED,
entity_type='Project',
entity_id=project_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_project_status_changed(project_id: str, old_status: str, new_status: str, triggered_by=None):
"""Publish PROJECT_STATUS_CHANGED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_STATUS_CHANGED,
entity_type='Project',
entity_id=project_id,
triggered_by=triggered_by,
metadata={'old_status': old_status, 'new_status': new_status}
)
async def publish_project_completed(project_id: str, triggered_by=None, metadata=None):
"""Publish PROJECT_COMPLETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_COMPLETED,
entity_type='Project',
entity_id=project_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_project_cancelled(project_id: str, triggered_by=None, metadata=None):
"""Publish PROJECT_CANCELLED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_CANCELLED,
entity_type='Project',
entity_id=project_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_project_dispatched(project_id: str, triggered_by=None, metadata=None):
"""Publish PROJECT_DISPATCHED event (admin assigned to project)"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_DISPATCHED,
entity_type='Project',
entity_id=project_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_project_deleted(project_id: str, triggered_by=None, metadata=None):
"""Publish PROJECT_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_DELETED,
entity_type='Project',
entity_id=project_id,
triggered_by=triggered_by,
metadata=metadata
)
# Team profile events
async def publish_team_profile_created(profile_id: str, triggered_by=None, metadata=None):
"""Publish TEAM_PROFILE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.TEAM_PROFILE_CREATED,
entity_type='TeamProfile',
entity_id=profile_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_team_profile_updated(profile_id: str, triggered_by=None, metadata=None):
"""Publish TEAM_PROFILE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.TEAM_PROFILE_UPDATED,
entity_type='TeamProfile',
entity_id=profile_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_team_profile_deleted(profile_id: str, triggered_by=None, metadata=None):
"""Publish TEAM_PROFILE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.TEAM_PROFILE_DELETED,
entity_type='TeamProfile',
entity_id=profile_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_team_profile_role_changed(profile_id: str, old_role: str, new_role: str, triggered_by=None):
"""Publish TEAM_PROFILE_ROLE_CHANGED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.TEAM_PROFILE_ROLE_CHANGED,
entity_type='TeamProfile',
entity_id=profile_id,
triggered_by=triggered_by,
metadata={'old_role': old_role, 'new_role': new_role}
)
# Customer profile events
async def publish_customer_profile_created(profile_id: str, triggered_by=None, metadata=None):
"""Publish CUSTOMER_PROFILE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_PROFILE_CREATED,
entity_type='CustomerProfile',
entity_id=profile_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_customer_profile_updated(profile_id: str, triggered_by=None, metadata=None):
"""Publish CUSTOMER_PROFILE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_PROFILE_UPDATED,
entity_type='CustomerProfile',
entity_id=profile_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_customer_profile_deleted(profile_id: str, triggered_by=None, metadata=None):
"""Publish CUSTOMER_PROFILE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_PROFILE_DELETED,
entity_type='CustomerProfile',
entity_id=profile_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_customer_profile_access_granted(profile_id: str, customer_id: str, triggered_by=None):
"""Publish CUSTOMER_PROFILE_ACCESS_GRANTED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_PROFILE_ACCESS_GRANTED,
entity_type='CustomerProfile',
entity_id=profile_id,
triggered_by=triggered_by,
metadata={'customer_id': customer_id}
)
async def publish_customer_profile_access_revoked(profile_id: str, customer_id: str, triggered_by=None):
"""Publish CUSTOMER_PROFILE_ACCESS_REVOKED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_PROFILE_ACCESS_REVOKED,
entity_type='CustomerProfile',
entity_id=profile_id,
triggered_by=triggered_by,
metadata={'customer_id': customer_id}
)
# Report events
async def publish_report_created(report_id: str, triggered_by=None, metadata=None):
"""Publish REPORT_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.REPORT_CREATED,
entity_type='Report',
entity_id=report_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_report_updated(report_id: str, triggered_by=None, metadata=None):
"""Publish REPORT_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.REPORT_UPDATED,
entity_type='Report',
entity_id=report_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_report_deleted(report_id: str, triggered_by=None, metadata=None):
"""Publish REPORT_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.REPORT_DELETED,
entity_type='Report',
entity_id=report_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_report_submitted(report_id: str, triggered_by=None, metadata=None):
"""Publish REPORT_SUBMITTED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.REPORT_SUBMITTED,
entity_type='Report',
entity_id=report_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_report_approved(report_id: str, triggered_by=None, metadata=None):
"""Publish REPORT_APPROVED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.REPORT_APPROVED,
entity_type='Report',
entity_id=report_id,
triggered_by=triggered_by,
metadata=metadata
)
# Invoice events
async def publish_invoice_generated(invoice_id: str, triggered_by=None, metadata=None):
"""Publish INVOICE_GENERATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.INVOICE_GENERATED,
entity_type='Invoice',
entity_id=invoice_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_invoice_sent(invoice_id: str, triggered_by=None, metadata=None):
"""Publish INVOICE_SENT event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.INVOICE_SENT,
entity_type='Invoice',
entity_id=invoice_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_invoice_paid(invoice_id: str, triggered_by=None, metadata=None):
"""Publish INVOICE_PAID event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.INVOICE_PAID,
entity_type='Invoice',
entity_id=invoice_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_invoice_overdue(invoice_id: str, triggered_by=None, metadata=None):
"""Publish INVOICE_OVERDUE event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.INVOICE_OVERDUE,
entity_type='Invoice',
entity_id=invoice_id,
triggered_by=triggered_by,
metadata=metadata
)
async def publish_invoice_cancelled(invoice_id: str, triggered_by=None, metadata=None):
"""Publish INVOICE_CANCELLED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.INVOICE_CANCELLED,
entity_type='Invoice',
entity_id=invoice_id,
triggered_by=triggered_by,
metadata=metadata
)
# Service Session events
async def publish_service_session_opened(session_id: str, service_id: str, triggered_by=None):
"""Publish SERVICE_SESSION_OPENED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_SESSION_OPENED,
entity_type='ServiceSession',
entity_id=session_id,
triggered_by=triggered_by,
metadata={'service_id': service_id}
)
async def publish_service_session_closed(session_id: str, service_id: str, triggered_by=None, metadata=None):
"""Publish SERVICE_SESSION_CLOSED event"""
event_metadata = {'service_id': service_id}
if metadata:
event_metadata.update(metadata)
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_SESSION_CLOSED,
entity_type='ServiceSession',
entity_id=session_id,
triggered_by=triggered_by,
metadata=event_metadata
)
async def publish_service_session_reverted(session_id: str, service_id: str, triggered_by=None):
"""Publish SERVICE_SESSION_REVERTED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_SESSION_REVERTED,
entity_type='ServiceSession',
entity_id=session_id,
triggered_by=triggered_by,
metadata={'service_id': service_id}
)
async def publish_service_task_completed(task_id: str, service_id: str, task_name: str, triggered_by=None):
"""Publish SERVICE_TASK_COMPLETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_TASK_COMPLETED,
entity_type='TaskCompletion',
entity_id=task_id,
triggered_by=triggered_by,
metadata={'service_id': service_id, 'task_name': task_name}
)
async def publish_service_task_uncompleted(task_id: str, service_id: str, task_name: str, triggered_by=None):
"""Publish SERVICE_TASK_UNCOMPLETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SERVICE_TASK_UNCOMPLETED,
entity_type='TaskCompletion',
entity_id=task_id,
triggered_by=triggered_by,
metadata={'service_id': service_id, 'task_name': task_name}
)
# Project Session events
async def publish_project_session_opened(session_id: str, project_id: str, triggered_by=None):
"""Publish PROJECT_SESSION_OPENED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SESSION_OPENED,
entity_type='ProjectSession',
entity_id=session_id,
triggered_by=triggered_by,
metadata={'project_id': project_id}
)
async def publish_project_session_closed(session_id: str, project_id: str, triggered_by=None, metadata=None):
"""Publish PROJECT_SESSION_CLOSED event"""
event_metadata = {'project_id': project_id}
if metadata:
event_metadata.update(metadata)
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SESSION_CLOSED,
entity_type='ProjectSession',
entity_id=session_id,
triggered_by=triggered_by,
metadata=event_metadata
)
async def publish_project_session_reverted(session_id: str, project_id: str, triggered_by=None):
"""Publish PROJECT_SESSION_REVERTED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SESSION_REVERTED,
entity_type='ProjectSession',
entity_id=session_id,
triggered_by=triggered_by,
metadata={'project_id': project_id}
)
async def publish_project_task_completed(task_id: str, project_id: str, task_name: str, triggered_by=None):
"""Publish PROJECT_TASK_COMPLETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_TASK_COMPLETED,
entity_type='ProjectTaskCompletion',
entity_id=task_id,
triggered_by=triggered_by,
metadata={'project_id': project_id, 'task_name': task_name}
)
async def publish_project_task_uncompleted(task_id: str, project_id: str, task_name: str, triggered_by=None):
"""Publish PROJECT_TASK_UNCOMPLETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_TASK_UNCOMPLETED,
entity_type='ProjectTaskCompletion',
entity_id=task_id,
triggered_by=triggered_by,
metadata={'project_id': project_id, 'task_name': task_name}
)
# Punchlist events
async def publish_account_punchlist_created(punchlist_id: str, account_id: str, triggered_by=None, metadata=None):
"""Publish ACCOUNT_PUNCHLIST_CREATED event"""
meta = metadata or {}
meta['account_id'] = account_id
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_PUNCHLIST_CREATED,
entity_type='AccountPunchlist',
entity_id=punchlist_id,
triggered_by=triggered_by,
metadata=meta
)
async def publish_account_punchlist_updated(punchlist_id: str, account_id: str, triggered_by=None, metadata=None):
"""Publish ACCOUNT_PUNCHLIST_UPDATED event"""
meta = metadata or {}
meta['account_id'] = account_id
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_PUNCHLIST_UPDATED,
entity_type='AccountPunchlist',
entity_id=punchlist_id,
triggered_by=triggered_by,
metadata=meta
)
async def publish_account_punchlist_deleted(punchlist_id: str, account_id: str, triggered_by=None, metadata=None):
"""Publish ACCOUNT_PUNCHLIST_DELETED event"""
meta = metadata or {}
meta['account_id'] = account_id
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_PUNCHLIST_DELETED,
entity_type='AccountPunchlist',
entity_id=punchlist_id,
triggered_by=triggered_by,
metadata=meta
)
async def publish_project_punchlist_created(punchlist_id: str, project_id: str, triggered_by=None, metadata=None):
"""Publish PROJECT_PUNCHLIST_CREATED event"""
meta = metadata or {}
meta['project_id'] = project_id
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_PUNCHLIST_CREATED,
entity_type='ProjectPunchlist',
entity_id=punchlist_id,
triggered_by=triggered_by,
metadata=meta
)
async def publish_project_punchlist_updated(punchlist_id: str, project_id: str, triggered_by=None, metadata=None):
"""Publish PROJECT_PUNCHLIST_UPDATED event"""
meta = metadata or {}
meta['project_id'] = project_id
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_PUNCHLIST_UPDATED,
entity_type='ProjectPunchlist',
entity_id=punchlist_id,
triggered_by=triggered_by,
metadata=meta
)
async def publish_project_punchlist_deleted(punchlist_id: str, project_id: str, triggered_by=None, metadata=None):
"""Publish PROJECT_PUNCHLIST_DELETED event"""
meta = metadata or {}
meta['project_id'] = project_id
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_PUNCHLIST_DELETED,
entity_type='ProjectPunchlist',
entity_id=punchlist_id,
triggered_by=triggered_by,
metadata=meta
)
async def publish_punchlist_status_changed(punchlist_id: str, entity_type: str, old_status: str, new_status: str, triggered_by=None):
"""Publish PUNCHLIST_STATUS_CHANGED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PUNCHLIST_STATUS_CHANGED,
entity_type=entity_type,
entity_id=punchlist_id,
triggered_by=triggered_by,
metadata={'old_status': old_status, 'new_status': new_status}
)
async def publish_punchlist_priority_changed(punchlist_id: str, entity_type: str, old_priority: str, new_priority: str, triggered_by=None):
"""Publish PUNCHLIST_PRIORITY_CHANGED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PUNCHLIST_PRIORITY_CHANGED,
entity_type=entity_type,
entity_id=punchlist_id,
triggered_by=triggered_by,
metadata={'old_priority': old_priority, 'new_priority': new_priority}
)
# Session Media events
async def publish_session_image_uploaded(image_id: str, session_id: str, is_internal: bool, triggered_by=None):
"""Publish SESSION_IMAGE_UPLOADED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SESSION_IMAGE_UPLOADED,
entity_type='SessionImage',
entity_id=image_id,
triggered_by=triggered_by,
metadata={'session_id': session_id, 'is_internal': is_internal}
)
async def publish_session_image_updated(image_id: str, session_id: str, triggered_by=None, metadata=None):
"""Publish SESSION_IMAGE_UPDATED event"""
meta = metadata or {}
meta['session_id'] = session_id
return await EventPublisher.publish(
event_type=EventTypeChoices.SESSION_IMAGE_UPDATED,
entity_type='SessionImage',
entity_id=image_id,
triggered_by=triggered_by,
metadata=meta
)
async def publish_session_image_deleted(image_id: str, session_id: str, triggered_by=None):
"""Publish SESSION_IMAGE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SESSION_IMAGE_DELETED,
entity_type='SessionImage',
entity_id=image_id,
triggered_by=triggered_by,
metadata={'session_id': session_id}
)
async def publish_session_video_uploaded(video_id: str, session_id: str, is_internal: bool, triggered_by=None):
"""Publish SESSION_VIDEO_UPLOADED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SESSION_VIDEO_UPLOADED,
entity_type='SessionVideo',
entity_id=video_id,
triggered_by=triggered_by,
metadata={'session_id': session_id, 'is_internal': is_internal}
)
async def publish_session_video_updated(video_id: str, session_id: str, triggered_by=None, metadata=None):
"""Publish SESSION_VIDEO_UPDATED event"""
meta = metadata or {}
meta['session_id'] = session_id
return await EventPublisher.publish(
event_type=EventTypeChoices.SESSION_VIDEO_UPDATED,
entity_type='SessionVideo',
entity_id=video_id,
triggered_by=triggered_by,
metadata=meta
)
async def publish_session_video_deleted(video_id: str, session_id: str, triggered_by=None):
"""Publish SESSION_VIDEO_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SESSION_VIDEO_DELETED,
entity_type='SessionVideo',
entity_id=video_id,
triggered_by=triggered_by,
metadata={'session_id': session_id}
)
async def publish_session_media_internal_flagged(media_id: str, media_type: str, session_id: str, triggered_by=None):
"""Publish SESSION_MEDIA_INTERNAL_FLAGGED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SESSION_MEDIA_INTERNAL_FLAGGED,
entity_type=media_type,
entity_id=media_id,
triggered_by=triggered_by,
metadata={'session_id': session_id}
)
# Session Notes events
async def publish_session_note_created(note_id: str, session_id: str, triggered_by=None):
"""Publish SESSION_NOTE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SESSION_NOTE_CREATED,
entity_type='SessionNote',
entity_id=note_id,
triggered_by=triggered_by,
metadata={'session_id': session_id}
)
async def publish_session_note_updated(note_id: str, session_id: str, triggered_by=None):
"""Publish SESSION_NOTE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SESSION_NOTE_UPDATED,
entity_type='SessionNote',
entity_id=note_id,
triggered_by=triggered_by,
metadata={'session_id': session_id}
)
async def publish_session_note_deleted(note_id: str, session_id: str, triggered_by=None):
"""Publish SESSION_NOTE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SESSION_NOTE_DELETED,
entity_type='SessionNote',
entity_id=note_id,
triggered_by=triggered_by,
metadata={'session_id': session_id}
)
# Customer Address & Contact events
async def publish_customer_address_created(address_id: str, customer_id: str, triggered_by=None):
"""Publish CUSTOMER_ADDRESS_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_ADDRESS_CREATED,
entity_type='CustomerAddress',
entity_id=address_id,
triggered_by=triggered_by,
metadata={'customer_id': customer_id}
)
async def publish_customer_address_updated(address_id: str, customer_id: str, triggered_by=None):
"""Publish CUSTOMER_ADDRESS_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_ADDRESS_UPDATED,
entity_type='CustomerAddress',
entity_id=address_id,
triggered_by=triggered_by,
metadata={'customer_id': customer_id}
)
async def publish_customer_address_deleted(address_id: str, customer_id: str, triggered_by=None):
"""Publish CUSTOMER_ADDRESS_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_ADDRESS_DELETED,
entity_type='CustomerAddress',
entity_id=address_id,
triggered_by=triggered_by,
metadata={'customer_id': customer_id}
)
async def publish_customer_contact_created(contact_id: str, customer_id: str, triggered_by=None):
"""Publish CUSTOMER_CONTACT_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_CONTACT_CREATED,
entity_type='CustomerContact',
entity_id=contact_id,
triggered_by=triggered_by,
metadata={'customer_id': customer_id}
)
async def publish_customer_contact_updated(contact_id: str, customer_id: str, triggered_by=None):
"""Publish CUSTOMER_CONTACT_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_CONTACT_UPDATED,
entity_type='CustomerContact',
entity_id=contact_id,
triggered_by=triggered_by,
metadata={'customer_id': customer_id}
)
async def publish_customer_contact_deleted(contact_id: str, customer_id: str, triggered_by=None):
"""Publish CUSTOMER_CONTACT_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.CUSTOMER_CONTACT_DELETED,
entity_type='CustomerContact',
entity_id=contact_id,
triggered_by=triggered_by,
metadata={'customer_id': customer_id}
)
# Account Address & Contact events
async def publish_account_address_created(address_id: str, account_id: str, triggered_by=None):
"""Publish ACCOUNT_ADDRESS_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_ADDRESS_CREATED,
entity_type='AccountAddress',
entity_id=address_id,
triggered_by=triggered_by,
metadata={'account_id': account_id}
)
async def publish_account_address_updated(address_id: str, account_id: str, triggered_by=None):
"""Publish ACCOUNT_ADDRESS_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_ADDRESS_UPDATED,
entity_type='AccountAddress',
entity_id=address_id,
triggered_by=triggered_by,
metadata={'account_id': account_id}
)
async def publish_account_address_deleted(address_id: str, account_id: str, triggered_by=None):
"""Publish ACCOUNT_ADDRESS_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_ADDRESS_DELETED,
entity_type='AccountAddress',
entity_id=address_id,
triggered_by=triggered_by,
metadata={'account_id': account_id}
)
async def publish_account_contact_created(contact_id: str, account_id: str, triggered_by=None):
"""Publish ACCOUNT_CONTACT_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_CONTACT_CREATED,
entity_type='AccountContact',
entity_id=contact_id,
triggered_by=triggered_by,
metadata={'account_id': account_id}
)
async def publish_account_contact_updated(contact_id: str, account_id: str, triggered_by=None):
"""Publish ACCOUNT_CONTACT_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_CONTACT_UPDATED,
entity_type='AccountContact',
entity_id=contact_id,
triggered_by=triggered_by,
metadata={'account_id': account_id}
)
async def publish_account_contact_deleted(contact_id: str, account_id: str, triggered_by=None):
"""Publish ACCOUNT_CONTACT_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.ACCOUNT_CONTACT_DELETED,
entity_type='AccountContact',
entity_id=contact_id,
triggered_by=triggered_by,
metadata={'account_id': account_id}
)
# Scope events
async def publish_scope_created(scope_id: str, account_id: str, triggered_by=None):
"""Publish SCOPE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SCOPE_CREATED,
entity_type='Scope',
entity_id=scope_id,
triggered_by=triggered_by,
metadata={'account_id': account_id}
)
async def publish_scope_updated(scope_id: str, account_id: str, triggered_by=None):
"""Publish SCOPE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SCOPE_UPDATED,
entity_type='Scope',
entity_id=scope_id,
triggered_by=triggered_by,
metadata={'account_id': account_id}
)
async def publish_scope_deleted(scope_id: str, account_id: str, triggered_by=None):
"""Publish SCOPE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SCOPE_DELETED,
entity_type='Scope',
entity_id=scope_id,
triggered_by=triggered_by,
metadata={'account_id': account_id}
)
async def publish_area_created(area_id: str, scope_id: str, triggered_by=None):
"""Publish AREA_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.AREA_CREATED,
entity_type='Area',
entity_id=area_id,
triggered_by=triggered_by,
metadata={'scope_id': scope_id}
)
async def publish_area_updated(area_id: str, scope_id: str, triggered_by=None):
"""Publish AREA_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.AREA_UPDATED,
entity_type='Area',
entity_id=area_id,
triggered_by=triggered_by,
metadata={'scope_id': scope_id}
)
async def publish_area_deleted(area_id: str, scope_id: str, triggered_by=None):
"""Publish AREA_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.AREA_DELETED,
entity_type='Area',
entity_id=area_id,
triggered_by=triggered_by,
metadata={'scope_id': scope_id}
)
async def publish_task_created(task_id: str, area_id: str, triggered_by=None):
"""Publish TASK_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.TASK_CREATED,
entity_type='Task',
entity_id=task_id,
triggered_by=triggered_by,
metadata={'area_id': area_id}
)
async def publish_task_updated(task_id: str, area_id: str, triggered_by=None):
"""Publish TASK_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.TASK_UPDATED,
entity_type='Task',
entity_id=task_id,
triggered_by=triggered_by,
metadata={'area_id': area_id}
)
async def publish_task_deleted(task_id: str, area_id: str, triggered_by=None):
"""Publish TASK_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.TASK_DELETED,
entity_type='Task',
entity_id=task_id,
triggered_by=triggered_by,
metadata={'area_id': area_id}
)
async def publish_task_completion_recorded(completion_id: str, task_id: str, service_id: str, triggered_by=None):
"""Publish TASK_COMPLETION_RECORDED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.TASK_COMPLETION_RECORDED,
entity_type='TaskCompletion',
entity_id=completion_id,
triggered_by=triggered_by,
metadata={'task_id': task_id, 'service_id': service_id}
)
# Scope Template events
async def publish_scope_template_created(template_id: str, triggered_by=None):
"""Publish SCOPE_TEMPLATE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SCOPE_TEMPLATE_CREATED,
entity_type='ScopeTemplate',
entity_id=template_id,
triggered_by=triggered_by,
metadata={}
)
async def publish_scope_template_updated(template_id: str, triggered_by=None):
"""Publish SCOPE_TEMPLATE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SCOPE_TEMPLATE_UPDATED,
entity_type='ScopeTemplate',
entity_id=template_id,
triggered_by=triggered_by,
metadata={}
)
async def publish_scope_template_deleted(template_id: str, triggered_by=None):
"""Publish SCOPE_TEMPLATE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SCOPE_TEMPLATE_DELETED,
entity_type='ScopeTemplate',
entity_id=template_id,
triggered_by=triggered_by,
metadata={}
)
async def publish_scope_template_instantiated(scope_id: str, template_id: str, account_id: str, triggered_by=None):
"""Publish SCOPE_TEMPLATE_INSTANTIATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.SCOPE_TEMPLATE_INSTANTIATED,
entity_type='Scope',
entity_id=scope_id,
triggered_by=triggered_by,
metadata={'template_id': template_id, 'account_id': account_id}
)
async def publish_area_template_created(template_id: str, scope_template_id: str, triggered_by=None):
"""Publish AREA_TEMPLATE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.AREA_TEMPLATE_CREATED,
entity_type='AreaTemplate',
entity_id=template_id,
triggered_by=triggered_by,
metadata={'scope_template_id': scope_template_id}
)
async def publish_area_template_updated(template_id: str, scope_template_id: str, triggered_by=None):
"""Publish AREA_TEMPLATE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.AREA_TEMPLATE_UPDATED,
entity_type='AreaTemplate',
entity_id=template_id,
triggered_by=triggered_by,
metadata={'scope_template_id': scope_template_id}
)
async def publish_area_template_deleted(template_id: str, scope_template_id: str, triggered_by=None):
"""Publish AREA_TEMPLATE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.AREA_TEMPLATE_DELETED,
entity_type='AreaTemplate',
entity_id=template_id,
triggered_by=triggered_by,
metadata={'scope_template_id': scope_template_id}
)
async def publish_task_template_created(template_id: str, area_template_id: str, triggered_by=None):
"""Publish TASK_TEMPLATE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.TASK_TEMPLATE_CREATED,
entity_type='TaskTemplate',
entity_id=template_id,
triggered_by=triggered_by,
metadata={'area_template_id': area_template_id}
)
async def publish_task_template_updated(template_id: str, area_template_id: str, triggered_by=None):
"""Publish TASK_TEMPLATE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.TASK_TEMPLATE_UPDATED,
entity_type='TaskTemplate',
entity_id=template_id,
triggered_by=triggered_by,
metadata={'area_template_id': area_template_id}
)
async def publish_task_template_deleted(template_id: str, area_template_id: str, triggered_by=None):
"""Publish TASK_TEMPLATE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.TASK_TEMPLATE_DELETED,
entity_type='TaskTemplate',
entity_id=template_id,
triggered_by=triggered_by,
metadata={'area_template_id': area_template_id}
)
# Project Scope events
async def publish_project_scope_created(scope_id: str, project_id: str, triggered_by=None):
"""Publish PROJECT_SCOPE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SCOPE_CREATED,
entity_type='ProjectScope',
entity_id=scope_id,
triggered_by=triggered_by,
metadata={'project_id': project_id}
)
async def publish_project_scope_updated(scope_id: str, project_id: str, triggered_by=None):
"""Publish PROJECT_SCOPE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SCOPE_UPDATED,
entity_type='ProjectScope',
entity_id=scope_id,
triggered_by=triggered_by,
metadata={'project_id': project_id}
)
async def publish_project_scope_deleted(scope_id: str, project_id: str, triggered_by=None):
"""Publish PROJECT_SCOPE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SCOPE_DELETED,
entity_type='ProjectScope',
entity_id=scope_id,
triggered_by=triggered_by,
metadata={'project_id': project_id}
)
async def publish_project_scope_category_created(category_id: str, scope_id: str, triggered_by=None):
"""Publish PROJECT_SCOPE_CATEGORY_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SCOPE_CATEGORY_CREATED,
entity_type='ProjectScopeCategory',
entity_id=category_id,
triggered_by=triggered_by,
metadata={'scope_id': scope_id}
)
async def publish_project_scope_category_updated(category_id: str, scope_id: str, triggered_by=None):
"""Publish PROJECT_SCOPE_CATEGORY_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SCOPE_CATEGORY_UPDATED,
entity_type='ProjectScopeCategory',
entity_id=category_id,
triggered_by=triggered_by,
metadata={'scope_id': scope_id}
)
async def publish_project_scope_category_deleted(category_id: str, scope_id: str, triggered_by=None):
"""Publish PROJECT_SCOPE_CATEGORY_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SCOPE_CATEGORY_DELETED,
entity_type='ProjectScopeCategory',
entity_id=category_id,
triggered_by=triggered_by,
metadata={'scope_id': scope_id}
)
async def publish_project_scope_task_created(task_id: str, category_id: str, triggered_by=None):
"""Publish PROJECT_SCOPE_TASK_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SCOPE_TASK_CREATED,
entity_type='ProjectScopeTask',
entity_id=task_id,
triggered_by=triggered_by,
metadata={'category_id': category_id}
)
async def publish_project_scope_task_updated(task_id: str, category_id: str, triggered_by=None):
"""Publish PROJECT_SCOPE_TASK_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SCOPE_TASK_UPDATED,
entity_type='ProjectScopeTask',
entity_id=task_id,
triggered_by=triggered_by,
metadata={'category_id': category_id}
)
async def publish_project_scope_task_deleted(task_id: str, category_id: str, triggered_by=None):
"""Publish PROJECT_SCOPE_TASK_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SCOPE_TASK_DELETED,
entity_type='ProjectScopeTask',
entity_id=task_id,
triggered_by=triggered_by,
metadata={'category_id': category_id}
)
async def publish_project_scope_template_instantiated(scope_id: str, template_id: str, project_id: str, triggered_by=None):
"""Publish PROJECT_SCOPE_TEMPLATE_INSTANTIATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.PROJECT_SCOPE_TEMPLATE_INSTANTIATED,
entity_type='ProjectScope',
entity_id=scope_id,
triggered_by=triggered_by,
metadata={'template_id': template_id, 'project_id': project_id}
)
# Labor & Revenue events
async def publish_labor_rate_created(rate_id: str, triggered_by=None):
"""Publish LABOR_RATE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.LABOR_RATE_CREATED,
entity_type='LaborRate',
entity_id=rate_id,
triggered_by=triggered_by,
metadata={}
)
async def publish_labor_rate_updated(rate_id: str, triggered_by=None):
"""Publish LABOR_RATE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.LABOR_RATE_UPDATED,
entity_type='LaborRate',
entity_id=rate_id,
triggered_by=triggered_by,
metadata={}
)
async def publish_labor_rate_deleted(rate_id: str, triggered_by=None):
"""Publish LABOR_RATE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.LABOR_RATE_DELETED,
entity_type='LaborRate',
entity_id=rate_id,
triggered_by=triggered_by,
metadata={}
)
async def publish_revenue_rate_created(rate_id: str, triggered_by=None):
"""Publish REVENUE_RATE_CREATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.REVENUE_RATE_CREATED,
entity_type='RevenueRate',
entity_id=rate_id,
triggered_by=triggered_by,
metadata={}
)
async def publish_revenue_rate_updated(rate_id: str, triggered_by=None):
"""Publish REVENUE_RATE_UPDATED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.REVENUE_RATE_UPDATED,
entity_type='RevenueRate',
entity_id=rate_id,
triggered_by=triggered_by,
metadata={}
)
async def publish_revenue_rate_deleted(rate_id: str, triggered_by=None):
"""Publish REVENUE_RATE_DELETED event"""
return await EventPublisher.publish(
event_type=EventTypeChoices.REVENUE_RATE_DELETED,
entity_type='RevenueRate',
entity_id=rate_id,
triggered_by=triggered_by,
metadata={}
)