Source code for winterthur.models.mission_report

from __future__ import annotations

from datetime import datetime
from decimal import Decimal
from onegov.core.orm import Base
from onegov.core.orm.abstract import associated
from onegov.core.orm.mixins import ContentMixin
from onegov.file import File
from onegov.org.models import AccessExtension
from sedate import to_timezone
from sqlalchemy import Enum, ForeignKey, Numeric
from sqlalchemy.orm import mapped_column, relationship, Mapped
from uuid import uuid4, UUID


from typing import Literal, 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: Mapped[UUID] = mapped_column( primary_key=True, default=uuid4 )
#: the date of the report
[docs] date: Mapped[datetime]
#: how long the mission lasted, in hours
[docs] duration: Mapped[Decimal] = mapped_column( Numeric(precision=6, scale=2) )
#: the nature of the mission
[docs] nature: Mapped[str]
#: the location of the mission
[docs] location: Mapped[str]
#: actually active personnel
[docs] personnel: Mapped[int]
#: backup personnel
[docs] backup: Mapped[int]
#: the Zivilschutz was involved
[docs] civil_defence: Mapped[bool] = mapped_column(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: Mapped[int] = mapped_column(default=1)
# the mission type
[docs] mission_type: Mapped[MissionType] = mapped_column( Enum(*MISSION_TYPES, name='mission_type'), default='single' )
[docs] used_vehicles: Mapped[list[MissionReportVehicleUse]] = relationship( 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: Mapped[UUID] = mapped_column( primary_key=True, default=uuid4 )
#: the short id of the vehicle
[docs] name: Mapped[str]
#: the longer name of the vehicle
[docs] description: Mapped[str]
#: symbol of the vehicle
[docs] symbol = associated(MissionReportFile, 'symbol', 'one-to-one')
#: a website describing the vehicle
[docs] website: Mapped[str | None]
[docs] uses: Mapped[list[MissionReportVehicleUse]] = relationship( 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: Mapped[UUID] = mapped_column( ForeignKey('mission_reports.id'), primary_key=True )
[docs] mission_report: Mapped[MissionReport] = relationship( back_populates='used_vehicles' )
[docs] vehicle_id: Mapped[UUID] = mapped_column( ForeignKey('mission_report_vehicles.id'), primary_key=True )
[docs] vehicle: Mapped[MissionReportVehicle] = relationship( back_populates='uses' )
# vehicles may be used multiple times in a single mission_report
[docs] count: Mapped[int] = mapped_column(default=1)