Source code for activity.models.invoice

from __future__ import annotations

from onegov.core.orm.types import UUID
from onegov.pay import Invoice
from onegov.user import User
from sqlalchemy import Column
from sqlalchemy import ForeignKey
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship


from typing import Any, TYPE_CHECKING
if TYPE_CHECKING:
    import uuid
    from collections.abc import Iterable
    from decimal import Decimal
    from onegov.activity.models import ActivityInvoiceItem
    from onegov.activity.models import BookingPeriod


[docs] class BookingPeriodInvoice(Invoice): """ An invoice for all bookings within a period. """
[docs] __mapper_args__ = { 'polymorphic_identity': 'booking_period' }
#: the period to which this invoice belongs to
[docs] period_id: Column[uuid.UUID] = Column( # type: ignore[assignment] UUID, # type:ignore[arg-type] ForeignKey('periods.id'), nullable=True )
[docs] period: relationship[BookingPeriod] = relationship( 'BookingPeriod', back_populates='invoices' )
#: the user to which the invoice belongs
[docs] user_id: Column[uuid.UUID] = Column( # type: ignore[assignment] UUID, # type:ignore[arg-type] ForeignKey('users.id'), nullable=True )
# FIXME: Do we need this backref? It's across module boundaries, so # not the best for proper module isolation
[docs] user: relationship[User] = relationship(User, backref='invoices')
if TYPE_CHECKING:
[docs] items: relationship[list[ActivityInvoiceItem]] # type: ignore[assignment]
@property
[docs] def has_donation(self) -> bool: for item in self.items: if item.group == 'donation': return True return False
[docs] def add( self, group: str, text: str, unit: Decimal, quantity: Decimal, *, organizer: str = '', attendee_id: uuid.UUID | None = None, flush: bool = True, **kwargs: Any # FIXME: type safety for optional arguments ) -> ActivityInvoiceItem: return super().add( # type: ignore[return-value] type='activity', group=group, text=text, unit=unit, quantity=quantity, organizer=organizer, attendee_id=attendee_id, flush=flush, **kwargs )
@hybrid_property
[docs] def discourage_changes(self) -> bool: return self.discourage_changes_for_items(self.items)
@hybrid_property
[docs] def disable_changes(self) -> bool: return self.disable_changes_for_items(self.items)
@hybrid_property
[docs] def has_online_payments(self) -> bool: return self.has_online_payments_for_items(self.items)
[docs] def discourage_changes_for_items( self, items: Iterable[ActivityInvoiceItem] ) -> bool: for item in items: if item.source == 'xml': return True return False
[docs] def disable_changes_for_items( self, items: Iterable[ActivityInvoiceItem] ) -> bool: for item in items: if not item.source: continue if item.source == 'xml': continue states = {p.state for p in item.payments} if 'open' in states or 'paid' in states: return True return False
[docs] def has_online_payments_for_items( self, items: Iterable[ActivityInvoiceItem] ) -> bool: for item in items: if not item.source or item.source == 'xml': continue return True return False