Source code for feriennet.models.notification_template

from markupsafe import Markup
from onegov.activity import BookingCollection, InvoiceCollection
from onegov.core.orm import Base
from onegov.core.orm.mixins import ContentMixin, TimestampMixin
from onegov.core.orm.types import UUID, UTCDateTime
from onegov.feriennet import _
from onegov.feriennet.collections import VacationActivityCollection
from sqlalchemy import Column, Text
from uuid import uuid4


from typing import TYPE_CHECKING
if TYPE_CHECKING:
    import uuid
    from collections.abc import Callable
    from datetime import datetime
    from onegov.activity.models import Period
    from onegov.feriennet.request import FeriennetRequest
    from typing import Protocol
    from typing import Self

[docs] class BoundCallable(Protocol):
[docs] __doc__: str
[docs] def __call__(self) -> str: ...
[docs] MISSING = object()
[docs] TOKEN = '[{}]' # nosec: B105
[docs] class NotificationTemplate(Base, ContentMixin, TimestampMixin):
[docs] __tablename__ = 'notification_templates'
#: holds the selected period id (not stored in the database)
[docs] period_id: 'uuid.UUID | None' = None
#: The public id of the notification template
[docs] id: 'Column[uuid.UUID]' = Column( UUID, # type:ignore[arg-type] primary_key=True, default=uuid4 )
#: The subject of the notification
[docs] subject: 'Column[str]' = Column(Text, nullable=False, unique=True)
#: The template text in html, fully rendered html content
[docs] text: 'Column[str]' = Column(Text, nullable=False)
#: The date the notification was last sent
[docs] last_sent: 'Column[datetime | None]' = Column(UTCDateTime, nullable=True)
[docs] def for_period(self, period: 'Period') -> 'Self': """ Implements the required interface for the 'periods' macro in onegov.feriennet. """ self.period_id = period.id return self
[docs] class TemplateVariables:
[docs] bound: dict[str, 'BoundCallable']
[docs] expanded: dict[str, str]
def __init__( self, request: 'FeriennetRequest', period: 'Period | None' ) -> None:
[docs] self.request = request
[docs] self.period = period
self.expanded = {} self.bound = {} self.bind( _('Period'), _('Title of the period.'), self.period_title, ) self.bind( _('Invoices'), _("Link to the user's invoices."), self.invoices_link, ) self.bind( _('Bookings'), _("Link to the user's bookings."), self.bookings_link ) self.bind( _('Activities'), _('Link to the activities.'), self.activities_link ) self.bind( _('Homepage'), _('Link to the homepage.'), self.homepage_link )
[docs] def bind( self, name: str, description: str, method: 'Callable[[], str]' ) -> None: assert hasattr(method, '__func__') token = TOKEN.format(self.request.translate(name)) method.__func__.__doc__ = self.request.translate(description) self.bound[token] = method
[docs] def render(self, text: Markup) -> Markup: """ Replaces the tokens with the corresponding internal links. """ for token, method in self.bound.items(): if token in text: text = text.replace(token, method()) return text
[docs] def period_title(self) -> str: return self.period.title if self.period else ''