from __future__ import annotations
from onegov.org.models.political_business import (
par_political_business_parliamentary_groups
)
from onegov.org.i18n import _
from onegov.parliament.collections import CommissionCollection
from onegov.parliament.collections import CommissionMembershipCollection
from onegov.parliament.collections import ParliamentarianCollection
from onegov.parliament.collections import ParliamentarianRoleCollection
from onegov.parliament.collections import ParliamentaryGroupCollection
from onegov.parliament.models import Commission
from onegov.parliament.models import CommissionMembership
from onegov.parliament.models import Parliamentarian
from onegov.parliament.models import ParliamentarianRole
from onegov.parliament.models import ParliamentaryGroup
from onegov.search import ORMSearchable
from sedate import utcnow
from sqlalchemy import and_, or_, exists
from sqlalchemy.orm import relationship
from sqlalchemy.ext.hybrid import hybrid_property
from typing import Self, TYPE_CHECKING
if TYPE_CHECKING:
from onegov.org.models import PoliticalBusiness
from onegov.org.models import PoliticalBusinessParticipation
from sqlalchemy.orm import Query, Session
[docs]
class RISCommission(Commission, ORMSearchable):
[docs]
__mapper_args__ = {
'polymorphic_identity': 'ris_commission',
}
[docs]
fts_type_title = _('Commissions')
[docs]
fts_properties = {
'name': {'type': 'text', 'weight': 'A'},
'description': {'type': 'text', 'weight': 'B'}
}
@property
[docs]
def fts_suggestion(self) -> str:
return self.name
# NOTE: When a commission was last changed should not influence how
# relevant they are in the search results
@property
[docs]
def fts_last_change(self) -> None:
return None
[docs]
class RISCommissionCollection(CommissionCollection[RISCommission]):
@property
[docs]
def model_class(self) -> type[RISCommission]:
return RISCommission
[docs]
class RISCommissionMembership(CommissionMembership):
[docs]
__mapper_args__ = {
'polymorphic_identity': 'ris_commission_membership'
}
[docs]
class RISCommissionMembershipCollection(
CommissionMembershipCollection[RISCommissionMembership]
):
def __init__(
self,
session: Session,
active: bool | None = None
):
super().__init__(session)
@property
[docs]
def model_class(self) -> type[RISCommissionMembership]:
return RISCommissionMembership
[docs]
def query(self) -> Query[RISCommissionMembership]:
query = super().query()
if self.active is not None:
if self.active:
query = query.filter(
or_(
RISCommissionMembership.end.is_(None),
RISCommissionMembership.end >= utcnow()
)
)
else:
query = query.filter(
RISCommissionMembership.end < utcnow()
)
return query
[docs]
def for_filter(
self,
active: bool | None = None
) -> Self:
return self.__class__(self.session, active)
[docs]
class RISParliamentarian(Parliamentarian, ORMSearchable):
[docs]
__mapper_args__ = {
'polymorphic_identity': 'ris_parliamentarian',
}
[docs]
fts_type_title = _('Parliamentarians')
[docs]
fts_properties = {
'first_name': {'type': 'text', 'weight': 'A'},
'last_name': {'type': 'text', 'weight': 'A'},
'title': {'type': 'text', 'weight': 'A'},
}
@property
[docs]
def fts_suggestion(self) -> tuple[str, ...]:
return (
f'{self.first_name} {self.last_name}',
f'{self.last_name} {self.first_name}'
)
# NOTE: When a parliamentarian was last changed should not influence how
# relevant they are in the search results
@property
[docs]
def fts_last_change(self) -> None:
return None
@property
[docs]
def title(self) -> str:
return f'{self.last_name} {self.first_name}'
#: political businesses participations [0..n]
[docs]
political_businesses: relationship[list[PoliticalBusinessParticipation]]
political_businesses = relationship(
'PoliticalBusinessParticipation',
back_populates='parliamentarian',
)
@hybrid_property
[docs]
def active(self) -> bool:
# Wil: every parliamentarian is active if in a parliamentary
# group (which leads to a role) or in a commission
# this will be changed to the parents class implementation
# once the inactive parliamentarians have end dates defined
for role in self.roles:
if role.end is None or role.end >= utcnow().date():
return True
for membership in self.commission_memberships:
if membership.end is None or membership.end >= utcnow().date():
return True
return False
@active.expression # type:ignore[no-redef]
def active(cls):
return or_(
exists().where(
and_(
RISParliamentarianRole.parliamentarian_id == cls.id,
or_(
RISParliamentarianRole.end.is_(None),
RISParliamentarianRole.end >= utcnow()
)
)
),
exists().where(
and_(
RISCommissionMembership.parliamentarian_id == cls.id,
or_(
RISCommissionMembership.end.is_(None),
RISCommissionMembership.end >= utcnow()
)
)
)
)
[docs]
class RISParliamentarianCollection(
ParliamentarianCollection[RISParliamentarian]
):
@property
[docs]
def model_class(self) -> type[RISParliamentarian]:
return RISParliamentarian
[docs]
class RISParliamentarianRole(ParliamentarianRole):
[docs]
__mapper_args__ = {
'polymorphic_identity': 'ris_parliamentarian_role',
}
[docs]
class RISParliamentarianRoleCollection(
ParliamentarianRoleCollection[RISParliamentarianRole]
):
@property
[docs]
def model_class(self) -> type[RISParliamentarianRole]:
return RISParliamentarianRole
[docs]
class RISParliamentaryGroup(ParliamentaryGroup, ORMSearchable):
[docs]
__mapper_args__ = {
'polymorphic_identity': 'ris_parliamentary_group',
}
[docs]
fts_type_title = _('Parliamentary groups')
[docs]
fts_properties = {
'name': {'type': 'text', 'weight': 'A'},
'description': {'type': 'text', 'weight': 'B'}
}
@property
[docs]
def fts_suggestion(self) -> str:
return self.name
# NOTE: When a parliamentary group was last changed should not
# influence how relevant they are in the search results
@property
[docs]
def fts_last_change(self) -> None:
return None
[docs]
political_businesses: relationship[list[PoliticalBusiness]]
political_businesses = relationship(
'PoliticalBusiness',
secondary=par_political_business_parliamentary_groups,
back_populates='parliamentary_groups',
passive_deletes=True
)
[docs]
class RISParliamentaryGroupCollection(
ParliamentaryGroupCollection[RISParliamentaryGroup]
):
@property
[docs]
def model_class(self) -> type[RISParliamentaryGroup]:
return RISParliamentaryGroup