330 lines
No EOL
12 KiB
Python
330 lines
No EOL
12 KiB
Python
# ----------------------
|
|
# Roads Models
|
|
# ----------------------
|
|
|
|
from django.contrib.gis.db import models
|
|
from django.contrib.postgres.fields import ArrayField
|
|
from django.urls import reverse
|
|
from django.utils.text import slugify
|
|
from django.utils.translation import get_language
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
import os
|
|
|
|
from assets.models import AbstractLocation, AbstractAsset, AbstractGeoAsset, AbstractAssetModel
|
|
from common.models import Municipality, Document
|
|
from common.storages import PrivateMediaStorage
|
|
|
|
from observations.models import Observation
|
|
|
|
private_storage = PrivateMediaStorage()
|
|
|
|
|
|
|
|
# Road Street
|
|
class RoadStreet(AbstractLocation):
|
|
geom = models.MultiPolygonField(srid=3812, null=True,blank=True)
|
|
municipality = models.ForeignKey(Municipality, on_delete=models.SET_NULL, null=True, blank=True, related_name="road_streets")
|
|
road_code = models.CharField(max_length=50, null=True, blank=True)
|
|
section_code = models.CharField(max_length=50, null=True, blank=True)
|
|
street_level = models.CharField(max_length=50, null=True, blank=True)
|
|
|
|
def get_active_assets(self):
|
|
roadways = self.roadways.filter(status='active')
|
|
sidewalks = self.sidewalks.filter(status='active')
|
|
furnitures = self.furnitures.filter(status='active')
|
|
|
|
return {
|
|
"roadways": roadways,
|
|
"sidewalks": sidewalks,
|
|
"furnitures": furnitures,
|
|
}
|
|
|
|
def get_all_assets(self):
|
|
roadways = self.roadways.all()
|
|
sidewalks = self.sidewalks.all()
|
|
furnitures = self.furnitures.all()
|
|
|
|
return {
|
|
"roadways": roadways,
|
|
"sidewalks": sidewalks,
|
|
"furnitures": furnitures,
|
|
}
|
|
|
|
def get_direct_child_assets(self):
|
|
roadways = self.roadways.all()
|
|
sidewalks = self.sidewalks.all()
|
|
furnitures = self.furnitures.all()
|
|
|
|
return {
|
|
"roadways": roadways,
|
|
"sidewalks": sidewalks,
|
|
"furnitures": furnitures,
|
|
}
|
|
|
|
def get_absolute_url(self):
|
|
return reverse("assets:roads_streets_detail", kwargs={"street_id": self.id})
|
|
|
|
|
|
def upload_to_roadstreet(instance, filename):
|
|
location = instance.street
|
|
code = slugify(location.code or "unknown") # Fallback si code est None
|
|
return os.path.join("assets_documents", "roads", code, filename)
|
|
|
|
ROAD_DOCUMENT_TYPE_CHOICES = (
|
|
('as_built', 'As Built'),
|
|
('other', 'Autre'),
|
|
)
|
|
class RoadStreetDocument(Document):
|
|
street = models.ForeignKey(RoadStreet, on_delete=models.CASCADE, related_name="documents", verbose_name="Associated Street")
|
|
file = models.FileField(upload_to=upload_to_roadstreet, storage=private_storage, verbose_name="Fichier", max_length=255)
|
|
thumbnail = models.ImageField(upload_to=upload_to_roadstreet, storage=private_storage, null=True, blank=True, max_length=255)
|
|
document_type = models.CharField(max_length=50, choices=ROAD_DOCUMENT_TYPE_CHOICES, default='other', verbose_name="Type de document")
|
|
|
|
|
|
|
|
|
|
QUALITY_LEVEL_CHOICES = (
|
|
(1, '1 - Très mauvais'),
|
|
(2, '2 - Mauvais'),
|
|
(3, '3 - Bon'),
|
|
(4, '4 - Très bon'),
|
|
(5, '5 - Excellent'),
|
|
)
|
|
|
|
|
|
|
|
# Roadway Model
|
|
class RoadwayModel(AbstractAssetModel):
|
|
speed_limit = models.IntegerField(null=True,blank=True)
|
|
|
|
|
|
ROAD_COATING_TYPE_CHOICES = (
|
|
('asphalt', 'Asphalt'),
|
|
('concrete', 'Concrete'),
|
|
('cobblestone', 'Cobblestone'),
|
|
('gravel', 'Gravel'),
|
|
('dirt', 'Dirt'),
|
|
('other', 'Other'),
|
|
)
|
|
|
|
|
|
# Roadway
|
|
class Roadway(AbstractGeoAsset):
|
|
coating_type = models.CharField(max_length=200, null=True,blank=True, choices=ROAD_COATING_TYPE_CHOICES)
|
|
model = models.ForeignKey(RoadwayModel, on_delete=models.SET_NULL, null=True, blank=True)
|
|
street = models.ForeignKey(RoadStreet, related_name="roadways", on_delete=models.PROTECT)
|
|
quality_level = models.IntegerField(null=True, blank=True, choices=QUALITY_LEVEL_CHOICES)
|
|
lanes = models.IntegerField(null=True, blank=True)
|
|
area = models.FloatField(null=True, blank=True)
|
|
geom = models.MultiPolygonField(srid=3812, null=True,blank=True)
|
|
|
|
class Meta:
|
|
verbose_name = "Roadway"
|
|
verbose_name_plural = "Roadways"
|
|
|
|
def get_absolute_url(self):
|
|
return reverse(
|
|
"assets:roads_assets_detail",
|
|
kwargs={"asset_model": self._meta.model_name, "asset_id": self.id},
|
|
)
|
|
|
|
|
|
|
|
# Sidewalk Model
|
|
class RoadSidewalkModel(AbstractAssetModel):
|
|
pass
|
|
|
|
|
|
SW_COATING_TYPE_CHOICES = (
|
|
('concrete', 'Concrete'),
|
|
('paving_stones', 'Paving Stones'),
|
|
('tiles20', 'Tiles 20x20'),
|
|
('tiles30', 'Tiles 30x30'),
|
|
('tiles40', 'Tiles 40x40'),
|
|
('tiles50', 'Tiles 50x50'),
|
|
('tiles', 'Tiles'),
|
|
('asphalt', 'Asphalt'),
|
|
('dolomite','Dolomie'),
|
|
('gravel', 'Gravel'),
|
|
('dirt', 'Dirt'),
|
|
('other', 'Other'),
|
|
)
|
|
|
|
# Sidewalk
|
|
class RoadSidewalk(AbstractGeoAsset):
|
|
coating_type = models.CharField(max_length=200, null=True,blank=True, choices=SW_COATING_TYPE_CHOICES)
|
|
model = models.ForeignKey(RoadSidewalkModel, on_delete=models.SET_NULL, null=True, blank=True)
|
|
street = models.ForeignKey(RoadStreet, related_name="sidewalks", on_delete=models.PROTECT)
|
|
quality_level = models.IntegerField(null=True, blank=True, choices=QUALITY_LEVEL_CHOICES)
|
|
area = models.FloatField(null=True, blank=True)
|
|
geom = models.MultiPolygonField(srid=3812, null=True,blank=True)
|
|
|
|
class Meta:
|
|
verbose_name = "Sidewalk"
|
|
verbose_name_plural = "Sidewalks"
|
|
|
|
def get_absolute_url(self):
|
|
return reverse(
|
|
"assets:roads_assets_detail",
|
|
kwargs={"asset_model": self._meta.model_name, "asset_id": self.id},
|
|
)
|
|
|
|
|
|
# Street Furniture Model
|
|
class RoadFurnitureModel(AbstractAssetModel):
|
|
color = models.CharField(max_length=200, null=True,blank=True)
|
|
ral = models.CharField(max_length=200, null=True,blank=True)
|
|
height = models.FloatField(null=True,blank=True)
|
|
width = models.FloatField(null=True,blank=True)
|
|
material = models.CharField(max_length=200, null=True,blank=True)
|
|
|
|
|
|
# Street Furniture
|
|
class RoadFurniture(AbstractGeoAsset):
|
|
model = models.ForeignKey(RoadFurnitureModel, on_delete=models.SET_NULL, null=True, blank=True)
|
|
street = models.ForeignKey(RoadStreet, related_name="furnitures", on_delete=models.PROTECT)
|
|
|
|
class Meta:
|
|
verbose_name = "Street Furniture"
|
|
verbose_name_plural = "Street Furnitures"
|
|
|
|
def get_absolute_url(self):
|
|
return reverse(
|
|
"assets:roads_assets_detail",
|
|
kwargs={"asset_model": self._meta.model_name, "asset_id": self.id},
|
|
)
|
|
|
|
|
|
|
|
|
|
ROAD_FUNCTION_CHOICES = (
|
|
('masterful', 'Magistrale'),
|
|
('plus', 'Plus'),
|
|
('confort', 'Confort'),
|
|
('other', 'Autre'),
|
|
)
|
|
|
|
# Roadway Functions
|
|
class RoadwayFunction(models.Model):
|
|
roadway = models.ForeignKey(Roadway, on_delete=models.CASCADE, related_name="functions")
|
|
pedestrian_function = models.CharField(max_length=200, null=True, blank=True, choices=ROAD_FUNCTION_CHOICES)
|
|
bicycle_function = models.CharField(max_length=200, null=True, blank=True, choices=ROAD_FUNCTION_CHOICES)
|
|
public_transport_function = models.CharField(max_length=200, null=True, blank=True, choices=ROAD_FUNCTION_CHOICES)
|
|
private_motorized_function = models.CharField(max_length=200, null=True, blank=True, choices=ROAD_FUNCTION_CHOICES)
|
|
|
|
class Meta:
|
|
verbose_name = "Roadway Function"
|
|
verbose_name_plural = "Roadway Functions"
|
|
|
|
|
|
|
|
|
|
CONCRETE_BLOCK_FUNCTION_CHOICES = (
|
|
('protection', _('Protection Asset')),
|
|
('antiterrorist', _('Antiterroriste')),
|
|
('parking_neutralization', _('Neutralisation stationnement')),
|
|
('road_safety', _('Sécurité routière')),
|
|
('public_space', _('Espace public')),
|
|
('construction', _('Chantier')),
|
|
('unidentified', _('Non identifié')),
|
|
)
|
|
|
|
CONCRETE_BLOCK_ACTION_CHOICES = (
|
|
('keep', _('Maintenir')),
|
|
('remove', _('Enlever')),
|
|
('replace', _('Remplacer')),
|
|
)
|
|
|
|
# Road Concrete blocks Set
|
|
class RoadConcreteBlockSet(AbstractGeoAsset):
|
|
address = models.CharField(max_length=2048, null=True, blank=True)
|
|
main_function = models.CharField(max_length=200, null=True, blank=True, choices=CONCRETE_BLOCK_FUNCTION_CHOICES)
|
|
secondary_functions = ArrayField(models.CharField(max_length=200, choices=CONCRETE_BLOCK_FUNCTION_CHOICES), null=True, blank=True)
|
|
number_of_blocks = models.IntegerField(null=True, blank=True)
|
|
length = models.FloatField(null=True, blank=True)
|
|
recommended_action = models.CharField(max_length=2048, null=True, blank=True, choices=CONCRETE_BLOCK_ACTION_CHOICES)
|
|
priority_level = models.IntegerField(null=True, blank=True)
|
|
targeted_action_date = models.DateField(null=True, blank=True)
|
|
observation_source = models.ForeignKey(Observation, on_delete=models.SET_NULL, null=True, blank=True, related_name="concrete_block_sets")
|
|
|
|
def get_absolute_url(self):
|
|
return reverse(
|
|
'assets:roads_assets_detail',
|
|
kwargs={'asset_model': self._meta.model_name, 'asset_id': self.id},
|
|
)
|
|
|
|
def __str__(self):
|
|
return self.address if self.address else _("Road Concrete Block Set")
|
|
|
|
|
|
|
|
|
|
DRAIN_SOIL_TYPE_CHOICES = (
|
|
('concrete', _('Béton')),
|
|
('asphalt', _('Asphalte')),
|
|
('stone', _('Pierre')),
|
|
('concrete_slabs', _('Dalles en béton')),
|
|
('concrete_paving', _('Pavés en béton')),
|
|
('stone_slabs', _('Dalles en pierre')),
|
|
('stone_paving', _('Pavés en pierre')),
|
|
('concrete_grass', _('Béton/Gazon')),
|
|
('gravel', _('Gravier')),
|
|
('grass', _('Gazon')),
|
|
('earth', _('Terre')),
|
|
('other', _('Autre')),
|
|
('na', _('N/A')),
|
|
)
|
|
|
|
DRAIN_LOCATION_TYPE_CHOICES = (
|
|
('waterway', _("Filet d'eau")),
|
|
('sidewalk', _('Trottoir')),
|
|
('berme', _('Berme')),
|
|
('sidewalk_facade_to_road', _('Trottoir façade vers chaussée')),
|
|
('square', _('Place')),
|
|
('along_sidewalk', _('Le long du trottoir')),
|
|
('middle_road', _('Milieu chaussée')),
|
|
('other', _('Autre')),
|
|
('na', _('N/A')),
|
|
)
|
|
|
|
DRAIN_DEFECT_TYPE_CHOICES = (
|
|
('obstructed', _('Obstrué')),
|
|
('smell_cut_missing', _('Coupe-odeur manquant')),
|
|
('grate_broken', _('Grille cassée')),
|
|
('grate_missing', _('Grille manquante')),
|
|
('poor_water_flow', _('Mauvais écoulement')),
|
|
('other', _('Autre')),
|
|
)
|
|
|
|
|
|
# Road Drain Model
|
|
class RoadDrainModel(AbstractAssetModel):
|
|
pass
|
|
|
|
# Road Drain
|
|
class RoadDrain(AbstractGeoAsset):
|
|
street = models.ForeignKey(RoadStreet, related_name="drains", on_delete=models.SET_NULL, null=True, blank=True)
|
|
model = models.ForeignKey(RoadDrainModel, on_delete=models.SET_NULL, null=True, blank=True)
|
|
soil_type = models.CharField(max_length=200, null=True, blank=True, choices=DRAIN_SOIL_TYPE_CHOICES)
|
|
positionning_source = models.CharField(max_length=2048, null=True, blank=True)
|
|
positionning_note = models.TextField(null=True, blank=True)
|
|
positionning_date = models.DateField(null=True, blank=True)
|
|
drain_location_type = models.CharField(max_length=200, null=True, blank=True, choices=DRAIN_LOCATION_TYPE_CHOICES)
|
|
nearby_vegetation = models.BooleanField(null=True, blank=True)
|
|
possible_rooting = models.BooleanField(null=True, blank=True)
|
|
is_defect = models.BooleanField(null=True, blank=True)
|
|
defect_types = ArrayField(models.CharField(max_length=200, choices=DRAIN_DEFECT_TYPE_CHOICES), null=True, blank=True)
|
|
defect_note = models.TextField(null=True, blank=True)
|
|
related_image_type = models.CharField(max_length=1000, null=True, blank=True)
|
|
altitude = models.FloatField(null=True, blank=True)
|
|
geom = models.PointField(srid=3812, null=True, blank=True, dim=3)
|
|
|
|
def get_absolute_url(self):
|
|
return reverse(
|
|
'assets:roads_assets_detail',
|
|
kwargs={'asset_model': self._meta.model_name, 'asset_id': self.id},
|
|
)
|
|
|
|
def __str__(self):
|
|
return self.code if self.code else _("Road Drain") |