Skip to content

Commit

Permalink
Merge branch 'master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
marcantoinedupre authored Dec 15, 2023
2 parents 06bb9f8 + 749a2b1 commit a7085b8
Show file tree
Hide file tree
Showing 35 changed files with 539 additions and 109 deletions.
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ CHANGELOG
**Improvements**

- Add rules fixture on sensitive area (#3470)
- Change condition on signage & blade to select many of them (#3847)

**Documentation**

Expand Down
2 changes: 1 addition & 1 deletion geotrek/api/tests/test_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@
])

SIGNAGE_DETAIL_JSON_STRUCTURE = sorted([
'id', 'attachments', 'blades', 'code', 'condition', 'description', 'eid',
'id', 'attachments', 'blades', 'code', 'condition', 'conditions', 'description', 'eid',
'geometry', 'implantation_year', 'name', 'printed_elevation', 'sealing',
'provider', 'structure', 'type', 'uuid'
])
Expand Down
15 changes: 14 additions & 1 deletion geotrek/api/v2/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1406,15 +1406,28 @@ class Meta:
model = signage_models.Blade
fields = ('id', 'number', 'color', 'direction', 'lines')

class SignageConditionSerializer(DynamicFieldsMixin, serializers.ModelSerializer):

class Meta:
model = signage_models.SignageCondition
fields = ('id', 'label', 'structure')

class SignageSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
geometry = geo_serializers.GeometryField(read_only=True, source="geom3d_transformed", precision=7)
structure = serializers.CharField(source='structure.name')
attachments = AttachmentSerializer(many=True)
blades = BladeSerializer(source='blades_set', many=True)
condition = serializers.SerializerMethodField(
help_text=_("This field is deprecated and will be removed in next releases. Please start using 'conditions'")
)

def get_condition(self, obj):
condition = obj.conditions.first()
return condition.pk if condition else None

