Skip to content

Commit

Permalink
Merge pull request #1760 from Nayor/fix/#1226-check-climbing-indoor-r…
Browse files Browse the repository at this point in the history
…oute-association

fix: #1226 prevent climbing indoor waypoints association with routes
  • Loading branch information
brunobesson authored Mar 8, 2024
2 parents 0cc21bb + 65f9469 commit 0903295
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 35 deletions.
96 changes: 75 additions & 21 deletions c2corg_api/tests/views/test_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,18 @@ def test_get(self):
linked_waypoints = associations.get('waypoints')
self.assertEqual(2, len(linked_waypoints))
self.assertEqual(
self.waypoint.document_id, linked_waypoints[0].get('document_id'))
self.waypoint.document_id,
linked_waypoints[0].get('document_id'))
self.assertEqual(
self.waypoint3.document_id, linked_waypoints[1].get('document_id'))
self.waypoint_tc.document_id,
linked_waypoints[1].get('document_id'))
# check waypoint data in listing
self.assertEqual(
self.waypoint.locales[0].access_period,
linked_waypoints[0].get('locales')[0].get('access_period')
)
self.assertEqual(
self.waypoint3.public_transportation_rating,
self.waypoint_tc.public_transportation_rating,
linked_waypoints[1].get('public_transportation_rating')
)
self.assertIn('geometry', linked_waypoints[0])
Expand Down Expand Up @@ -257,6 +259,41 @@ def test_post_empty_activities_and_associations_error(self):
self.assertError(
errors, 'associations.waypoints', 'at least one waypoint required')

def test_climing_indoor_waypoint_association(self):
body_post = {
'main_waypoint_id': self.waypoint_climbing_indoor.document_id,
'activities': ['hiking', 'skitouring'],
'elevation_min': 700,
'elevation_max': 1500,
'height_diff_up': 800,
'height_diff_down': 800,
'durations': ['1'],
'geometry': {
'id': 5678, 'version': 6789,
'geom_detail':
'{"type": "LineString", "coordinates": ' +
'[[635956, 5723604], [635966, 5723644]]}'
},
'locales': [
{'lang': 'en', 'title': 'Some nice loop',
'gear': 'shoes'}
],
'associations': {
'waypoints': [
{'document_id': self.waypoint_climbing_indoor.document_id}
]
}
}
body = self.post_error(body_post)
errors = body.get('errors')
self.assertEqual(len(errors), 3)
self.assertEqual(
errors[0].get('description'),
'climbing_indoor waypoint cannot be linked to a route')
self.assertEqual(
errors[0].get('name'),
'associations.climbing_indoor_waypoint')

def test_post_invalid_activity(self):
body_post = {
'activities': ['cooking'],
Expand Down Expand Up @@ -685,7 +722,7 @@ def test_post_main_wp_without_association(self):
{'lang': 'en', 'title': 'Some nice loop',
'gear': 'shoes'}
],
# no association for the main waypoint
# no association to the main waypoint
'associations': {
'waypoints': [
{'document_id': self.waypoint2.document_id}
Expand All @@ -696,7 +733,7 @@ def test_post_main_wp_without_association(self):
errors = body.get('errors')
self.assertEqual(len(errors), 1)
self.assertError(
errors, 'main_waypoint_id', 'no association for the main waypoint')
errors, 'main_waypoint_id', 'no association to the main waypoint')

def test_put_wrong_document_id(self):
body = {
Expand Down Expand Up @@ -818,8 +855,10 @@ def test_put_success_all(self):
'[[635956, 5723604], [635976, 5723654]]}'
},
'associations': {
'waypoints': [{'document_id': self.waypoint.document_id},
{'document_id': self.waypoint3.document_id}]
'waypoints': [
{'document_id': self.waypoint.document_id},
{'document_id': self.waypoint_tc.document_id}
]
}
}
}
Expand Down Expand Up @@ -872,8 +911,10 @@ def test_put_success_figures_only(self):
'title_prefix': 'Should be ignored'}
],
'associations': {
'waypoints': [{'document_id': self.waypoint.document_id},
{'document_id': self.waypoint3.document_id}]
'waypoints': [
{'document_id': self.waypoint.document_id},
{'document_id': self.waypoint_tc.document_id}
]
}
}
}
Expand Down Expand Up @@ -913,8 +954,10 @@ def test_put_success_new_track_with_default_geom(self):
'{"type": "Point", "coordinates": [635000, 5723000]}'
},
'associations': {
'waypoints': [{'document_id': self.waypoint.document_id},
{'document_id': self.waypoint3.document_id}]
'waypoints': [
{'document_id': self.waypoint.document_id},
{'document_id': self.waypoint_tc.document_id}
]
}
}
}
Expand Down Expand Up @@ -944,7 +987,7 @@ def test_put_success_main_wp_changed(self):
'associations': {
'waypoints': [
{'document_id': self.waypoint2.document_id},
{'document_id': self.waypoint3.document_id}
{'document_id': self.waypoint_tc.document_id}
]
}
}
Expand Down Expand Up @@ -993,8 +1036,10 @@ def test_put_success_lang_only(self):
'version': self.locale_en.version}
],
'associations': {
'waypoints': [{'document_id': self.waypoint.document_id},
{'document_id': self.waypoint3.document_id}]
'waypoints': [
{'document_id': self.waypoint.document_id},
{'document_id': self.waypoint_tc.document_id}
]
}
}
}
Expand Down Expand Up @@ -1023,8 +1068,10 @@ def test_put_success_new_lang(self):
'description': '...', 'gear': 'si'}
],
'associations': {
'waypoints': [{'document_id': self.waypoint.document_id},
{'document_id': self.waypoint3.document_id}]
'waypoints': [
{'document_id': self.waypoint.document_id},
{'document_id': self.waypoint_tc.document_id}
]
}
}
}
Expand Down Expand Up @@ -1203,7 +1250,7 @@ def _add_test_data(self):
gear='paraglider'))
self.session.add(self.route4)

# add some associations
# waypoints
self.waypoint = Waypoint(
waypoint_type='climbing_outdoor', elevation=4,
geometry=DocumentGeometry(
Expand All @@ -1223,17 +1270,24 @@ def _add_test_data(self):
lang='en', title='Mont Granier 2 (en)', description='...',
access='yep'))
self.session.add(self.waypoint2)
self.waypoint3 = Waypoint(
self.waypoint_tc = Waypoint(
waypoint_type='access', elevation=1776,
public_transportation_rating='poor service',
geometry=DocumentGeometry(
geom='SRID=3857;POINT(778846 5580167)'))
self.waypoint3.locales.append(WaypointLocale(
self.waypoint_tc.locales.append(WaypointLocale(
lang='fr', title='Roche écroulée', description='...',
access='yep', access_period='hiver'
))
self.session.add(self.waypoint3)
self.session.add(self.waypoint_tc)
self.waypoint_climbing_indoor = Waypoint(
waypoint_type='climbing_indoor', elevation=1,
geometry=DocumentGeometry(
geom='SRID=3857;POINT(635956 5723604)'))
self.session.add(self.waypoint_climbing_indoor)
self.session.flush()

# associations
self._add_association(Association.create(
parent_document=self.route,
child_document=self.route4), user_id)
Expand All @@ -1244,7 +1298,7 @@ def _add_test_data(self):
parent_document=self.waypoint,
child_document=self.route), user_id)
self._add_association(Association.create(
parent_document=self.waypoint3,
parent_document=self.waypoint_tc,
child_document=self.route), user_id)

# add a map
Expand Down
2 changes: 1 addition & 1 deletion c2corg_api/views/route.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def validate_main_waypoint(is_on_create, request, **kwargs):

# no association found
request.errors.add(
'body', 'main_waypoint_id', 'no association for the main waypoint')
'body', 'main_waypoint_id', 'no association to the main waypoint')


def validate_required_associations(request, **kwargs):
Expand Down
50 changes: 37 additions & 13 deletions c2corg_api/views/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from c2corg_api.models.xreport import XREPORT_TYPE
from c2corg_api.models.route import ROUTE_TYPE
from c2corg_api.models.user_profile import USERPROFILE_TYPE
from c2corg_api.models.waypoint import WAYPOINT_TYPE
from c2corg_api.models.waypoint import WAYPOINT_TYPE, Waypoint
from c2corg_api.views.document_associations import get_first_column

from c2corg_api.models.common.associations import valid_associations
Expand Down Expand Up @@ -604,6 +604,22 @@ def _get_linked_document_ids(associations):
])


def _is_any_climbing_indoor_waypoint(associations_in):
""" Check if there is any climbing indoor waypoints in the linked waypoints
"""
waypoints_id = [doc['document_id'] for doc in associations_in['waypoints']]

# load the waypoint type for each linked waypoint
if waypoints_id:
query_waypoints_with_type = DBSession. \
query(Waypoint.waypoint_type). \
filter(Waypoint.document_id.in_(waypoints_id))
for waypoint in query_waypoints_with_type.all():
if waypoint.waypoint_type == 'climbing_indoor':
return True
return False


def _add_associations(
associations, associations_in, main_document_type,
document_key, other_document_type, errors):
Expand All @@ -624,18 +640,26 @@ def _add_associations(
errors.add(
'body', 'associations.' + document_key,
'invalid association type')
else:
if document_key == 'waypoints' and main_document_type != BOOK_TYPE:
is_parent = True
elif document_key == 'waypoint_children':
is_parent = False

associations[document_key] = [
{
'document_id': doc['document_id'],
'is_parent': is_parent
} for doc in associations_in[document_key]
]
return

if document_key == 'waypoints' and main_document_type == ROUTE_TYPE:
if _is_any_climbing_indoor_waypoint(associations_in):
errors.add(
'body',
'associations.climbing_indoor_waypoint',
'climbing_indoor waypoint cannot be linked to a route')
return
elif document_key == 'waypoints' and main_document_type != BOOK_TYPE:
is_parent = True
elif document_key == 'waypoint_children':
is_parent = False

associations[document_key] = [
{
'document_id': doc['document_id'],
'is_parent': is_parent
} for doc in associations_in[document_key]
]


def _is_parent_of_association(main_document_type, other_document_type):
Expand Down

0 comments on commit 0903295

Please sign in to comment.