Passed
Pull Request — 2.x (#1960)
by Jordi
09:44 queued 03:35
created

senaite.core.locales   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 130
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 25
eloc 75
dl 0
loc 130
rs 10
c 0
b 0
f 0

3 Functions

Rating   Name   Duplication   Size   Complexity  
B get_states() 0 18 7
A get_countries() 0 2 1
A get_districts() 0 13 5

3 Methods

Rating   Name   Duplication   Size   Complexity  
A ajaxGetDistricts.__call__() 0 10 3
A ajaxGetStates.__call__() 0 10 3
B ajaxGetCountries.__call__() 0 29 6
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE.
4
#
5
# SENAITE.CORE is free software: you can redistribute it and/or modify it under
6
# the terms of the GNU General Public License as published by the Free Software
7
# Foundation, version 2.
8
#
9
# This program is distributed in the hope that it will be useful, but WITHOUT
10
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
# details.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# this program; if not, write to the Free Software Foundation, Inc., 51
16
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
#
18
# Copyright 2018-2021 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
import json
22
import pycountry
23
from operator import itemgetter
24
from senaite.core.p3compat import cmp
25
26
from bika.lims.browser import BrowserView
27
28
29
_marker = object()
30
31
32
def get_countries():
33
    return pycountry.countries
34
35
36
def get_states(country, search_by='name', fallback_historic=True, default=_marker):
37
    kw = {search_by: country}
38
    country = pycountry.countries.get(**kw)
39
    if not country and fallback_historic:
40
        # Try with historical countries
41
        country = pycountry.historic_countries.get(**kw)
42
43
    if not country:
44
        if default is _marker:
45
            raise ValueError("Country not found: '{}'".format(country))
46
        return default
47
48
    # Extract the first-level subdivisions of the country
49
    states = pycountry.subdivisions.get(country_code=country.alpha_2)
50
    states = filter(lambda sub: sub.parent_code is None, states)
51
52
    # Sort by name
53
    return sorted(list(states), key=lambda s: s.name)
54
55
56
def get_districts(country_name, state_name):
57
    states = get_states(country_name, default=[])
58
    state = filter(lambda st: st.name == state_name, states)
59
    if not state:
60
        return []
61
62
    # Extracts the districts for this state
63
    state = state[0]
64
    districts = pycountry.subdivisions.get(country_code=state.country_code)
65
    districts = filter(lambda dis: dis.parent_code == state.code, districts)
66
67
    # Sort by name
68
    return sorted(list(districts), key=lambda s: s.name)
69
70
71
class ajaxGetCountries(BrowserView):
72
73
    def __call__(self):
74
        searchTerm = self.request['searchTerm'].lower()
75
        page = self.request['page']
76
        nr_rows = self.request['rows']
77
        sord = self.request['sord']
78
        sidx = self.request['sidx']
79
        rows = []
80
81
        # lookup objects from ISO code list
82
        for country in get_countries():
83
            iso = country.alpha_2
84
            name = country.name
85
            country_info = {"Code": iso, "Country": name}
86
            if iso.lower().find(searchTerm) > -1:
87
                rows.append(country_info)
88
            elif name.lower().find(searchTerm) > -1:
89
                rows.append(country_info)
90
91
        rows = sorted(rows, cmp=lambda x,y: cmp(x.lower(), y.lower()), key=itemgetter(sidx and sidx or 'Country'))
92
        if sord == 'desc':
93
            rows.reverse()
94
        pages = len(rows) / int(nr_rows)
95
        pages += divmod(len(rows), int(nr_rows))[1] and 1 or 0
96
        ret = {'page':page,
97
               'total':pages,
98
               'records':len(rows),
99
               'rows':rows[ (int(page) - 1) * int(nr_rows) : int(page) * int(nr_rows) ]}
100
101
        return json.dumps(ret)
102
103
104
class ajaxGetStates(BrowserView):
105
106
    def __call__(self):
107
        items = []
108
        country = self.request.get('country', '')
109
        if not country:
110
            return json.dumps(items)
111
        
112
        # Get the states
113
        items = get_states(country, default=[])
114
        items = map(lambda sub: [sub.country_code, sub.code, sub.name], items)
115
        return json.dumps(items)
116
117
118
class ajaxGetDistricts(BrowserView):
119
120
    def __call__(self):
121
        country = self.request.get('country', '')
122
        state = self.request.get('state', '')
123
        items = []
124
        if not all([country, state]):
125
            return json.dumps(items)
126
        
127
        items = get_districts(country, state)
128
        items = map(lambda sub: [sub.country_code, sub.code, sub.name],  items)
129
        return json.dumps(items)
130