backend/passfinder/events/models.py

290 lines
9.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from django.contrib.postgres.fields import ArrayField
from django.db import models
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from rest_framework.serializers import ListSerializer, FloatField
from polymorphic.models import PolymorphicModel
from passfinder.utils.choices import count_max_length
class OIDModel(models.Model):
oid = models.CharField(primary_key=True, max_length=24, unique=True)
class Meta:
abstract = True
class Region(OIDModel):
city = models.ForeignKey(
"City", null=True, related_name="regions", on_delete=models.CASCADE
)
title = models.CharField(max_length=250)
description = models.TextField()
description_title = models.CharField(max_length=250)
description_short = models.CharField(max_length=500)
url = models.URLField()
showcase_cards = models.JSONField(null=True)
def __str__(self):
return self.title
class RegionMedia(OIDModel):
file = models.FileField(upload_to="uploads/")
type = models.CharField(max_length=200)
region = models.ForeignKey("Region", related_name="media", on_delete=models.CASCADE)
class City(OIDModel):
title = models.CharField(max_length=250)
region = models.ForeignKey(
"Region", related_name="cities", null=True, on_delete=models.SET_NULL
)
lon = models.FloatField(default=0, db_index=True)
lat = models.FloatField(default=0, db_index=True)
@property
def location(self):
return [self.lat, self.lon]
def __str__(self):
return self.title
class Place(OIDModel):
address = models.CharField(max_length=250, null=True, blank=True)
parser_source = models.CharField(max_length=250)
city = models.ForeignKey(
"City", related_name="places", null=True, on_delete=models.SET_NULL
)
region = models.ForeignKey(
"Region", related_name="places", null=True, on_delete=models.SET_NULL
)
title = models.CharField(max_length=250)
description = models.TextField()
lon = models.FloatField(default=0, db_index=True)
lat = models.FloatField(default=0, db_index=True)
sites = ArrayField(models.CharField(max_length=250), null=True)
phones = ArrayField(models.CharField(max_length=250), null=True)
working_time = models.JSONField(null=True)
@property
def location(self):
return [self.lat, self.lon]
class Category(OIDModel):
name = models.CharField(max_length=500, unique=True)
description = models.TextField()
def __str__(self):
return self.name
class PointCategory(models.Model):
point = models.ForeignKey(
"BasePoint", related_name="categories", on_delete=models.CASCADE
)
category = models.ForeignKey(
"Category", related_name="points", on_delete=models.CASCADE
)
class Meta:
unique_together = ("point", "category")
class BasePoint(OIDModel, PolymorphicModel):
title = models.CharField(max_length=500)
parser_source = models.CharField(max_length=250, null=True, blank=True)
description = models.TextField()
city = models.ForeignKey(
"City", related_name="points", null=True, on_delete=models.SET_NULL
)
region = models.ForeignKey(
"Region", related_name="points", null=True, on_delete=models.SET_NULL
)
place = models.ForeignKey(
"Place", related_name="points", null=True, on_delete=models.SET_NULL
)
sort = models.IntegerField(default=0)
lat = models.FloatField(default=0, db_index=True)
lon = models.FloatField(default=0, db_index=True)
can_buy = models.BooleanField(default=True)
priority = models.BooleanField(default=False)
price = models.IntegerField(null=True)
@property
@extend_schema_field(
field=ListSerializer(child=FloatField(), min_length=2, max_length=2)
)
def location(self):
return [self.lat, self.lon]
@property
@extend_schema_field(
field=ListSerializer(child=FloatField(), min_length=2, max_length=2)
)
def location_dec(self):
return [float(format(self.lat, ".6f")), float(format(self.lon, ".6f"))]
@property
@extend_schema_field(field=OpenApiTypes.URI)
def icon(self):
if self.media:
return self.media.last().file.url
return ""
def __str__(self):
return self.title
class PointMedia(OIDModel):
file = models.FileField(upload_to="uploads/")
type = models.CharField(max_length=200)
point = models.ForeignKey(
"BasePoint", related_name="media", on_delete=models.CASCADE
)
class Event(BasePoint):
class EventType(models.TextChoices):
yarmarka = "fair", "ярмарка"
bulvar = "boulevard", "бульвар"
dostoprimechatelnost = "attraction", "достопримечательность"
excursii = "excursion", "экскурсия"
teatr = "theatre", "театр"
museum = "museum", "музей"
kino = "movie", "кино"
concert = "concert", "концерт"
spektatli = "plays", "спектакли"
artwork = "artwork", "произведение искусства"
shop = "shop", "торговый центр"
gallery = "gallery", "галерея"
theme_park = "theme_park", "тематический парк"
viewpoint = "viewpoint", "обзорная точка"
zoo = "zoo", "зоопарк"
other = "other", "другое"
address = models.CharField(max_length=250, null=True)
payment_method = models.CharField(max_length=250, null=True, blank=True)
type = models.CharField(
db_index=True,
choices=EventType.choices,
max_length=count_max_length(EventType),
)
age = models.CharField(
"Возрастное ограничение", max_length=50, blank=True, null=True
)
booking_link = models.URLField(null=True, blank=True)
discover_moscow_link = models.URLField(null=True, blank=True)
duration = models.IntegerField(blank=True, null=True)
ticket_price = models.IntegerField(blank=True, null=True)
schedule = models.JSONField(null=True)
extra_kwargs = models.JSONField(null=True)
class Hotel(BasePoint):
class HotelType(models.TextChoices):
hotel = "hotel", "отель"
hostel = "hostel", "хостел"
guest_house = "guest_house", "гостевой дом"
motel = "motel", "мотель"
apartment = "apartment", "квартира"
chalet = "chalet", "домик"
type = models.CharField(
db_index=True,
default=HotelType.hotel,
choices=HotelType.choices,
max_length=count_max_length(HotelType),
)
address = models.CharField(max_length=500, null=True, blank=True)
rooms = models.JSONField(null=True)
email = models.CharField(max_length=250, null=True, blank=True)
stars = models.IntegerField(null=True)
extra_kwargs = models.JSONField(null=True)
class HotelPhone(models.Model):
hotel = models.ForeignKey("Hotel", related_name="phones", on_delete=models.CASCADE)
name = models.CharField(max_length=50)
number = models.CharField(max_length=18)
class Restaurant(BasePoint):
class RestaurantType(models.TextChoices):
restaurant = "restaurant", "ресторан"
bar = "bar", "бар"
cafe = "cafe", "кафе"
type = models.CharField(
db_index=True,
default=RestaurantType.restaurant,
choices=RestaurantType.choices,
max_length=count_max_length(RestaurantType),
)
address = models.CharField(max_length=250, blank=True, null=True)
bill = models.IntegerField(null=True)
can_reserve = models.BooleanField(default=True)
avg_time_visit = models.IntegerField(null=True)
working_time = models.JSONField(null=True)
phones = ArrayField(models.CharField(max_length=18), null=True)
extra_kwargs = models.JSONField(null=True)
class UserRoute(models.Model):
user = models.ForeignKey(
"users.User", related_name="routes", on_delete=models.CASCADE
)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user}'s route"
class UserRouteDate(models.Model):
date = models.DateField()
route = models.ForeignKey(
"UserRoute", related_name="dates", on_delete=models.CASCADE
)
class Meta:
unique_together = ("date", "route")
class BaseUserRouteDatePoint(PolymorphicModel):
date = models.ForeignKey(
"UserRouteDate", related_name="points", on_delete=models.CASCADE
)
duration = models.IntegerField()
class UserRoutePoint(BaseUserRouteDatePoint):
type = "point"
point = models.ForeignKey("BasePoint", on_delete=models.CASCADE)
point_type = models.CharField(max_length=250)
def get_json(self):
return {
"type": "point",
"duration": self.duration,
"point": self.point.oid,
"point_name": self.point.title,
"point_type": self.point_type,
}
class UserRouteTransaction(BaseUserRouteDatePoint):
type = "transition"
distance = models.FloatField()
def get_json(self):
return {
"type": "transition",
"duration": self.duration,
"distance": self.distance,
}