Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/count service unit by division #294

Merged
merged 5 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 52 additions & 25 deletions services/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,32 @@
)


def resolve_divisions(divisions):
div_list = []

Check warning on line 214 in services/api.py

View check run for this annotation

Codecov / codecov/patch

services/api.py#L214

Added line #L214 was not covered by tests
for division_path in divisions:
if division_path.startswith("ocd-division"):
muni_ocd_id = division_path

Check warning on line 217 in services/api.py

View check run for this annotation

Codecov / codecov/patch

services/api.py#L217

Added line #L217 was not covered by tests
else:
ocd_id_base = r"[\w0-9~_.-]+"
match_re = r"(%s)/([\w_-]+):(%s)" % (ocd_id_base, ocd_id_base)
m = re.match(match_re, division_path, re.U)

Check warning on line 221 in services/api.py

View check run for this annotation

Codecov / codecov/patch

services/api.py#L219-L221

Added lines #L219 - L221 were not covered by tests
if not m:
raise ParseError("'division' must be of form 'muni/type:id'")

Check warning on line 223 in services/api.py

View check run for this annotation

Codecov / codecov/patch

services/api.py#L223

Added line #L223 was not covered by tests

arr = division_path.split("/")
muni_ocd_id = make_muni_ocd_id(arr.pop(0), "/".join(arr))
try:
div = AdministrativeDivision.objects.select_related("geometry").get(

Check warning on line 228 in services/api.py

View check run for this annotation

Codecov / codecov/patch

services/api.py#L225-L228

Added lines #L225 - L228 were not covered by tests
ocd_id=muni_ocd_id
)
except AdministrativeDivision.DoesNotExist:
raise ParseError(

Check warning on line 232 in services/api.py

View check run for this annotation

Codecov / codecov/patch

services/api.py#L231-L232

Added lines #L231 - L232 were not covered by tests
"administrative division with OCD ID '%s' not found" % muni_ocd_id
)
div_list.append(div)
return div_list

Check warning on line 236 in services/api.py

View check run for this annotation

Codecov / codecov/patch

services/api.py#L235-L236

Added lines #L235 - L236 were not covered by tests


class JSONAPISerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
super(JSONAPISerializer, self).__init__(*args, **kwargs)
Expand Down Expand Up @@ -300,7 +326,13 @@

class Meta:
model = ServiceNode
fields = "__all__"
exclude = (
"search_column_fi",
"search_column_sv",
"search_column_en",
"syllables_fi",
"service_reference",
)


class ServiceSerializer(TranslatedModelSerializer, JSONAPISerializer):
Expand All @@ -315,6 +347,16 @@
total += unit_count.count
ret["unit_count"]["municipality"][div_name] = unit_count.count
ret["unit_count"]["total"] = total

divisions = self.context.get("divisions", [])
include_fields = self.context.get("include", [])
if "unit_count_per_division" in include_fields and divisions:
ret["unit_count_per_division"] = {}
div_list = resolve_divisions(divisions)

Check warning on line 355 in services/api.py

View check run for this annotation

Codecov / codecov/patch

services/api.py#L354-L355

Added lines #L354 - L355 were not covered by tests
for div in div_list:
ret["unit_count_per_division"][div.name] = Unit.objects.filter(

Check warning on line 357 in services/api.py

View check run for this annotation

Codecov / codecov/patch

services/api.py#L357

Added line #L357 was not covered by tests
services=obj.pk, location__within=div.geometry.boundary
).count()
return ret

class Meta:
Expand Down Expand Up @@ -530,6 +572,13 @@
queryset = Service.objects.all()
serializer_class = ServiceSerializer

def get_serializer_context(self):
ret = super(ServiceViewSet, self).get_serializer_context()
query_params = self.request.query_params
division = query_params.get("division", "")
ret["divisions"] = [x.strip() for x in division.split(",") if x]
return ret

def get_queryset(self):
queryset = (
super(ServiceViewSet, self)
Expand Down Expand Up @@ -720,6 +769,7 @@
"accessibility_property_hash",
"identifier_hash",
"public",
"syllables_fi",
"search_column_fi",
"search_column_sv",
"search_column_en",
Expand Down Expand Up @@ -916,30 +966,7 @@
# Divisions can be specified with form:
# division=helsinki/kaupunginosa:kallio,vantaa/äänestysalue:5
d_list = filters["division"].lower().split(",")
div_list = []
for division_path in d_list:
if division_path.startswith("ocd-division"):
muni_ocd_id = division_path
else:
ocd_id_base = r"[\w0-9~_.-]+"
match_re = r"(%s)/([\w_-]+):(%s)" % (ocd_id_base, ocd_id_base)
m = re.match(match_re, division_path, re.U)
if not m:
raise ParseError("'division' must be of form 'muni/type:id'")

arr = division_path.split("/")
muni_ocd_id = make_muni_ocd_id(arr.pop(0), "/".join(arr))
try:
div = AdministrativeDivision.objects.select_related("geometry").get(
ocd_id=muni_ocd_id
)
except AdministrativeDivision.DoesNotExist:
raise ParseError(
"administrative division with OCD ID '%s' not found"
% muni_ocd_id
)
div_list.append(div)

div_list = resolve_divisions(d_list)

Check warning on line 969 in services/api.py

View check run for this annotation

Codecov / codecov/patch

services/api.py#L969

Added line #L969 was not covered by tests
if div_list:
mp = div_list.pop(0).geometry.boundary
for div in div_list:
Expand Down
23 changes: 21 additions & 2 deletions specification.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,25 @@ paths:
schema:
type: integer
example: 811
- $ref: "#/components/parameters/include_param"
- name: include
in: query
style: form
explode: false
description: "Enable count service by division with: "include=unit_count_per_division""
type: string
- name: division
in: query
style: form
explode: false
description: A comma-separated list of administrative divisions to be used when unit
counting by service and division. Use either full division ids or shorthands of the form
muni/type\:id
required: false
schema:
type: array
items:
type: string
example: ocd-division/country:fi/kunta:raisio
- $ref: "#/components/parameters/only_param"
- $ref: "#/components/parameters/geometry_param"
/service/:
Expand All @@ -313,7 +331,7 @@ paths:
- service
parameters:
- $ref: "#/components/parameters/page_param"
- $ref: "#/components/parameters/pagesize_param"
- $ref: "#/components/parameters/pagesize_param"
- name: id
in: query
style: form
Expand All @@ -324,6 +342,7 @@ paths:
items:
type: integer
example: 811,663

responses:
"200":
description: List of services, paginated
Expand Down
Loading