2024-01-26 00:31:14 +00:00
|
|
|
from django.db import models
|
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
class TransportType(models.TextChoices):
|
|
|
|
TGV = "TGV", _("TGV")
|
|
|
|
TER = "TER", _("TER")
|
|
|
|
INTERCITES = "IC", _("Intercités")
|
|
|
|
TRANSILIEN = "TN", _("Transilien")
|
2024-02-10 16:33:36 +00:00
|
|
|
EUROSTAR = "ES", _("Eurostar")
|
|
|
|
TRENITALIA = "TI", _("Trenitalia")
|
|
|
|
RENFE = "RENFE", _("Renfe")
|
|
|
|
OBB = "OBB", _("ÖBB")
|
2024-01-27 09:43:59 +00:00
|
|
|
|
|
|
|
|
2024-01-26 00:31:14 +00:00
|
|
|
class LocationType(models.IntegerChoices):
|
|
|
|
STOP_PLATFORM = 0, _("Stop/platform")
|
|
|
|
STATION = 1, _("Station")
|
|
|
|
ENTRANCE_EXIT = 2, _("Entrance/exit")
|
|
|
|
GENERIC_NODE = 3, _("Generic node")
|
|
|
|
BOARDING_AREA = 4, _("Boarding area")
|
|
|
|
|
|
|
|
|
|
|
|
class AccessInformation(models.IntegerChoices):
|
|
|
|
NO_INFORMATION = 0, _("No information")
|
|
|
|
POSSIBLE = 1, _("Possible")
|
|
|
|
NOT_POSSIBLE = 2, _("Not possible")
|
|
|
|
|
|
|
|
|
|
|
|
class PickupType(models.IntegerChoices):
|
|
|
|
REGULAR = 0, _("Regular")
|
|
|
|
NONE = 1, _("None")
|
|
|
|
MUST_PHONE_AGENCY = 2, _("Must phone agency")
|
|
|
|
MUST_COORDINATE_WITH_DRIVER = 3, _("Must coordinate with driver")
|
|
|
|
|
|
|
|
|
|
|
|
class RouteType(models.IntegerChoices):
|
|
|
|
TRAM = 0, _("Tram")
|
|
|
|
METRO = 1, _("Metro")
|
|
|
|
RAIL = 2, _("Rail")
|
|
|
|
BUS = 3, _("Bus")
|
|
|
|
FERRY = 4, _("Ferry")
|
|
|
|
CABLE_CAR = 5, _("Cable car")
|
|
|
|
GONDOLA = 6, _("Gondola")
|
|
|
|
FUNICULAR = 7, _("Funicular")
|
|
|
|
|
|
|
|
|
|
|
|
class Direction(models.IntegerChoices):
|
|
|
|
OUTBOUND = 0, _("Outbound")
|
|
|
|
INBOUND = 1, _("Inbound")
|
|
|
|
|
|
|
|
|
2024-01-26 20:16:26 +00:00
|
|
|
class TransferType(models.IntegerChoices):
|
|
|
|
RECOMMENDED = 0, _("Recommended")
|
|
|
|
TIMED = 1, _("Timed")
|
|
|
|
MINIMUM_TIME = 2, _("Minimum time")
|
|
|
|
NOT_POSSIBLE = 3, _("Not possible")
|
|
|
|
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
class ExceptionType(models.IntegerChoices):
|
|
|
|
ADDED = 1, _("Added")
|
|
|
|
REMOVED = 2, _("Removed")
|
|
|
|
|
|
|
|
|
2024-02-06 07:01:56 +00:00
|
|
|
class TripScheduleRelationship(models.IntegerChoices):
|
|
|
|
SCHEDULED = 0, _("Scheduled")
|
|
|
|
ADDED = 1, _("Added")
|
|
|
|
UNSCHEDULED = 2, _("Unscheduled")
|
|
|
|
CANCELED = 3, _("Canceled")
|
|
|
|
REPLACEMENT = 5, _("Replacement")
|
|
|
|
DUPLICATED = 6, _("Duplicated")
|
|
|
|
DELETED = 7, _("Deleted")
|
|
|
|
|
|
|
|
|
|
|
|
class StopScheduleRelationship(models.IntegerChoices):
|
2024-02-04 21:20:09 +00:00
|
|
|
SCHEDULED = 0, _("Scheduled")
|
|
|
|
SKIPPED = 1, _("Skipped")
|
|
|
|
NO_DATA = 2, _("No data")
|
|
|
|
UNSCHEDULED = 3, _("Unscheduled")
|
|
|
|
|
|
|
|
|
2024-01-26 00:31:14 +00:00
|
|
|
class Agency(models.Model):
|
2024-01-27 09:43:59 +00:00
|
|
|
id = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
primary_key=True,
|
|
|
|
verbose_name=_("Agency ID"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
name = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Agency name"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
url = models.URLField(
|
2024-01-26 00:31:14 +00:00
|
|
|
verbose_name=_("Agency URL"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
timezone = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Agency timezone"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
lang = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Agency language"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
phone = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Agency phone"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
email = models.EmailField(
|
|
|
|
verbose_name=_("Agency email"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return self.name
|
|
|
|
|
2024-01-26 00:31:14 +00:00
|
|
|
class Meta:
|
|
|
|
verbose_name = _("Agency")
|
|
|
|
verbose_name_plural = _("Agencies")
|
2024-01-27 14:18:33 +00:00
|
|
|
ordering = ("name",)
|
2024-01-26 00:31:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Stop(models.Model):
|
2024-01-27 09:43:59 +00:00
|
|
|
id = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
primary_key=True,
|
|
|
|
verbose_name=_("Stop ID"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
code = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Stop code"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
name = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Stop name"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
desc = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Stop description"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
lon = models.FloatField(
|
2024-01-26 00:31:14 +00:00
|
|
|
verbose_name=_("Stop longitude"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
lat = models.FloatField(
|
2024-01-26 00:31:14 +00:00
|
|
|
verbose_name=_("Stop latitude"),
|
|
|
|
)
|
|
|
|
|
|
|
|
zone_id = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Zone ID"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
url = models.URLField(
|
2024-01-26 00:31:14 +00:00
|
|
|
verbose_name=_("Stop URL"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
location_type = models.IntegerField(
|
|
|
|
verbose_name=_("Location type"),
|
|
|
|
blank=True,
|
|
|
|
choices=LocationType,
|
|
|
|
default=LocationType.STOP_PLATFORM,
|
|
|
|
)
|
|
|
|
|
|
|
|
parent_station = models.ForeignKey(
|
|
|
|
to="Stop",
|
|
|
|
on_delete=models.PROTECT,
|
|
|
|
verbose_name=_("Parent station"),
|
2024-01-27 09:43:59 +00:00
|
|
|
related_name="children",
|
2024-01-26 00:31:14 +00:00
|
|
|
blank=True,
|
2024-01-27 09:43:59 +00:00
|
|
|
null=True,
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
timezone = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Stop timezone"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
level_id = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Level ID"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
wheelchair_boarding = models.IntegerField(
|
|
|
|
verbose_name=_("Wheelchair boarding"),
|
|
|
|
blank=True,
|
|
|
|
choices=AccessInformation,
|
|
|
|
default=AccessInformation.NO_INFORMATION,
|
|
|
|
)
|
|
|
|
|
|
|
|
platform_code = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Platform code"),
|
2024-01-27 09:43:59 +00:00
|
|
|
blank=True,
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
2024-02-10 16:33:36 +00:00
|
|
|
transport_type = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Transport type"),
|
|
|
|
choices=TransportType,
|
|
|
|
)
|
|
|
|
|
2024-02-04 21:20:09 +00:00
|
|
|
@property
|
|
|
|
def stop_type(self):
|
|
|
|
train_type = self.id.split('StopPoint:OCE')[1].split('-')[0]
|
|
|
|
return train_type
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.name} ({self.id})"
|
|
|
|
|
2024-01-26 00:31:14 +00:00
|
|
|
class Meta:
|
|
|
|
verbose_name = _("Stop")
|
|
|
|
verbose_name_plural = _("Stops")
|
2024-01-27 14:18:33 +00:00
|
|
|
ordering = ("id",)
|
2024-01-26 00:31:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Route(models.Model):
|
2024-01-27 09:43:59 +00:00
|
|
|
id = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
primary_key=True,
|
2024-01-27 09:43:59 +00:00
|
|
|
verbose_name=_("ID"),
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
agency = models.ForeignKey(
|
|
|
|
to="Agency",
|
|
|
|
on_delete=models.CASCADE,
|
2024-02-09 22:15:14 +00:00
|
|
|
verbose_name=_("Agency"),
|
2024-01-27 09:43:59 +00:00
|
|
|
related_name="routes",
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
short_name = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Route short name"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
long_name = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Route long name"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
desc = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Route description"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
type = models.IntegerField(
|
2024-01-26 00:31:14 +00:00
|
|
|
verbose_name=_("Route type"),
|
|
|
|
choices=RouteType,
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
url = models.URLField(
|
2024-01-26 00:31:14 +00:00
|
|
|
verbose_name=_("Route URL"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
color = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Route color"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
text_color = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Route text color"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
2024-02-09 22:15:14 +00:00
|
|
|
transport_type = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Transport type"),
|
|
|
|
choices=TransportType,
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.long_name}"
|
|
|
|
|
2024-01-26 00:31:14 +00:00
|
|
|
class Meta:
|
|
|
|
verbose_name = _("Route")
|
|
|
|
verbose_name_plural = _("Routes")
|
2024-01-27 14:18:33 +00:00
|
|
|
ordering = ("id",)
|
2024-01-26 00:31:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Trip(models.Model):
|
2024-01-27 09:43:59 +00:00
|
|
|
id = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
primary_key=True,
|
|
|
|
verbose_name=_("Trip ID"),
|
|
|
|
)
|
|
|
|
|
|
|
|
route = models.ForeignKey(
|
|
|
|
to="Route",
|
|
|
|
on_delete=models.CASCADE,
|
2024-01-27 09:43:59 +00:00
|
|
|
verbose_name=_("Route"),
|
|
|
|
related_name="trips",
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
service = models.ForeignKey(
|
|
|
|
to="Calendar",
|
|
|
|
on_delete=models.CASCADE,
|
|
|
|
verbose_name=_("Service"),
|
|
|
|
related_name="trips",
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
headsign = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Trip headsign"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
short_name = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Trip short name"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
direction_id = models.IntegerField(
|
|
|
|
verbose_name=_("Direction"),
|
|
|
|
choices=Direction,
|
2024-01-27 09:43:59 +00:00
|
|
|
null=True,
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
block_id = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Block ID"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
shape_id = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Shape ID"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
wheelchair_accessible = models.IntegerField(
|
|
|
|
verbose_name=_("Wheelchair accessible"),
|
|
|
|
choices=AccessInformation,
|
|
|
|
default=AccessInformation.NO_INFORMATION,
|
2024-01-27 09:43:59 +00:00
|
|
|
null=True,
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
bikes_allowed = models.IntegerField(
|
|
|
|
verbose_name=_("Bikes allowed"),
|
|
|
|
choices=AccessInformation,
|
|
|
|
default=AccessInformation.NO_INFORMATION,
|
2024-01-27 09:43:59 +00:00
|
|
|
null=True,
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
2024-02-09 22:15:14 +00:00
|
|
|
last_update = models.DateTimeField(
|
|
|
|
verbose_name=_("Last update"),
|
|
|
|
null=True,
|
|
|
|
)
|
|
|
|
|
2024-01-27 12:41:34 +00:00
|
|
|
@property
|
|
|
|
def origin(self):
|
|
|
|
return self.stop_times.order_by('stop_sequence').first().stop
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
@property
|
|
|
|
def destination(self):
|
2024-01-27 12:41:34 +00:00
|
|
|
return self.stop_times.order_by('-stop_sequence').first().stop
|
|
|
|
|
2024-02-09 22:15:14 +00:00
|
|
|
@property
|
|
|
|
def departure_time(self):
|
|
|
|
dep_time = self.stop_times.order_by('stop_sequence').first().departure_time
|
|
|
|
hours = int(dep_time.total_seconds() // 3600)
|
|
|
|
minutes = int((dep_time.total_seconds() % 3600) // 60)
|
|
|
|
return f"{hours:02}:{minutes:02}"
|
|
|
|
|
|
|
|
@property
|
|
|
|
def arrival_time(self):
|
|
|
|
arr_time = self.stop_times.order_by('-stop_sequence').first().arrival_time
|
|
|
|
hours = int(arr_time.total_seconds() // 3600)
|
|
|
|
minutes = int((arr_time.total_seconds() % 3600) // 60)
|
|
|
|
return f"{hours:02}:{minutes:02}"
|
|
|
|
|
2024-01-27 12:41:34 +00:00
|
|
|
@property
|
|
|
|
def train_type(self):
|
2024-02-09 22:15:14 +00:00
|
|
|
if self.route.transport_type == TransportType.TRANSILIEN:
|
2024-01-27 12:41:34 +00:00
|
|
|
return self.route.short_name
|
|
|
|
else:
|
2024-02-04 21:20:09 +00:00
|
|
|
return self.origin.stop_type
|
2024-01-27 12:41:34 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def train_number(self):
|
2024-02-09 22:15:14 +00:00
|
|
|
if self.route.transport_type == TransportType.TRANSILIEN:
|
2024-01-27 12:41:34 +00:00
|
|
|
return self.short_name
|
|
|
|
else:
|
|
|
|
return self.headsign
|
|
|
|
|
|
|
|
@property
|
|
|
|
def color(self):
|
|
|
|
if self.route.color:
|
|
|
|
return self.route.color
|
|
|
|
elif self.train_type == "OUIGO":
|
|
|
|
return "E60075"
|
|
|
|
return "FFFFFF"
|
|
|
|
|
|
|
|
@property
|
|
|
|
def text_color(self):
|
|
|
|
if self.route.text_color:
|
|
|
|
return self.route.text_color
|
|
|
|
elif self.train_type == "OUIGO":
|
|
|
|
return "FFFFFF"
|
|
|
|
elif self.train_type == "TGV INOUI":
|
|
|
|
return "9B2743"
|
|
|
|
elif self.train_type == "INTER-CITÉS" or self.train_type == "INTER-CITÉS de nuit":
|
|
|
|
return "404042"
|
|
|
|
return "000000"
|
2024-01-27 09:43:59 +00:00
|
|
|
|
|
|
|
def __str__(self):
|
2024-02-09 22:15:14 +00:00
|
|
|
return f"{self.origin.name} {self.departure_time} → {self.destination.name} {self.arrival_time}" \
|
|
|
|
f" - {self.service_id}"
|
2024-01-27 09:43:59 +00:00
|
|
|
|
2024-01-26 00:31:14 +00:00
|
|
|
class Meta:
|
|
|
|
verbose_name = _("Trip")
|
|
|
|
verbose_name_plural = _("Trips")
|
|
|
|
|
|
|
|
|
|
|
|
class StopTime(models.Model):
|
2024-01-27 09:43:59 +00:00
|
|
|
id = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
primary_key=True,
|
|
|
|
verbose_name=_("ID"),
|
|
|
|
)
|
|
|
|
|
|
|
|
trip = models.ForeignKey(
|
2024-01-26 00:31:14 +00:00
|
|
|
to="Trip",
|
|
|
|
on_delete=models.CASCADE,
|
2024-01-27 09:43:59 +00:00
|
|
|
verbose_name=_("Trip"),
|
|
|
|
related_name="stop_times",
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
2024-01-27 10:43:01 +00:00
|
|
|
arrival_time = models.DurationField(
|
2024-01-26 00:31:14 +00:00
|
|
|
verbose_name=_("Arrival time"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 10:43:01 +00:00
|
|
|
departure_time = models.DurationField(
|
2024-01-26 00:31:14 +00:00
|
|
|
verbose_name=_("Departure time"),
|
|
|
|
)
|
|
|
|
|
|
|
|
stop = models.ForeignKey(
|
|
|
|
to="Stop",
|
|
|
|
on_delete=models.CASCADE,
|
|
|
|
verbose_name=_("Stop ID"),
|
2024-01-27 09:43:59 +00:00
|
|
|
related_name="stop_times",
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
stop_sequence = models.IntegerField(
|
|
|
|
verbose_name=_("Stop sequence"),
|
|
|
|
)
|
|
|
|
|
|
|
|
stop_headsign = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Stop headsign"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
pickup_type = models.IntegerField(
|
|
|
|
verbose_name=_("Pickup type"),
|
|
|
|
choices=PickupType,
|
|
|
|
default=PickupType.REGULAR,
|
2024-01-27 09:43:59 +00:00
|
|
|
null=True,
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
drop_off_type = models.IntegerField(
|
|
|
|
verbose_name=_("Drop off type"),
|
|
|
|
choices=PickupType,
|
|
|
|
default=PickupType.REGULAR,
|
2024-01-27 09:43:59 +00:00
|
|
|
null=True,
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
timepoint = models.BooleanField(
|
|
|
|
verbose_name=_("Timepoint"),
|
|
|
|
default=True,
|
2024-01-27 09:43:59 +00:00
|
|
|
null=True,
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
2024-01-27 10:43:01 +00:00
|
|
|
@property
|
|
|
|
def pretty_arrival_time(self):
|
|
|
|
seconds = self.arrival_time.total_seconds()
|
|
|
|
hours = int(seconds // 3600) % 24
|
|
|
|
minutes = int((seconds % 3600) // 60)
|
|
|
|
return f"{hours:02}:{minutes:02}"
|
|
|
|
|
|
|
|
@property
|
|
|
|
def pretty_departure_time(self):
|
|
|
|
seconds = self.departure_time.total_seconds()
|
|
|
|
hours = int(seconds // 3600) % 24
|
|
|
|
minutes = int((seconds % 3600) // 60)
|
|
|
|
return f"{hours:02}:{minutes:02}"
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
def __str__(self):
|
2024-02-09 22:15:14 +00:00
|
|
|
return f"{self.stop.name} - {self.trip_id}"
|
2024-01-27 09:43:59 +00:00
|
|
|
|
2024-01-26 00:31:14 +00:00
|
|
|
class Meta:
|
|
|
|
verbose_name = _("Stop time")
|
|
|
|
verbose_name_plural = _("Stop times")
|
|
|
|
|
|
|
|
|
|
|
|
class Calendar(models.Model):
|
2024-01-27 09:43:59 +00:00
|
|
|
id = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
primary_key=True,
|
|
|
|
verbose_name=_("Service ID"),
|
|
|
|
)
|
|
|
|
|
|
|
|
monday = models.BooleanField(
|
|
|
|
verbose_name=_("Monday"),
|
|
|
|
)
|
|
|
|
|
|
|
|
tuesday = models.BooleanField(
|
|
|
|
verbose_name=_("Tuesday"),
|
|
|
|
)
|
|
|
|
|
|
|
|
wednesday = models.BooleanField(
|
|
|
|
verbose_name=_("Wednesday"),
|
|
|
|
)
|
|
|
|
|
|
|
|
thursday = models.BooleanField(
|
|
|
|
verbose_name=_("Thursday"),
|
|
|
|
)
|
|
|
|
|
|
|
|
friday = models.BooleanField(
|
|
|
|
verbose_name=_("Friday"),
|
|
|
|
)
|
|
|
|
|
|
|
|
saturday = models.BooleanField(
|
|
|
|
verbose_name=_("Saturday"),
|
|
|
|
)
|
|
|
|
|
|
|
|
sunday = models.BooleanField(
|
|
|
|
verbose_name=_("Sunday"),
|
|
|
|
)
|
|
|
|
|
|
|
|
start_date = models.DateField(
|
|
|
|
verbose_name=_("Start date"),
|
|
|
|
)
|
|
|
|
|
|
|
|
end_date = models.DateField(
|
|
|
|
verbose_name=_("End date"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
transport_type = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Transport type"),
|
|
|
|
choices=TransportType,
|
|
|
|
)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return self.id
|
|
|
|
|
2024-01-26 00:31:14 +00:00
|
|
|
class Meta:
|
|
|
|
verbose_name = _("Calendar")
|
|
|
|
verbose_name_plural = _("Calendars")
|
2024-01-27 14:18:33 +00:00
|
|
|
ordering = ("id",)
|
2024-01-26 00:31:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
class CalendarDate(models.Model):
|
2024-01-27 09:43:59 +00:00
|
|
|
id = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
primary_key=True,
|
|
|
|
verbose_name=_("ID"),
|
|
|
|
)
|
|
|
|
|
|
|
|
service = models.ForeignKey(
|
2024-01-26 00:31:14 +00:00
|
|
|
to="Calendar",
|
|
|
|
on_delete=models.CASCADE,
|
2024-01-27 09:43:59 +00:00
|
|
|
verbose_name=_("Service"),
|
|
|
|
related_name="dates",
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
date = models.DateField(
|
|
|
|
verbose_name=_("Date"),
|
|
|
|
)
|
|
|
|
|
|
|
|
exception_type = models.IntegerField(
|
|
|
|
verbose_name=_("Exception type"),
|
2024-01-27 09:43:59 +00:00
|
|
|
choices=ExceptionType,
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
2024-01-27 09:43:59 +00:00
|
|
|
def __str__(self):
|
|
|
|
return f"{self.service.id} - {self.date} - {self.exception_type}"
|
|
|
|
|
2024-01-26 00:31:14 +00:00
|
|
|
class Meta:
|
|
|
|
verbose_name = _("Calendar date")
|
|
|
|
verbose_name_plural = _("Calendar dates")
|
2024-01-27 14:18:33 +00:00
|
|
|
ordering = ("id",)
|
2024-01-26 00:31:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Transfer(models.Model):
|
2024-01-27 09:43:59 +00:00
|
|
|
id = models.CharField(
|
|
|
|
max_length=255,
|
|
|
|
primary_key=True,
|
|
|
|
verbose_name=_("ID"),
|
|
|
|
)
|
|
|
|
|
2024-01-26 00:31:14 +00:00
|
|
|
from_stop = models.ForeignKey(
|
|
|
|
to="Stop",
|
|
|
|
on_delete=models.CASCADE,
|
|
|
|
verbose_name=_("From stop"),
|
|
|
|
related_name="transfers_from",
|
|
|
|
)
|
|
|
|
|
|
|
|
to_stop = models.ForeignKey(
|
|
|
|
to="Stop",
|
|
|
|
on_delete=models.CASCADE,
|
|
|
|
verbose_name=_("To stop"),
|
|
|
|
related_name="transfers_to",
|
|
|
|
)
|
|
|
|
|
|
|
|
transfer_type = models.IntegerField(
|
|
|
|
verbose_name=_("Transfer type"),
|
2024-01-26 20:16:26 +00:00
|
|
|
choices=TransferType,
|
|
|
|
default=TransferType.RECOMMENDED,
|
2024-01-26 00:31:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
min_transfer_time = models.IntegerField(
|
|
|
|
verbose_name=_("Minimum transfer time"),
|
|
|
|
blank=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
verbose_name = _("Transfer")
|
|
|
|
verbose_name_plural = _("Transfers")
|
2024-01-27 14:18:33 +00:00
|
|
|
ordering = ("id",)
|
2024-01-26 00:31:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
class FeedInfo(models.Model):
|
2024-01-27 14:18:33 +00:00
|
|
|
publisher_name = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Feed publisher name"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 14:18:33 +00:00
|
|
|
publisher_url = models.URLField(
|
2024-01-26 00:31:14 +00:00
|
|
|
verbose_name=_("Feed publisher URL"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 14:18:33 +00:00
|
|
|
lang = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Feed language"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 14:18:33 +00:00
|
|
|
start_date = models.DateField(
|
2024-01-26 00:31:14 +00:00
|
|
|
verbose_name=_("Feed start date"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 14:18:33 +00:00
|
|
|
end_date = models.DateField(
|
2024-01-26 00:31:14 +00:00
|
|
|
verbose_name=_("Feed end date"),
|
|
|
|
)
|
|
|
|
|
2024-01-27 14:18:33 +00:00
|
|
|
version = models.CharField(
|
2024-01-26 00:31:14 +00:00
|
|
|
max_length=255,
|
|
|
|
verbose_name=_("Feed version"),
|
|
|
|
)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
verbose_name = _("Feed info")
|
|
|
|
verbose_name_plural = _("Feed infos")
|
2024-01-27 14:18:33 +00:00
|
|
|
ordering = ("publisher_name",)
|
2024-02-04 21:20:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TripUpdate(models.Model):
|
|
|
|
trip = models.OneToOneField(
|
|
|
|
to="Trip",
|
|
|
|
on_delete=models.CASCADE,
|
|
|
|
verbose_name=_("Trip"),
|
|
|
|
related_name="update",
|
|
|
|
primary_key=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
start_date = models.DateField(
|
|
|
|
verbose_name=_("Start date"),
|
|
|
|
)
|
|
|
|
|
|
|
|
start_time = models.TimeField(
|
|
|
|
verbose_name=_("Start time"),
|
|
|
|
)
|
|
|
|
|
|
|
|
schedule_relationship = models.IntegerField(
|
|
|
|
verbose_name=_("Schedule relationship"),
|
2024-02-06 07:01:56 +00:00
|
|
|
choices=TripScheduleRelationship,
|
|
|
|
default=TripScheduleRelationship.SCHEDULED,
|
2024-02-04 21:20:09 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return str(self.trip)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
verbose_name = _("Trip update")
|
|
|
|
verbose_name_plural = _("Trip updates")
|
|
|
|
ordering = ("start_date", "trip",)
|
|
|
|
unique_together = ("trip", "start_date", "start_time",)
|
|
|
|
|
|
|
|
|
|
|
|
class StopTimeUpdate(models.Model):
|
|
|
|
trip_update = models.ForeignKey(
|
|
|
|
to="TripUpdate",
|
|
|
|
on_delete=models.CASCADE,
|
|
|
|
verbose_name=_("Trip update"),
|
|
|
|
related_name="stop_time_updates",
|
|
|
|
)
|
|
|
|
|
|
|
|
stop_time = models.OneToOneField(
|
|
|
|
to="StopTime",
|
|
|
|
on_delete=models.CASCADE,
|
|
|
|
verbose_name=_("Stop time"),
|
|
|
|
related_name="update",
|
|
|
|
primary_key=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
arrival_delay = models.DurationField(
|
|
|
|
verbose_name=_("Arrival delay"),
|
|
|
|
)
|
|
|
|
|
|
|
|
arrival_time = models.DateTimeField(
|
|
|
|
verbose_name=_("Arrival time"),
|
|
|
|
)
|
|
|
|
|
|
|
|
departure_delay = models.DurationField(
|
|
|
|
verbose_name=_("Departure delay"),
|
|
|
|
)
|
|
|
|
|
|
|
|
departure_time = models.DateTimeField(
|
|
|
|
verbose_name=_("Departure time"),
|
|
|
|
)
|
|
|
|
|
|
|
|
schedule_relationship = models.IntegerField(
|
|
|
|
verbose_name=_("Schedule relationship"),
|
2024-02-06 07:01:56 +00:00
|
|
|
choices=StopScheduleRelationship,
|
|
|
|
default=StopScheduleRelationship.SCHEDULED,
|
2024-02-04 21:20:09 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return str(self.trip_update)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
verbose_name = _("Stop time update")
|
|
|
|
verbose_name_plural = _("Stop time updates")
|
|
|
|
ordering = ("trip_update", "stop_time",)
|
|
|
|
unique_together = ("trip_update", "stop_time",)
|