class Meta:
model = signage_models.Signage
fields = ('id', 'attachments', 'blades', 'code', 'condition', 'description', 'eid',
fields = ('id', 'attachments', 'blades', 'code', 'condition', 'conditions', 'description', 'eid',
'geometry', 'implantation_year', 'name', 'printed_elevation', 'provider', 'sealing',
'structure', 'type', 'uuid')

Expand Down
1 change: 1 addition & 0 deletions geotrek/api/v2/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
router.register('signage_sealing', api_views.SealingViewSet, basename='signage-sealing')
router.register('signage_color', api_views.ColorViewSet, basename='signage-color')
router.register('signage_direction', api_views.DirectionViewSet, basename='signage-direction')
router.register('signage_condition', api_views.SignageConditionViewSet, basename='signage-condition')
router.register('hdviewpoint', api_views.HDViewPointViewSet, basename='hdviewpoint')


Expand Down
2 changes: 1 addition & 1 deletion geotrek/api/v2/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
if 'geotrek.infrastructure' in settings.INSTALLED_APPS:
from .infrastructure import InfrastructureTypeViewSet, InfrastructureViewSet, InfrastructureUsageDifficultyLevelViewSet, InfrastructureConditionViewSet, InfrastructureMaintenanceDifficultyLevelViewSet # noqa
if 'geotrek.signage' in settings.INSTALLED_APPS:
from .signage import SignageViewSet, SignageTypeViewSet, SealingViewSet, ColorViewSet, DirectionViewSet, BladeTypeViewSet # noqa
from .signage import SignageViewSet, SignageTypeViewSet, SignageConditionViewSet, SealingViewSet, ColorViewSet, DirectionViewSet, BladeTypeViewSet # noqa
if 'drf_yasg' in settings.INSTALLED_APPS:
from .swagger import schema_view # noqa

Expand Down
5 changes: 5 additions & 0 deletions geotrek/api/v2/views/signage.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ class SignageTypeViewSet(api_viewsets.GeotrekViewSet):
queryset = signage_models.SignageType.objects.all().order_by('pk')


class SignageConditionViewSet(api_viewsets.GeotrekViewSet):
serializer_class = api_serializers.SignageConditionSerializer
queryset = signage_models.SignageCondition.objects.all()


class DirectionViewSet(api_viewsets.GeotrekViewSet):
serializer_class = api_serializers.DirectionSerializer
queryset = signage_models.Direction.objects.all().order_by('pk')
Expand Down
6 changes: 3 additions & 3 deletions geotrek/infrastructure/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class BaseInfrastructureForm(TopologyForm):

class Meta(TopologyForm.Meta):
fields = TopologyForm.Meta.fields + \
['structure', 'name', 'description', 'type', 'condition', 'access', 'implantation_year', 'published']
['structure', 'name', 'description', 'type', 'access', 'implantation_year', 'published']
else:
class BaseInfrastructureForm(CommonForm):

Expand All @@ -30,7 +30,7 @@ def __init__(self, *args, **kwargs):

class Meta(CommonForm.Meta):
model = Infrastructure
fields = CommonForm.Meta.fields + ['geom', 'structure', 'name', 'description', 'type', 'condition', 'access',
fields = CommonForm.Meta.fields + ['geom', 'structure', 'name', 'description', 'type', 'access',
'implantation_year', 'published']


Expand All @@ -54,4 +54,4 @@ class InfrastructureForm(BaseInfrastructureForm):

class Meta(BaseInfrastructureForm.Meta):
model = Infrastructure
fields = BaseInfrastructureForm.Meta.fields + ['accessibility', 'maintenance_difficulty', 'usage_difficulty']
fields = BaseInfrastructureForm.Meta.fields + ['accessibility', 'maintenance_difficulty', 'usage_difficulty', 'condition']
7 changes: 3 additions & 4 deletions geotrek/infrastructure/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,6 @@ class BaseInfrastructure(BasePublishableMixin, Topology, StructureRelated):
access = models.ForeignKey(InfrastructureAccessMean,
verbose_name=_("Access mean"), blank=True, null=True,
on_delete=models.PROTECT)
condition = models.ForeignKey(InfrastructureCondition,
verbose_name=_("Condition"), blank=True, null=True,
on_delete=models.PROTECT)
implantation_year = models.PositiveSmallIntegerField(verbose_name=_("Implantation year"), null=True)
eid = models.CharField(verbose_name=_("External id"), max_length=1024, blank=True, null=True)
provider = models.CharField(verbose_name=_("Provider"), db_index=True, max_length=1024, blank=True)
Expand Down Expand Up @@ -176,7 +173,9 @@ class Infrastructure(BaseInfrastructure, GeotrekMapEntityMixin):
on_delete=models.PROTECT,
related_name='infrastructures_set')
accessibility = models.TextField(verbose_name=_("Accessibility"), blank=True)

condition = models.ForeignKey(InfrastructureCondition,
verbose_name=_("Condition"), blank=True, null=True,
on_delete=models.PROTECT)
geometry_types_allowed = ["LINESTRING", "POINT"]

class Meta:
Expand Down
28 changes: 17 additions & 11 deletions geotrek/maintenance/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
CompetenceEdgeFactory, WorkManagementEdgeFactory,
SignageManagementEdgeFactory)
from geotrek.outdoor.tests.factories import CourseFactory
from geotrek.signage.tests.factories import BladeFactory, SignageFactory
from geotrek.signage.tests.factories import BladeFactory, SignageFactory, SignageTypeFactory
from geotrek.signage.forms import SignageForm
from geotrek.signage.models import Signage
from geotrek.maintenance.tests.factories import (InterventionFactory, InfrastructureInterventionFactory,
InterventionDisorderFactory, InterventionStatusFactory, ManDayFactory,
Expand Down Expand Up @@ -260,29 +261,34 @@ def test_update_form_on_signage(self):
self.assertEqual(response.status_code, 302)

def test_update_signage(self):
"""Test updating signage also updates intervention"""
target_year = 2017
if settings.TREKKING_TOPOLOGY_ENABLED:
intervention = SignageInterventionFactory.create()
else:
intervention = SignageInterventionFactory.create(geom='SRID=2154;POINT (700000 6600000)')
signa = intervention.target
# Save infrastructure form
response = self.client.get(signa.get_update_url())
form = response.context['form']
data = form.initial
data['name_en'] = 'modified'
data['implantation_year'] = target_year
access_mean = InfrastructureAccessMeanFactory()
data['access'] = access_mean.pk
data = {
'name_en': "modified",
'implantation_year': target_year,
'type': SignageTypeFactory.create(),
"structure": StructureFactory.create(),
'access': access_mean.pk,
'manager': OrganismFactory.create().pk
}
if settings.TREKKING_TOPOLOGY_ENABLED:
data['topology'] = '{"paths": [%s]}' % PathFactory.create().pk
else:
data['geom'] = 'SRID=4326;POINT (2.0 6.6)'
data['manager'] = OrganismFactory.create().pk
response = self.client.post(signa.get_update_url(), data)
self.assertEqual(response.status_code, 302)
self.super_user = SuperUserFactory.create()
form = SignageForm(instance=signa, data=data, user=self.super_user)
self.assertTrue(form.is_valid(), form.errors)
form.save()
intervention.refresh_from_db()

# Check that intervention was not deleted (bug #783)
intervention = Intervention.objects.first()
self.assertFalse(intervention.deleted)
self.assertEqual(str(intervention.target.access), access_mean.label)
self.assertEqual(intervention.target.name, 'modified')
Expand Down
40 changes: 39 additions & 1 deletion geotrek/signage/admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from django.contrib import admin
from django.db.models import Q

from geotrek.common.mixins.actions import MergeActionMixin
from geotrek.signage.models import LinePictogram, SignageType, Color, Sealing, Direction, BladeType
from geotrek.signage.models import LinePictogram, SignageType, Color, Sealing, Direction, BladeType, SignageCondition


class ColorBladeAdmin(MergeActionMixin, admin.ModelAdmin):
Expand Down Expand Up @@ -128,9 +129,46 @@ def get_list_filter(self, request):
return ('structure', )


class SignageConditionAdmin(MergeActionMixin, admin.ModelAdmin):
search_fields = ('label', 'structure__name')
merge_field = "label"

def get_queryset(self, request):
"""
filter objects by structure
"""
qs = super().get_queryset(request)
if not request.user.has_perm('authent.can_bypass_structure'):
qs = qs.filter(Q(structure=request.user.profile.structure) | Q(structure=None))
return qs

def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'structure':
if not request.user.has_perm('authent.can_bypass_structure'):
return None
kwargs['initial'] = request.user.profile.structure
return db_field.formfield(**kwargs)

def save_model(self, request, obj, form, change):
if not request.user.has_perm('authent.can_bypass_structure'):
obj.structure = request.user.profile.structure
obj.save()

def get_list_display(self, request):
if not request.user.has_perm('authent.can_bypass_structure'):
return ('label', )
return ('label', 'structure')

def get_list_filter(self, request):
if not request.user.has_perm('authent.can_bypass_structure'):
return ()
return ('structure',)


admin.site.register(SignageType, SignageTypeAdmin)
admin.site.register(Color, ColorBladeAdmin)
admin.site.register(Sealing, SealingAdmin)
admin.site.register(Direction, DirectionBladeAdmin)
admin.site.register(BladeType, BladeTypeAdmin)
admin.site.register(LinePictogram, LinePictogramAdmin)
admin.site.register(SignageCondition, SignageConditionAdmin)
4 changes: 2 additions & 2 deletions geotrek/signage/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SignageFilterSet(AltimetryPointFilterSet, ValidTopologyFilterSet, ZoningFi

class Meta(StructureRelatedFilterSet.Meta):
model = Signage
fields = StructureRelatedFilterSet.Meta.fields + ['type', 'condition', 'implantation_year', 'intervention_year',
fields = StructureRelatedFilterSet.Meta.fields + ['type', 'conditions', 'implantation_year', 'intervention_year',
'published', 'code', 'printed_elevation', 'manager',
'sealing', 'access', 'provider']

Expand All @@ -63,4 +63,4 @@ def __init__(self, *args, **kwargs):

class Meta(MapEntityFilterSet.Meta):
model = Blade
fields = MapEntityFilterSet.Meta.fields + ['structure', 'number', 'direction', 'type', 'color', 'condition']
fields = MapEntityFilterSet.Meta.fields + ['structure', 'number', 'direction', 'type', 'color', 'conditions']
10 changes: 5 additions & 5 deletions geotrek/signage/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class BaseBladeForm(CommonForm):
'number',
'direction',
'type',
'condition',
'conditions',
'color',
Fieldset(_('Lines')),
)
Expand All @@ -57,7 +57,7 @@ class BaseBladeForm(CommonForm):
'number',
'direction',
'type',
'condition',
'conditions',
'color',
)
]
Expand Down Expand Up @@ -107,7 +107,7 @@ def _set_number_field_initial_value(self):

