loko/streetup/assets/models/roads.py
2026-07-22 14:48:40 +02:00

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")