# Copyright (c) 2025 Patrick Motsch # All rights reserved. """ Notification model for in-app notifications. Supports actionable notifications (e.g., invitation accept/decline). """ import uuid from typing import Optional, List from enum import Enum from pydantic import BaseModel, Field, ConfigDict from modules.datamodels.datamodelBase import PowerOnModel from modules.shared.i18nRegistry import i18nModel class NotificationType(str, Enum): """Types of notifications""" INVITATION = "invitation" # Einladung zu Mandat/Feature SYSTEM = "system" # System-Nachrichten WORKFLOW = "workflow" # Workflow-Status Updates MENTION = "mention" # Erwähnung in Chat/Kommentar class NotificationStatus(str, Enum): """Status of a notification""" UNREAD = "unread" # Noch nicht gelesen READ = "read" # Gelesen ACTIONED = "actioned" # Aktion wurde durchgeführt DISMISSED = "dismissed" # Verworfen/Geschlossen @i18nModel("Benachrichtigungs-Aktion") class NotificationAction(BaseModel): """Possible action for a notification""" actionId: str = Field( description="Unique identifier for the action (e.g., 'accept', 'decline')", json_schema_extra={"label": "Aktions-ID"}, ) label: str = Field( description="Display label for the action button", json_schema_extra={"label": "Bezeichnung"}, ) style: str = Field( default="default", description="Button style: 'primary', 'danger', 'default'", json_schema_extra={"label": "Stil"}, ) @i18nModel("Benachrichtigung") class UserNotification(PowerOnModel): """ In-app notification for a user. Supports actionable notifications with accept/decline buttons. """ id: str = Field( default_factory=lambda: str(uuid.uuid4()), description="Unique ID of the notification", json_schema_extra={"label": "ID", "frontend_type": "text", "frontend_readonly": True, "frontend_required": False} ) userId: str = Field( description="Target user ID for this notification", json_schema_extra={ "label": "Benutzer", "frontend_type": "text", "frontend_readonly": True, "frontend_required": True, "fk_target": {"db": "poweron_app", "table": "User"}, }, ) type: NotificationType = Field( default=NotificationType.SYSTEM, description="Type of notification", json_schema_extra={ "label": "Typ", "frontend_type": "select", "frontend_readonly": True, "frontend_required": True, "frontend_options": [ {"value": "invitation", "label": "Einladung"}, {"value": "system", "label": "System"}, {"value": "workflow", "label": "Workflow"}, {"value": "mention", "label": "Erwähnung"} ] } ) status: NotificationStatus = Field( default=NotificationStatus.UNREAD, description="Current status of the notification", json_schema_extra={ "label": "Status", "frontend_type": "select", "frontend_readonly": True, "frontend_required": False, "frontend_options": [ {"value": "unread", "label": "Ungelesen"}, {"value": "read", "label": "Gelesen"}, {"value": "actioned", "label": "Bearbeitet"}, {"value": "dismissed", "label": "Verworfen"} ] } ) title: str = Field( description="Notification title", json_schema_extra={"label": "Titel", "frontend_type": "text", "frontend_readonly": True, "frontend_required": True} ) message: str = Field( description="Notification message/body", json_schema_extra={"label": "Nachricht", "frontend_type": "textarea", "frontend_readonly": True, "frontend_required": True} ) icon: Optional[str] = Field( default=None, description="Optional icon identifier (e.g., 'mail', 'warning', 'info')", json_schema_extra={"label": "Symbol", "frontend_type": "text", "frontend_readonly": True, "frontend_required": False} ) referenceType: Optional[str] = Field( default=None, description="Type of referenced object (e.g., 'Invitation', 'Workflow')", json_schema_extra={"label": "Referenz-Typ", "frontend_type": "text", "frontend_readonly": True, "frontend_required": False} ) referenceId: Optional[str] = Field( default=None, description="ID of referenced object", json_schema_extra={"label": "Referenz-ID", "frontend_type": "text", "frontend_readonly": True, "frontend_required": False} ) actions: Optional[List[NotificationAction]] = Field( default=None, description="List of possible actions for this notification", json_schema_extra={"label": "Aktionen", "frontend_type": "json", "frontend_readonly": True, "frontend_required": False} ) actionTaken: Optional[str] = Field( default=None, description="Which action was taken (actionId)", json_schema_extra={"label": "Durchgefuehrte Aktion", "frontend_type": "text", "frontend_readonly": True, "frontend_required": False} ) actionResult: Optional[str] = Field( default=None, description="Result message from the action", json_schema_extra={"label": "Aktions-Ergebnis", "frontend_type": "textarea", "frontend_readonly": True, "frontend_required": False} ) readAt: Optional[float] = Field( default=None, description="When the notification was read (UTC timestamp)", json_schema_extra={"label": "Gelesen am", "frontend_type": "timestamp", "frontend_readonly": True, "frontend_required": False} ) actionedAt: Optional[float] = Field( default=None, description="When action was taken (UTC timestamp)", json_schema_extra={"label": "Bearbeitet am", "frontend_type": "timestamp", "frontend_readonly": True, "frontend_required": False} ) expiresAt: Optional[float] = Field( default=None, description="When the notification expires (optional, UTC timestamp)", json_schema_extra={"label": "Gueltig bis", "frontend_type": "timestamp", "frontend_readonly": True, "frontend_required": False} ) model_config = ConfigDict(use_enum_values=True)