Source code for pas.models.parliamentarian

from datetime import date
from onegov.core.orm import Base
from onegov.core.orm.mixins import ContentMixin
from onegov.core.orm.mixins import TimestampMixin
from onegov.core.orm.types import UUID
from onegov.file import AssociatedFiles
from onegov.file import NamedFile
from onegov.pas import _
from onegov.search import ORMSearchable
from sqlalchemy import Column, or_
from sqlalchemy import Date
from sqlalchemy import Enum
from sqlalchemy import Text
from sqlalchemy.orm import relationship
from uuid import uuid4


from typing import TYPE_CHECKING
if TYPE_CHECKING:
    import uuid
    from onegov.pas.models.attendence import Attendence
    from onegov.pas.models import ParliamentarianRole
    from sqlalchemy.orm import Session
    from onegov.pas.models.commission_membership import CommissionMembership
    from onegov.pas.models.party import Party
    from typing import Literal
    from typing import TypeAlias

[docs] Gender: TypeAlias = Literal[ 'male', 'female', ]
ShippingMethod: TypeAlias = Literal[ 'a', 'plus', 'registered', 'confidential', 'personal', ]
[docs] GENDERS: dict['Gender', str] = { 'male': _('male'), 'female': _('female'), }
[docs] SHIPPING_METHODS: dict['ShippingMethod', str] = { 'a': _('A mail'), 'plus': _('A mail plus'), 'registered': _('registered'), 'confidential': _('confidential'), 'personal': _('personal / confidential') }
[docs] class Parliamentarian( Base, ContentMixin, TimestampMixin, AssociatedFiles, ORMSearchable ):
[docs] __tablename__ = 'pas_parliamentarians'
[docs] es_public = False
[docs] es_properties = { 'first_name': {'type': 'text'}, 'last_name': {'type': 'text'}, }
@property
[docs] def es_suggestion(self) -> tuple[str, ...]: return ( f'{self.first_name} {self.last_name}', f'{self.last_name} {self.first_name}' )
@property
[docs] def title(self) -> str: return f'{self.first_name} {self.last_name}'
#: Internal ID
[docs] id: 'Column[uuid.UUID]' = Column( UUID, # type:ignore[arg-type] primary_key=True, default=uuid4 )
#: The first name
[docs] first_name: 'Column[str]' = Column( Text, nullable=False )
#: The last name
[docs] last_name: 'Column[str]' = Column( Text, nullable=False )
#: The personnel number
[docs] personnel_number: 'Column[str|None]' = Column( Text, nullable=True )
#: The contract number
[docs] contract_number: 'Column[str|None]' = Column( Text, nullable=True )
#: The gender value
[docs] gender: 'Column[Gender]' = Column( Enum( *GENDERS.keys(), # type:ignore[arg-type] name='pas_gender' ), nullable=False, default='male' )
#: The gender as translated text @property
[docs] def gender_label(self) -> str: return GENDERS.get(self.gender, '')
@property
[docs] def formal_greeting(self) -> str: """Returns the formal German greeting based on gender.""" if self.gender == 'female': return 'Frau ' + self.first_name + ' ' + self.last_name return 'Herr' + self.first_name + ' ' + self.last_name
#: The shipping method value
[docs] shipping_method: 'Column[ShippingMethod]' = Column( Enum( *SHIPPING_METHODS.keys(), # type:ignore[arg-type] name='pas_shipping_methods' ), nullable=False, default='a' )
#: The shipping method as translated text @property
[docs] def shipping_method_label(self) -> str: return SHIPPING_METHODS.get(self.shipping_method, '')
#: The shipping address
[docs] shipping_address: 'Column[str|None]' = Column( Text, nullable=True )
#: The shipping address addition
[docs] shipping_address_addition: 'Column[str|None]' = Column( Text, nullable=True )
#: The shipping address zip code
[docs] shipping_address_zip_code: 'Column[str|None]' = Column( Text, nullable=True )
#: The shipping address city
[docs] shipping_address_city: 'Column[str|None]' = Column( Text, nullable=True )
#: The private address
[docs] private_address: 'Column[str|None]' = Column( Text, nullable=True )
#: The private address addition
[docs] private_address_addition: 'Column[str|None]' = Column( Text, nullable=True )
#: The private address zip code
[docs] private_address_zip_code: 'Column[str|None]' = Column( Text, nullable=True )
#: The private address city
[docs] private_address_city: 'Column[str|None]' = Column( Text, nullable=True )
#: The date of birth
[docs] date_of_birth: 'Column[date|None]' = Column( Date, nullable=True )
#: The date of death
[docs] date_of_death: 'Column[date|None]' = Column( Date, nullable=True )
#: The place of origin
[docs] place_of_origin: 'Column[str|None]' = Column( Text, nullable=True )
#: The occupation
[docs] occupation: 'Column[str|None]' = Column( Text, nullable=True )
#: The academic title
[docs] academic_title: 'Column[str|None]' = Column( Text, nullable=True )
#: The salutation
[docs] salutation: 'Column[str|None]' = Column( Text, nullable=True )
#: The salutation used in the address
[docs] salutation_for_address: 'Column[str|None]' = Column( Text, nullable=True )
#: The salutation used for letters
[docs] salutation_for_letter: 'Column[str|None]' = Column( Text, nullable=True )
#: How bills should be delivered
[docs] forwarding_of_bills: 'Column[str|None]' = Column( Text, nullable=True )
#: The private phone number
[docs] phone_private: 'Column[str|None]' = Column( Text, nullable=True )
#: The mobile phone number
[docs] phone_mobile: 'Column[str|None]' = Column( Text, nullable=True )
#: The business phone number
[docs] phone_business: 'Column[str|None]' = Column( Text, nullable=True )
#: The primary email address
[docs] email_primary: 'Column[str|None]' = Column( Text, nullable=True )
#: The secondary email address
[docs] email_secondary: 'Column[str|None]' = Column( Text, nullable=True )
#: The website
[docs] website: 'Column[str|None]' = Column( Text, nullable=True )
#: The remarks
[docs] remarks: 'Column[str|None]' = Column( Text, nullable=True )
#: A picture
[docs] picture = NamedFile()
#: A parliamentarian may have n roles
[docs] roles: 'relationship[list[ParliamentarianRole]]'
roles = relationship( 'ParliamentarianRole', cascade='all, delete-orphan', back_populates='parliamentarian', order_by='desc(ParliamentarianRole.start)' )
[docs] def get_party_during_period( self, start_date: date, end_date: date, session: 'Session' ) -> 'Party | None': """Get the party this parliamentarian belonged to during a specific period.""" from onegov.pas.models.parliamentarian_role import ParliamentarianRole role = ( session.query(ParliamentarianRole) .filter( ParliamentarianRole.parliamentarian_id == self.id, ParliamentarianRole.party_id.isnot( None ), or_( ParliamentarianRole.end.is_(None), ParliamentarianRole.end >= start_date, ), ParliamentarianRole.start <= end_date, ) .order_by(ParliamentarianRole.start.desc()) .first() ) return role.party if role else None
@property
[docs] def active(self) -> bool: if not self.roles: return True for role in self.roles: if role.end is None or role.end >= date.today(): return True return False
[docs] def active_during(self, start: date, end: date) -> bool: if not self.roles: return True for role in self.roles: role_start = role.start if role.start is not None else date.min role_end = role.end if role.end is not None else date.max if role_end >= start and role_start <= end: return True return False
@property
[docs] def display_name(self) -> str: return f'{self.first_name} {self.last_name}'
#: A parliamentarian may be part of n commissions
[docs] commission_memberships: 'relationship[list[CommissionMembership]]'
commission_memberships = relationship( 'CommissionMembership', cascade='all, delete-orphan', back_populates='parliamentarian' ) #: A parliamentarian may attend meetings
[docs] attendences: 'relationship[list[Attendence]]' = relationship( 'Attendence', cascade='all, delete-orphan', back_populates='parliamentarian' )