text: from onegov.ballot.models.election.mixins import DerivedAttributesMixin
  from onegov.core.orm import Base
  from onegov.core.orm.mixins import TimestampMixin
  from onegov.core.orm.types import UUID
  from sqlalchemy import Boolean
  from sqlalchemy import Column
  from sqlalchemy import ForeignKey
  from sqlalchemy import Integer
  from sqlalchemy import select
  from sqlalchemy import Text
  from sqlalchemy import text
  from sqlalchemy.ext.hybrid import hybrid_property
  from sqlalchemy.orm import backref
  from sqlalchemy.orm import relationship
  from uuid import uuid4
  
  
  class ElectionResult(Base, TimestampMixin, DerivedAttributesMixin):
      """ The election result in a single political entity. """
  
      __tablename__ = 'election_results'
  
      #: identifies the result
      id = Column(UUID, primary_key=True, default=uuid4)
  
      #: the election this result belongs to
      election_id = Column(
          Text,
          ForeignKey('elections.id', onupdate='CASCADE', ondelete='CASCADE'),
          nullable=False
      )
  
      #: entity id (e.g. a BFS number).
      entity_id = Column(Integer, nullable=False)
  
      #: the name of the entity
      name = Column(Text, nullable=False)
  
      #: the district this entity belongs to
      district = Column(Text, nullable=True)
  
      #: True if the result has been counted and no changes will be made anymore.
      #: If the result is definite, all the values below must be specified.
      counted = Column(Boolean, nullable=False)
  
      #: number of eligible voters
      eligible_voters = Column(Integer, nullable=False, default=lambda: 0)
  
      #: number of received ballots
      received_ballots = Column(Integer, nullable=False, default=lambda: 0)
  
      #: number of blank ballots
      blank_ballots = Column(Integer, nullable=False, default=lambda: 0)
  
      #: number of invalid ballots
      invalid_ballots = Column(Integer, nullable=False, default=lambda: 0)
  
      #: number of blank votes
      blank_votes = Column(Integer, nullable=False, default=lambda: 0)
  
      #: number of invalid votes
      invalid_votes = Column(Integer, nullable=False, default=lambda: 0)
  
      @hybrid_property
      def counted_eligible_voters(self):
          """ The number of votes for turnout calculation """
          return 0 if not self.counted else self.eligible_voters
  
      @hybrid_property
      def counted_received_ballots(self):
          return 0 if not self.counted else self.received_ballots
  
      @hybrid_property
      def accounted_votes(self):
          """ The number of accounted votes. """
  
          return (
              self.election.number_of_mandates * self.accounted_ballots
              - self.blank_votes
              - self.invalid_votes
          )
  
      @accounted_votes.expression
      def accounted_votes(cls):
          """ The number of accounted votes. """
          from onegov.ballot.models.election import Election  # circular
  
          # A bit of a hack :|
          number_of_mandates = select(
              [Election.number_of_mandates],
              whereclause=text('elections.id = election_results.election_id')
          )
          return (
              number_of_mandates * (
                  cls.received_ballots - cls.blank_ballots - cls.invalid_ballots
              ) - cls.blank_votes - cls.invalid_votes
          )
  
      #: an election result may contain n list results
      list_results = relationship(
          'ListResult',
          cascade='all, delete-orphan',
          backref=backref('election_result'),
          lazy='dynamic',
      )
  
      #: an election result contains n candidate results
      candidate_results = relationship(
          'CandidateResult',
          cascade='all, delete-orphan',
          backref=backref('election_result'),
          lazy='dynamic',
      )
  