Skip to content

Commit

Permalink
Change condition on signage & blade to select many of them
Browse files Browse the repository at this point in the history
  • Loading branch information
juggler31 committed Nov 13, 2023
1 parent dbec892 commit c818cd8
Show file tree
Hide file tree
Showing 25 changed files with 366 additions and 78 deletions.
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
8 changes: 7 additions & 1 deletion geotrek/api/v2/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1411,10 +1411,16 @@ class SignageSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
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):
return str(obj.conditions.first())

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
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 SignageSimpleFieldAdmin(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

Check warning on line 143 in geotrek/signage/admin.py

View check run for this annotation

Codecov / codecov/patch

geotrek/signage/admin.py#L140-L143

Added lines #L140 - L143 were not covered by tests

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)

Check warning on line 150 in geotrek/signage/admin.py

View check run for this annotation

Codecov / codecov/patch

geotrek/signage/admin.py#L146-L150

Added lines #L146 - L150 were not covered by tests

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

Check warning on line 155 in geotrek/signage/admin.py

View check run for this annotation

Codecov / codecov/patch

geotrek/signage/admin.py#L153-L155

Added lines #L153 - L155 were not covered by tests

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

Check warning on line 160 in geotrek/signage/admin.py

View check run for this annotation

Codecov / codecov/patch

geotrek/signage/admin.py#L158-L160

Added lines #L158 - L160 were not covered by tests

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

Check warning on line 165 in geotrek/signage/admin.py

View check run for this annotation

Codecov / codecov/patch

geotrek/signage/admin.py#L163-L165

Added lines #L163 - L165 were not covered by tests


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, SignageSimpleFieldAdmin)
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']
15 changes: 10 additions & 5 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,7 +153,7 @@ 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)
condition_type, 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))
else:
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': [condition_type] if condition_type else [],
'structure': structure,
'description': description,
'implantation_year': year,
Expand All @@ -217,16 +216,22 @@ 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(
eid=eid,
defaults=fields_to_integrate
)
if conditions:
infra.conditions.add(conditions)

Check warning on line 227 in geotrek/signage/management/commands/loadsignage.py

View check run for this annotation

Codecov / codecov/patch

geotrek/signage/management/commands/loadsignage.py#L227

Added line #L227 was not covered by tests
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)
if conditions:
for condition in conditions:
infra.conditions.add(condition.pk)
if settings.TREKKING_TOPOLOGY_ENABLED:
try:
geometry = geometry.transform(settings.API_SRID, clone=True)
Expand Down
84 changes: 84 additions & 0 deletions geotrek/signage/migrations/0036_auto_20231013_1326.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Generated by Django 3.2.21 on 2023-10-13 13:26

from django.db import migrations, models
import django.db.models.deletion


def copy_infrastructure_conditions(apps, schema_editor):

# Get conditions models to use them
InfrastructureCondition = apps.get_model('infrastructure', 'InfrastructureCondition')
SignageCondition = apps.get_model('signage', 'SignageCondition')
BladeCondition = apps.get_model('signage', 'BladeCondition')

Signage = apps.get_model('signage', 'Signage')
Blade = apps.get_model('signage', 'Blade')

# Copy InfrastructureCondition to SignageCondition and BladeCondition
for condition in InfrastructureCondition.objects.all():
SignageCondition.objects.get_or_create(label=condition.label)
BladeCondition.objects.get_or_create(label=condition.label)

# Associate signage condition to signage condition_tmp
for signage in Signage.objects.all():
if (signage.condition is not None):
signage_condition, created = SignageCondition.objects.get_or_create(label=signage.condition.label)
signage.condition_tmp.add(signage_condition)

# Associate blade condition to blade condition_tmp
for blade in Blade.objects.all():
if (blade.condition is not None):
blade_condition, created = BladeCondition.objects.get_or_create(label=blade.condition.label)
blade.condition_tmp.add(blade_condition)


class Migration(migrations.Migration):

dependencies = [
('authent', '0011_alter_userprofile_structure'),
('signage', '0035_delete_pictogramname'),
]

operations = [
migrations.CreateModel(
name='SignageCondition',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date_insert', models.DateTimeField(auto_now_add=True, verbose_name='Insertion date')),
('date_update', models.DateTimeField(auto_now=True, db_index=True, verbose_name='Update date')),
('label', models.CharField(max_length=250, verbose_name='Name')),
('structure', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='authent.structure', verbose_name='Related structure')),
],
options={
'verbose_name': 'Signage Condition',
'verbose_name_plural': 'Signage Conditions',
'ordering': ('label',),
},
),
migrations.CreateModel(
name='BladeCondition',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date_insert', models.DateTimeField(auto_now_add=True, verbose_name='Insertion date')),
('date_update', models.DateTimeField(auto_now=True, db_index=True, verbose_name='Update date')),
('label', models.CharField(max_length=250, verbose_name='Name')),
('structure', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='authent.structure', verbose_name='Related structure')),
],
options={
'verbose_name': 'Blade Condition',
'verbose_name_plural': 'Blade Conditions',
'ordering': ('label',),
},
),
migrations.AddField(
model_name='blade',
name='condition_tmp',
field=models.ManyToManyField(blank=True, related_name='blades', to='signage.BladeCondition', verbose_name='Condition'),
),
migrations.AddField(
model_name='signage',
name='condition_tmp',
field=models.ManyToManyField(blank=True, related_name='signages', to='signage.SignageCondition', verbose_name='Condition'),
),
migrations.RunPython(copy_infrastructure_conditions, reverse_code=migrations.RunPython.noop),
]
Loading

0 comments on commit c818cd8

Please sign in to comment.