from __future__ import annotations
from functools import cached_property
from onegov.activity import Activity, ActivityCollection, Occasion
from onegov.activity import PublicationRequestCollection
from onegov.activity.models import DAYS
from onegov.core.templates import render_macro
from onegov.feriennet import _
from onegov.core.elements import Link, Confirm, Intercooler
from onegov.org.models.extensions import CoordinatesExtension
from onegov.org.models.ticket import OrgTicketMixin
from onegov.search import SearchableContent
from onegov.ticket import handlers, Handler, Ticket
from uuid import UUID
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Iterator, Sequence
from markupsafe import Markup
from onegov.activity.models import PublicationRequest
from onegov.feriennet.request import FeriennetRequest
[docs]
class VacationActivity(Activity, CoordinatesExtension, SearchableContent):
[docs]
__mapper_args__ = {'polymorphic_identity': 'vacation'}
[docs]
fts_type_title = _('Activities')
[docs]
fts_title_property = 'title'
[docs]
fts_properties = {
'title': {'type': 'localized', 'weight': 'A'},
'lead': {'type': 'localized', 'weight': 'B'},
'text': {'type': 'localized', 'weight': 'C'},
'organizer_name': {'type': 'text', 'weight': 'B'},
'organization_text': {'type': 'text', 'weight': 'B'},
'organizer_details_text': {'type': 'text', 'weight': 'D'}
}
@property
[docs]
def fts_public(self) -> bool:
return self.state == 'accepted'
@property
[docs]
def fts_skip(self) -> bool:
return self.state == 'preview'
@property
[docs]
def organizer_name(self) -> str:
if self.user.realname:
return self.user.realname
return self.user.username
@property
[docs]
def organization_text(self) -> str:
organization_keys = (
'organisation',
'address',
'zip_code',
'place',
'email',
'phone',
'website',
)
if not self.user.data:
return ''
return ' '.join(
value
for key in organization_keys
if (value := self.user.data.get(key))
)
@property
[docs]
def organizer_details_text(self) -> str:
details_keys = (
'emergency',
'bank_account',
'bank_beneficiary',
)
if not self.user.data:
return ''
return ' '.join(
value
for key in details_keys
if (value := self.user.data.get(key))
)
[docs]
class ActivityTicket(OrgTicketMixin, Ticket):
[docs]
__mapper_args__ = {'polymorphic_identity': 'FER'}
[docs]
def reference_group(
self,
request: FeriennetRequest # type:ignore[override]
) -> str:
return self.handler.title
@handlers.registered_handler('FER')
[docs]
class VacationActivityHandler(Handler):
[docs]
handler_title = _('Activities')
[docs]
code_title = _('Activities')
@cached_property
[docs]
def collection(self) -> PublicationRequestCollection:
return PublicationRequestCollection(self.session)
@cached_property
[docs]
def activity(self) -> Activity | None:
if self.publication_request is None:
return None
return self.publication_request.activity
@cached_property
[docs]
def publication_request(self) -> PublicationRequest | None:
return self.collection.by_id(UUID(self.id))
@property
[docs]
def deleted(self) -> bool:
return self.publication_request is None
@property
[docs]
def email(self) -> str:
return self.activity.username if self.activity else ''
@property
[docs]
def title(self) -> str:
return self.activity.title if self.activity else ''
@property
[docs]
def subtitle(self) -> str | None:
if self.publication_request is None:
return None
return self.publication_request.period.title
@property
[docs]
def group(self) -> str:
return _('Activity')
@property
[docs]
def extra_data(self) -> Sequence[str]:
return ()
@property
[docs]
def undecided(self) -> bool:
if self.deleted:
return False
assert self.activity is not None
return self.activity.state == 'proposed'
@cached_property
[docs]
def ticket_deletable(self) -> bool:
if super().ticket_deletable:
if self.activity is not None:
return self.activity.state != 'archived'
return True
return False
[docs]
def get_summary(
self,
request: FeriennetRequest # type:ignore[override]
) -> Markup:
assert self.publication_request is not None
assert self.activity is not None
from onegov.feriennet.layout import DefaultLayout
layout = DefaultLayout(self.activity, request)
ac = ActivityCollection(request.session)
activities = ac.by_username(self.activity.username)
return render_macro(
layout.macros['activity_ticket_summary'], request, {
'activity': self.activity,
'layout': layout,
'show_ticket_panel': False,
'ticket': self.ticket,
'is_first': activities.count() == 1,
'period': self.publication_request.period
}
)
[docs]
def get_period_bound_links(
self,
request: FeriennetRequest
) -> Iterator[Link]:
if self.activity is None:
return
if self.activity.state in ('proposed', 'archived'):
yield Link(
text=_('Publish'),
url=request.link(self.activity, name='accept'),
attrs={'class': 'accept-activity'},
traits=(
Confirm(
_('Do you really want to publish this activity?'),
_('This cannot be undone.'),
_('Publish Activity'),
_('Cancel')
),
Intercooler(
request_method='POST',
redirect_after=request.url
)
)
)
if self.activity.state == 'accepted':
yield Link(
text=_('Archive'),
url=request.link(self.activity, name='archive'),
attrs={'class': 'archive-activity'},
traits=(
Confirm(
_('Do you really want to archive this activity?'),
_(
'The activity will be made private as a result.'
),
_('Archive Activity'),
_('Cancel')
),
Intercooler(
request_method='POST',
redirect_after=request.url
)
)
)
[docs]
def get_links( # type:ignore[override]
self,
request: FeriennetRequest # type:ignore[override]
) -> list[Link]:
links = list(self.get_period_bound_links(request))
links.append(Link(
text=_('Show activity'),
url=request.return_here(request.link(self.activity)),
attrs={'class': 'show-activity'}
))
return links