# -*- coding: utf-8 -*-
"""Akvo RSR is covered by the GNU Affero General Public License.
See more details in the license.txt file located at the root folder of the
Akvo RSR module. For additional details on the GNU license please
see < http://www.gnu.org/licenses/agpl.html >.
"""
from copy import deepcopy
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from akvo.codelists.store.default_codelists import SECTOR_CATEGORY
from akvo.utils import codelist_choices
from .models import (Organisation, OrganisationLocation,
Project, ProjectLocation, ProjectUpdate, ProjectUpdateLocation,
RecipientCountry)
from .m49 import M49_CODES, M49_HIERARCHY
ANY_CHOICE = (('', _('All')), )
[docs]def sectors():
sectors_list = []
for sector in codelist_choices(SECTOR_CATEGORY):
sectors_list.append(sector)
return sectors_list
[docs]def get_orgs():
orgs = list(Organisation.objects.all().values_list(
'id', 'name', flat=False))
return [('', _('All'))] + orgs
[docs]def remove_empty_querydict_items(request_get):
# querydicts are immutable
getvars = request_get.copy()
for k, v in list(getvars.items()):
if not v:
getvars.pop(k, None)
return getvars
[docs]def walk(node):
"""Walks the m49 tree and return countries"""
if isinstance(node, str):
return [node, ]
elif isinstance(node, int):
return walk(deepcopy(M49_HIERARCHY)[node])
else:
return (walk(node.pop()) + walk(node)) if node else []
[docs]def get_m49_filter(value, use_recipient_country=True):
"""Returns the location filter object based on value."""
countries = walk(deepcopy(M49_HIERARCHY)[int(value)])
countries_lower = [c.lower() for c in countries]
filter_ = Q(locations__country__iso_code__in=countries_lower)
if use_recipient_country:
filter_ = (Q(recipient_countries__country__in=countries) | filter_)
return filter_
[docs]def filter_m49(queryset, value):
"""Filters countries from the m49 list, for projects."""
if not value:
return queryset
else:
return queryset.filter(get_m49_filter(value))
[docs]def filter_m49_orgs(queryset, value):
"""Filters countries from the m49 list, for projects."""
if not value:
return queryset
countries = walk(deepcopy(M49_HIERARCHY)[int(value)])
return queryset.filter(locations__iati_country__in=countries)
[docs]def filter_title_or_subtitle(queryset, value):
"""Filters projects based on whether title or subtitle contains value."""
if not value:
return queryset
return queryset.filter(Q(title__icontains=value) | Q(subtitle__icontains=value))
[docs]def get_id_for_iso(i):
"""From an iso_code e.g. 'SE' get the identifier.
NOTE: If i is already an id, the parent id of the given id is returned!
"""
i = [k for k, v in M49_HIERARCHY.items() if i in v]
return None if not i else i.pop()
[docs]def get_location_hierarchy(location, locations=None):
"""Return the location > parent > ... > continent hierarchy for a location."""
if locations is None:
locations = [location]
# FIXME: Actually returns parent id, when location is already an id!
loc = get_id_for_iso(location)
if isinstance(loc, str) or loc == 1 or loc is None:
return locations
else:
locations.append(loc)
return get_location_hierarchy(loc, locations)
[docs]def location_choices(qs):
"""Return a filterd list of locations from M49_CODES based on queryset."""
country_ids = get_country_ids(qs)
location_ids = {
str(location)
for country_id in country_ids
for location in get_location_hierarchy(country_id)
}
# Add World to locations
location_ids.add("")
return [code for code in M49_CODES if code[0] in location_ids]
[docs]def get_country_ids(qs):
"""Return country ids for locations associated with the queryset items."""
country_ids = get_location_country_ids(qs)
if qs.model is Project:
country_ids = get_recipient_country_ids(qs) + country_ids
return set(country_ids)
[docs]def get_recipient_country_ids(projects):
"""Return countries based on recipient country of projects."""
countries = RecipientCountry.objects.filter(project__in=projects).values('country')
return [get_id_for_iso(country['country'].upper()) for country in countries]
[docs]def get_location_country_ids(qs):
"""Return countries for locations associated with objects in the queryset."""
if qs.model is Project:
location_model = ProjectLocation
elif qs.model is ProjectUpdate:
location_model = ProjectUpdateLocation
elif qs.model is Organisation:
location_model = OrganisationLocation
locations_qs = location_model.objects.filter(
location_target__in=qs
).values(
'country__iso_code',
).order_by('country__iso_code').distinct()
return [
get_id_for_iso(location['country__iso_code'].upper())
for location in locations_qs if location['country__iso_code']
]
[docs]def build_choices(qs):
"""Build choices from queryset and add an All option"""
return [('', _('All'))] + list(qs.values_list('id', 'name', flat=False))