Coverage for app / backend / src / couchers / models / public_trips.py: 100%

23 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-02-22 07:30 +0000

1import enum 

2from datetime import date, datetime 

3from typing import TYPE_CHECKING 

4 

5from sqlalchemy import BigInteger, CheckConstraint, Date, DateTime, Enum, ForeignKey, Index, String, func 

6from sqlalchemy.orm import Mapped, mapped_column, relationship 

7 

8from couchers.models.base import Base 

9 

10if TYPE_CHECKING: 

11 from couchers.models import Node, User 

12 from couchers.models.host_requests import HostRequest 

13 

14 

15class PublicTripStatus(enum.Enum): 

16 searching_for_host = enum.auto() 

17 closed = enum.auto() 

18 

19 

20class PublicTrip(Base, kw_only=True): 

21 """ 

22 A public trip posted by a traveler looking for a host in a community. 

23 """ 

24 

25 __tablename__ = "public_trips" 

26 

27 id: Mapped[int] = mapped_column(BigInteger, primary_key=True, init=False) 

28 

29 # The traveler posting the trip 

30 user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), index=True) 

31 

32 # The community/location (city-level node) 

33 node_id: Mapped[int] = mapped_column(ForeignKey("nodes.id"), index=True) 

34 

35 # Trip dates 

36 from_date: Mapped[date] = mapped_column(Date) 

37 to_date: Mapped[date] = mapped_column(Date) 

38 

39 # User's message about their trip 

40 description: Mapped[str] = mapped_column(String) 

41 

42 # Current status 

43 status: Mapped[PublicTripStatus] = mapped_column( 

44 Enum(PublicTripStatus), default=PublicTripStatus.searching_for_host 

45 ) 

46 

47 # Timestamps 

48 created: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), init=False) 

49 

50 # Relationships 

51 user: Mapped[User] = relationship(init=False, back_populates="public_trips") 

52 node: Mapped[Node] = relationship(init=False, back_populates="public_trips") 

53 host_requests: Mapped[list[HostRequest]] = relationship(init=False, back_populates="public_trip") 

54 

55 __table_args__ = ( 

56 # Ensure from_date is not after to_date 

57 CheckConstraint("from_date <= to_date", name="valid_date_range"), 

58 # Index for querying active trips in a community 

59 # Using partial index since we mostly query for active trips 

60 Index( 

61 "ix_public_trips_node_from_date_active", 

62 node_id, 

63 from_date, 

64 postgresql_where=status == PublicTripStatus.searching_for_host, 

65 ), 

66 )