class Meta:
model = Blade
fields = ['id', 'number', 'direction', 'type', 'condition', 'color']
fields = ['id', 'number', 'direction', 'type', 'conditions', 'color']


if settings.TREKKING_TOPOLOGY_ENABLED:
Expand Down Expand Up @@ -168,7 +168,7 @@ class SignageForm(BaseSignageForm):
'name',
'description',
'type',
'condition',
'conditions',
'implantation_year',
'published',
'code',
Expand All @@ -181,4 +181,4 @@ class SignageForm(BaseSignageForm):

class Meta(BaseInfrastructureForm.Meta):
model = Signage
fields = BaseInfrastructureForm.Meta.fields + ['code', 'printed_elevation', 'manager', 'sealing', 'access']
fields = BaseInfrastructureForm.Meta.fields + ['code', 'conditions', 'printed_elevation', 'manager', 'sealing', 'access']
30 changes: 17 additions & 13 deletions geotrek/signage/management/commands/loadsignage.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
from geotrek.authent.models import Structure
from geotrek.common.models import Organism
from geotrek.core.models import Topology
from geotrek.signage.models import Sealing, Signage, SignageType
from geotrek.infrastructure.models import InfrastructureCondition
from geotrek.signage.models import Sealing, Signage, SignageType, SignageCondition
from django.conf import settings


