feat: add regional_standard configuration and dynamic terminology context processor
This commit is contained in:
parent
efc0e3f955
commit
a1d9c2022c
7 changed files with 111 additions and 14 deletions
|
|
@ -14,7 +14,7 @@ from common.storages import PrivateMediaStorage
|
|||
private_storage = PrivateMediaStorage()
|
||||
|
||||
USAGE_TYPE_CHOICES = (
|
||||
('administrative', _('Administratif / Mairie')),
|
||||
('administrative', _('Administratif (Hôtel de Ville / Maison Communale / Mairie)')),
|
||||
('education', _('Enseignement / École / Crèche')),
|
||||
('sports', _('Sport & Équipement sportif')),
|
||||
('culture', _('Culture / Médiathèque / Musée')),
|
||||
|
|
@ -102,15 +102,15 @@ class PublicBuilding(AbstractGeoAsset):
|
|||
total_surface_m2 = models.FloatField(null=True, blank=True, verbose_name=_("Surface brute totale (m²)"))
|
||||
usable_surface_m2 = models.FloatField(null=True, blank=True, verbose_name=_("Surface utile (m²)"))
|
||||
|
||||
# Réglementation ERP
|
||||
is_erp = models.BooleanField(default=True, verbose_name=_("Établissement Recevant du Public (ERP)"))
|
||||
erp_category = models.CharField(max_length=10, choices=ERP_CATEGORY_CHOICES, null=True, blank=True, verbose_name=_("Catégorie ERP"))
|
||||
erp_type = models.CharField(max_length=10, choices=ERP_TYPE_CHOICES, null=True, blank=True, verbose_name=_("Type ERP"))
|
||||
# Réglementation & Accueil du Public
|
||||
is_erp = models.BooleanField(default=True, verbose_name=_("Accueil & Sécurité du Public (ERP / PMR)"))
|
||||
erp_category = models.CharField(max_length=10, choices=ERP_CATEGORY_CHOICES, null=True, blank=True, verbose_name=_("Catégorie d'accueil / ERP"))
|
||||
erp_type = models.CharField(max_length=10, choices=ERP_TYPE_CHOICES, null=True, blank=True, verbose_name=_("Type d'établissement / ERP"))
|
||||
max_capacity = models.IntegerField(null=True, blank=True, verbose_name=_("Jauge maximale d'accueil du public"))
|
||||
|
||||
# Diagnostics & Énergie
|
||||
dpe_rating = models.CharField(max_length=2, choices=DPE_RATING_CHOICES, null=True, blank=True, verbose_name=_("Diagnostic de Performance Énergétique (DPE)"))
|
||||
ges_rating = models.CharField(max_length=2, choices=DPE_RATING_CHOICES, null=True, blank=True, verbose_name=_("Émission de Gaz à Effet de Serre (GES)"))
|
||||
dpe_rating = models.CharField(max_length=2, choices=DPE_RATING_CHOICES, null=True, blank=True, verbose_name=_("Performance Énergétique (PEB / DPE / EPC)"))
|
||||
ges_rating = models.CharField(max_length=2, choices=DPE_RATING_CHOICES, null=True, blank=True, verbose_name=_("Émissions de Carbone & GES"))
|
||||
has_asbestos_diag = models.BooleanField(default=False, verbose_name=_("Diagnostic Amiante réalisé"))
|
||||
has_lead_diag = models.BooleanField(default=False, verbose_name=_("Diagnostic Plomb réalisé"))
|
||||
pmr_accessible = models.BooleanField(default=False, verbose_name=_("Accessible PMR"))
|
||||
|
|
|
|||
|
|
@ -36,20 +36,20 @@
|
|||
<span class="badge bg-primary-subtle text-primary border">{{ building.get_usage_type_display }}</span>
|
||||
<span class="badge bg-success-subtle text-success border">{{ building.get_building_status_display }}</span>
|
||||
{% if building.is_erp %}
|
||||
<span class="badge bg-info-subtle text-info border">ERP (Catégorie {{ building.erp_category|default:"-" }})</span>
|
||||
<span class="badge bg-info-subtle text-info border">{{ regional_terms.public_access_short }} (Cat. {{ building.erp_category|default:"-" }})</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 text-md-end mt-3 mt-md-0">
|
||||
{% if building.dpe_rating %}
|
||||
<div class="d-inline-block text-center me-3">
|
||||
<span class="d-block text-muted small">DPE</span>
|
||||
<span class="d-block text-muted small">{{ regional_terms.energy_diag_short }}</span>
|
||||
<span class="badge bg-success fs-5 px-3 py-2">Classe {{ building.dpe_rating }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if building.ges_rating %}
|
||||
<div class="d-inline-block text-center">
|
||||
<span class="d-block text-muted small">GES</span>
|
||||
<span class="d-block text-muted small">{{ regional_terms.carbon_diag_short }}</span>
|
||||
<span class="badge bg-primary fs-5 px-3 py-2">Classe {{ building.ges_rating }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
@ -100,7 +100,7 @@
|
|||
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm h-100">
|
||||
<div class="card-header bg-light fw-bold"><i class="bi bi-rulers me-2"></i>{% translate "Caractéristiques physiques & ERP" %}</div>
|
||||
<div class="card-header bg-light fw-bold"><i class="bi bi-rulers me-2"></i>{% translate "Caractéristiques physiques &" %} {{ regional_terms.public_access_short }}</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-borderless mb-0">
|
||||
<tr>
|
||||
|
|
@ -116,8 +116,8 @@
|
|||
<td>{{ building.usable_surface_m2|default:"-" }} m² / {{ building.total_surface_m2|default:"-" }} m²</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-muted">{% translate "Jauge ERP" %} :</th>
|
||||
<td>{{ building.max_capacity|default:"-" }} personnes</td>
|
||||
<th class="text-muted">{{ regional_terms.public_access_category }} :</th>
|
||||
<td>{{ building.erp_category|default:"-" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="text-muted">{% translate "Accessibilité PMR" %} :</th>
|
||||
|
|
|
|||
|
|
@ -152,4 +152,24 @@ def organization_info(request):
|
|||
'map_ortho_wms_url': getattr(settings, 'MAP_ORTHO_WMS_URL', ''),
|
||||
'map_ortho_wms_name': getattr(settings, 'MAP_ORTHO_WMS_NAME', ''),
|
||||
'map_ortho_wms_attribution': getattr(settings, 'MAP_ORTHO_WMS_ATTRIBUTION', ''),
|
||||
}
|
||||
|
||||
|
||||
def regional_terminology(request):
|
||||
"""
|
||||
Context processor providing regional terminology & standard definitions
|
||||
(e.g., PEB in Belgium vs DPE/GES in France) based on the user's UserConfig or system default.
|
||||
Makes 'regional_terms' and 'regional_standard' available in all templates.
|
||||
"""
|
||||
from .utils import get_regional_terms
|
||||
standard_code = getattr(settings, 'REGIONAL_STANDARD', 'BE')
|
||||
|
||||
if request.user.is_authenticated:
|
||||
user_config = getattr(request.user, 'config', None)
|
||||
if user_config and getattr(user_config, 'regional_standard', None):
|
||||
standard_code = user_config.regional_standard
|
||||
|
||||
return {
|
||||
'regional_standard': standard_code,
|
||||
'regional_terms': get_regional_terms(standard_code),
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 6.0.7 on 2026-07-26 17:39
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('common', '0004_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='userconfig',
|
||||
name='regional_standard',
|
||||
field=models.CharField(choices=[('BE', 'Belgique (PEB, Maison Communale / Hôtel de Ville, Sécurité PMR)'), ('FR', 'France (DPE, GES, Mairie, Normes ERP)'), ('INT', 'International / Générique')], default='BE', help_text='Définit la terminologie et les normes réglementaires adaptées à la région.', max_length=10, verbose_name='Norme régionale & vocabulaire'),
|
||||
),
|
||||
]
|
||||
|
|
@ -110,6 +110,18 @@ class UserConfig(models.Model):
|
|||
help_text="Limite les raccourcis et les compteurs de la page d'accueil aux contrats pour lesquels l'utilisateur dispose de permissions explicites.",
|
||||
)
|
||||
generic_email = models.EmailField(blank=True, null=True) # Email générique de l'utilisateur
|
||||
REGIONAL_STANDARD_CHOICES = [
|
||||
('BE', 'Belgique (PEB, Maison Communale / Hôtel de Ville, Sécurité PMR)'),
|
||||
('FR', 'France (DPE, GES, Mairie, Normes ERP)'),
|
||||
('INT', 'International / Générique'),
|
||||
]
|
||||
regional_standard = models.CharField(
|
||||
max_length=10,
|
||||
choices=REGIONAL_STANDARD_CHOICES,
|
||||
default='BE',
|
||||
verbose_name="Norme régionale & vocabulaire",
|
||||
help_text="Définit la terminologie et les normes réglementaires adaptées à la région.",
|
||||
)
|
||||
hide_intervention_map_by_default = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name="Masquer la carte des interventions par défaut",
|
||||
|
|
|
|||
|
|
@ -116,4 +116,49 @@ def get_short_name(user):
|
|||
first = getattr(user, "first_name", "") or ""
|
||||
last = getattr(user, "last_name", "") or ""
|
||||
initial = (last[0].upper() + ".") if last else ""
|
||||
return f"{first} {initial}".strip()
|
||||
return f"{first} {initial}".strip()
|
||||
|
||||
|
||||
REGIONAL_TERMINOLOGY = {
|
||||
'BE': {
|
||||
'regional_standard_name': 'Belgique (PEB / Maison Communale / Sécurité PMR)',
|
||||
'admin_building': 'Hôtel de Ville / Maison Communale',
|
||||
'energy_diag_short': 'PEB',
|
||||
'energy_diag_full': 'Performance Énergétique des Bâtiments (PEB)',
|
||||
'carbon_diag_short': 'Bilan Carbone',
|
||||
'carbon_diag_full': 'Émissions de Carbone / Bilan Énergétique',
|
||||
'public_access_short': 'Accès public & PMR',
|
||||
'public_access_full': 'Accueil & Sécurité du Public (Normes PMR)',
|
||||
'public_access_category': 'Catégorie d\'accueil',
|
||||
'public_access_type': 'Type d\'affectation',
|
||||
},
|
||||
'FR': {
|
||||
'regional_standard_name': 'France (DPE / GES / Mairie / ERP)',
|
||||
'admin_building': 'Mairie / Hôtel de Ville',
|
||||
'energy_diag_short': 'DPE',
|
||||
'energy_diag_full': 'Diagnostic de Performance Énergétique (DPE)',
|
||||
'carbon_diag_short': 'GES',
|
||||
'carbon_diag_full': 'Émissions de Gaz à Effet de Serre (GES)',
|
||||
'public_access_short': 'ERP',
|
||||
'public_access_full': 'Établissement Recevant du Public (ERP)',
|
||||
'public_access_category': 'Catégorie ERP',
|
||||
'public_access_type': 'Type ERP',
|
||||
},
|
||||
'INT': {
|
||||
'regional_standard_name': 'International / Générique',
|
||||
'admin_building': 'Bâtiment Administratif / Hôtel de Ville',
|
||||
'energy_diag_short': 'PEB / DPE',
|
||||
'energy_diag_full': 'Performance Énergétique (PEB / DPE / EPC)',
|
||||
'carbon_diag_short': 'Émissions Carbone',
|
||||
'carbon_diag_full': 'Bilan Carbone & Émissions',
|
||||
'public_access_short': 'Accès Public',
|
||||
'public_access_full': 'Bâtiment d\'Accueil du Public (ERP / PMR)',
|
||||
'public_access_category': 'Capacité d\'accueil',
|
||||
'public_access_type': 'Type d\'établissement',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def get_regional_terms(standard_code='BE'):
|
||||
"""Returns regional terminology dictionary for a given standard code ('BE', 'FR', 'INT')."""
|
||||
return REGIONAL_TERMINOLOGY.get(standard_code or 'BE', REGIONAL_TERMINOLOGY['BE'])
|
||||
|
|
@ -38,6 +38,7 @@ SECRET_KEY = getenv("SECRET_KEY")
|
|||
DEBUG = getenv("DEBUG") == "True"
|
||||
|
||||
ROOT_URL = getenv("ROOT_URL", "http://localhost:8000")
|
||||
REGIONAL_STANDARD = getenv("REGIONAL_STANDARD", "BE")
|
||||
|
||||
ALLOWED_HOSTS = getenv("ALLOWED_HOSTS").split(',')
|
||||
CSRF_TRUSTED_ORIGINS = getenv("CSRF_TRUSTED_ORIGINS").split(',')
|
||||
|
|
@ -111,6 +112,7 @@ TEMPLATES = [
|
|||
'common.context_processors.current_app_view',
|
||||
'common.context_processors.environment_info',
|
||||
'common.context_processors.organization_info',
|
||||
'common.context_processors.regional_terminology',
|
||||
'notifications.context_processors.unread_notifications_count',
|
||||
],
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue