from onegov.core.orm import Base
from onegov.core.orm.mixins import content_property
from onegov.core.orm.mixins import dict_markup_property
from onegov.core.orm.mixins import dict_property
from onegov.core.orm.mixins import ContentMixin
from onegov.core.orm.mixins import TimestampMixin
from onegov.core.orm.types import UTCDateTime
from onegov.core.orm.types import UUID
from onegov.file import AssociatedFiles
from onegov.file import NamedFile
from onegov.landsgemeinde import _
from onegov.landsgemeinde.models.file import LandsgemeindeFile
from onegov.landsgemeinde.models.votum import Votum
from onegov.landsgemeinde.models.mixins import TimestampedVideoMixin
from onegov.search import ORMSearchable
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import Enum
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import Text
from sqlalchemy.orm import relationship
from uuid import uuid4
from typing import TYPE_CHECKING
if TYPE_CHECKING:
import uuid
from datetime import date as date_t
from onegov.landsgemeinde.models import Assembly
from translationstring import TranslationString
from typing import Literal
from typing import TypeAlias
[docs]
AgendaItemState: TypeAlias = Literal['scheduled', 'ongoing', 'completed']
[docs]
STATES: dict['AgendaItemState', 'TranslationString'] = {
'scheduled': _('scheduled'),
'ongoing': _('ongoing'),
'completed': _('completed')
}
[docs]
class AgendaItem(
Base, ContentMixin, TimestampMixin, AssociatedFiles, ORMSearchable,
TimestampedVideoMixin
):
[docs]
__tablename__ = 'landsgemeinde_agenda_items'
[docs]
es_properties = {
'title': {'type': 'text'},
'overview': {'type': 'localized_html'},
'text': {'type': 'localized_html'},
'resolution': {'type': 'localized_html'},
}
#: the internal id of the agenda item
[docs]
id: 'Column[uuid.UUID]' = Column(
UUID, # type:ignore[arg-type]
primary_key=True,
default=uuid4
)
#: the external id of the agenda item
[docs]
number: 'Column[int]' = Column(Integer, nullable=False)
#: the state of the agenda item
[docs]
state: 'Column[AgendaItemState]' = Column(
Enum(*STATES.keys(), name='agenda_item_state'), # type:ignore
nullable=False
)
#: True if the item has been declared irrelevant
[docs]
irrelevant: 'Column[bool]' = Column(Boolean, nullable=False, default=False)
#: True if the item has been tacitly accepted
[docs]
tacitly_accepted: 'Column[bool]' = Column(
Boolean,
nullable=False,
default=False
)
#: the assembly this agenda item belongs to
[docs]
assembly_id: 'Column[uuid.UUID]' = Column(
UUID, # type:ignore[arg-type]
ForeignKey(
'landsgemeinde_assemblies.id',
onupdate='CASCADE',
ondelete='CASCADE'
),
nullable=False
)
[docs]
assembly: 'relationship[Assembly]' = relationship(
'Assembly',
back_populates='agenda_items',
)
#: Title of the agenda item (not translated)
[docs]
title: 'Column[str]' = Column(Text, nullable=False, default=lambda: '')
#: The memorial of the assembly
[docs]
memorial_pdf = NamedFile(cls=LandsgemeindeFile)
#: The page number on which the agenda item can be found
[docs]
memorial_page: dict_property[int | None] = content_property()
#: The overview (text) over the agenda item
[docs]
overview = dict_markup_property('content')
#: The main content (text) of the agenda item
[docs]
text = dict_markup_property('content')
#: The resolution (text) of the agenda item
[docs]
resolution = dict_markup_property('content')
#: The resolution (tags) of the agenda item
#: An agenda item contains n vota
[docs]
vota: 'relationship[list[Votum]]' = relationship(
Votum,
cascade='all, delete-orphan',
back_populates='agenda_item',
order_by='Votum.number',
)
#: The timestamp of the last modification
[docs]
last_modified = Column(UTCDateTime)
[docs]
def stamp(self) -> None:
self.last_modified = self.timestamp()
@property
[docs]
def date(self) -> 'date_t':
return self.assembly.date
@property
[docs]
def title_parts(self) -> list[str]:
return [
stripped_line
for line in (self.title or '').splitlines()
if (stripped_line := line.strip())
]