Expand Down Expand Up @@ -109,7 +108,7 @@ def handle(self, *args, **options):
break
if not self.check_fields_available_with_default(available_fields, field_name, default_name, 'name'):
break
if not self.check_fields_available_without_default(available_fields, field_condition_type, 'condition'):
if not self.check_fields_available_without_default(available_fields, field_condition_type, 'conditions'):
break
if not self.check_fields_available_without_default(available_fields, field_manager, 'manager'):
break
Expand Down Expand Up @@ -154,11 +153,11 @@ def handle(self, *args, **options):

condition = feature.get(field_condition_type) if field_condition_type in available_fields else default_condition_type
if condition:
condition_type, created = InfrastructureCondition.objects.get_or_create(label=condition, structure=structure if use_structure else None)
signage_condition, created = SignageCondition.objects.get_or_create(label=condition, structure=structure if use_structure else None)
if created and verbosity:
self.stdout.write("- Condition Type '{}' created".format(condition_type))
self.stdout.write("- Condition Type '{}' created".format(signage_condition))
else:
condition_type = None
signage_condition = None

sealing = feature.get(field_sealing) if field_sealing in available_fields else default_sealing
if sealing:
Expand Down Expand Up @@ -194,7 +193,7 @@ def handle(self, *args, **options):
fields_to_integrate = {
'type': signage_type,
'name': name,
'condition': condition_type,
'conditions': [signage_condition] if signage_condition else [],
'structure': structure,
'description': description,
'implantation_year': year,
Expand All @@ -217,31 +216,36 @@ def handle(self, *args, **options):
def create_signage(self, geometry, fields_to_integrate, verbosity):

with transaction.atomic():
conditions = fields_to_integrate.pop('conditions')
if fields_to_integrate['eid']:
eid = fields_to_integrate.pop('eid')
infra, created = Signage.objects.update_or_create(
signage, created = Signage.objects.update_or_create(
eid=eid,
defaults=fields_to_integrate
)
if conditions:
signage.conditions.set(conditions)
if verbosity > 0 and not created:
self.stdout.write("Update : %s with eid %s" % (fields_to_integrate['name'], eid))
else:
infra = Signage.objects.create(**fields_to_integrate)
signage = Signage.objects.create(**fields_to_integrate)
if conditions:
signage.conditions.set(conditions)
if settings.TREKKING_TOPOLOGY_ENABLED:
try:
geometry = geometry.transform(settings.API_SRID, clone=True)
geometry.coord_dim = 2
serialized = '{"lng": %s, "lat": %s}' % (geometry.x, geometry.y)
topology = Topology.deserialize(serialized)
infra.mutate(topology)
signage.mutate(topology)
except IndexError:
raise GEOSException('Invalid Geometry type.')
else:
if geometry.geom_type != 'Point':
raise GEOSException('Invalid Geometry type.')
geometry = geometry.transform(settings.SRID, clone=True)
infra.geom = Point(geometry.x, geometry.y)
infra.save()
signage.geom = Point(geometry.x, geometry.y)
signage.save()
self.counter += 1

return infra
return signage
Loading

0 comments on commit a7085b8

Please sign in to comment.