Source code for winterthur.models.mission_report

from onegov.core.orm import Base
from onegov.core.orm.abstract import associated
from onegov.core.orm.mixins import ContentMixin
from onegov.core.orm.types import UUID, UTCDateTime
from onegov.file import File
from onegov.org.models import AccessExtension
from sedate import to_timezone
from sqlalchemy import (
    Boolean, Column, ForeignKey, Integer, Numeric, Text, Enum
)
from sqlalchemy.orm import relationship
from uuid import uuid4


from typing import Literal, TYPE_CHECKING
if TYPE_CHECKING:
    import uuid
    from datetime import datetime
    from decimal import Decimal
    from typing import TypeAlias

[docs] MissionType: TypeAlias = Literal['single', 'multi']
[docs] MISSION_TYPES: tuple['MissionType', ...] = ('single', 'multi')
[docs] class MissionReportFile(File):
[docs] __mapper_args__ = {'polymorphic_identity': 'mission-report-file'}
[docs] class MissionReport(Base, ContentMixin, AccessExtension):
[docs] __tablename__ = 'mission_reports'
#: the public id of the mission_report
[docs] id: 'Column[uuid.UUID]' = Column( UUID, # type:ignore[arg-type] primary_key=True, default=uuid4 )
#: the date of the report
[docs] date: 'Column[datetime]' = Column(UTCDateTime, nullable=False)
#: how long the mission lasted, in hours
[docs] duration: 'Column[Decimal]' = Column( Numeric(precision=6, scale=2), nullable=False )
#: the nature of the mission
[docs] nature: 'Column[str]' = Column(Text, nullable=False)
#: the location of the mission
[docs] location: 'Column[str]' = Column(Text, nullable=False)
#: actually active personnel
[docs] personnel: 'Column[int]' = Column(Integer, nullable=False)
#: backup personnel
[docs] backup: 'Column[int]' = Column(Integer, nullable=False)
#: the Zivilschutz was involved
[docs] civil_defence: 'Column[bool]' = Column( Boolean, nullable=False, default=False )
#: pictures of the mission
[docs] pictures = associated(MissionReportFile, 'pictures', 'one-to-many')
# The number of missions on the same site during a day
[docs] mission_count: 'Column[int]' = Column(Integer, nullable=False, default=1)
# the mission type
[docs] mission_type: 'Column[MissionType]' = Column( Enum(*MISSION_TYPES, name='mission_type'), # type:ignore[arg-type] nullable=False, default='single' )
[docs] used_vehicles: 'relationship[list[MissionReportVehicleUse]]'
used_vehicles = relationship( 'MissionReportVehicleUse', cascade='all, delete-orphan', back_populates='mission_report' ) @property
[docs] def title(self) -> str: return self.nature
@property
[docs] def readable_duration(self) -> str: return str(self.duration).rstrip('.0') + 'h'
@property
[docs] def local_date(self) -> 'datetime': return to_timezone(self.date, 'Europe/Zurich')
[docs] class MissionReportVehicle(Base, ContentMixin, AccessExtension):
[docs] __tablename__ = 'mission_report_vehicles'
#: the public id of the vehicle
[docs] id: 'Column[uuid.UUID]' = Column( UUID, # type:ignore[arg-type] primary_key=True, default=uuid4 )
#: the short id of the vehicle
[docs] name: 'Column[str]' = Column(Text, nullable=False)
#: the longer name of the vehicle
[docs] description: 'Column[str]' = Column(Text, nullable=False)
#: symbol of the vehicle
[docs] symbol = associated(MissionReportFile, 'symbol', 'one-to-one')
#: a website describing the vehicle
[docs] website: 'Column[str | None]' = Column(Text, nullable=True)
[docs] uses: 'relationship[list[MissionReportVehicleUse]]' = relationship( 'MissionReportVehicleUse', back_populates='vehicle' )
@property
[docs] def title(self) -> str: return f'{self.name} - {self.description}'
@property
[docs] def readable_website(self) -> str | None: if self.website: return (self.website.removeprefix('http://') .removeprefix('https://')) return None
[docs] class MissionReportVehicleUse(Base): """ Many to many association between vehicles and reports. """
[docs] __tablename__ = 'mission_report_vehicle_usees'
[docs] mission_report_id: 'Column[uuid.UUID]' = Column( UUID, # type:ignore[arg-type] ForeignKey('mission_reports.id'), primary_key=True )
[docs] mission_report: 'relationship[MissionReport]' = relationship( MissionReport, back_populates='used_vehicles' )
[docs] vehicle_id: 'Column[uuid.UUID]' = Column( UUID, # type:ignore[arg-type] ForeignKey('mission_report_vehicles.id'), primary_key=True )
[docs] vehicle: 'relationship[MissionReportVehicle]' = relationship( MissionReportVehicle, back_populates='uses' )
# vehicles may be used multiple times in a single mission_report
[docs] count = Column( Integer, nullable=False, default=1 )