Use custom pager instead of Suq-Pagination. Don't request the first GeoJSON items...
[infos-pratiques:etalage.git] / poiscasse / conv.py
1 # -*- coding: utf-8 -*-
2
3
4 # PoisCasse -- Open Data POIs portal
5 # By: Emmanuel Raviart <eraviart@easter-eggs.com>
6 #     Romain Soufflet <rsoufflet@easter-eggs.com>
7 #
8 # Copyright (C) 2011 Easter-eggs
9 # http://gitorious.org/infos-pratiques/poiscasse
10 #
11 # This file is part of PoisCasse.
12 #
13 # PoisCasse is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU Affero General Public License as
15 # published by the Free Software Foundation, either version 3 of the
16 # License, or (at your option) any later version.
17 #
18 # PoisCasse is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 # GNU Affero General Public License for more details.
22 #
23 # You should have received a copy of the GNU Affero General Public License
24 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
25
26
27 """Conversion functions"""
28
29
30 import datetime
31
32 from biryani.baseconv import *
33 from biryani.bsonconv import *
34 from biryani.objectconv import *
35 from biryani.frconv import *
36 from biryani import states, strings
37 from territoria2.conv import str_to_postal_distribution
38
39
40 default_state = states.default_state
41 N_ = lambda message: message
42
43
44 def bson_to_poi(bson, state = default_state):
45     from . import pois
46     return make_dict_to_object(pois.Poi)(bson, state = state)
47
48
49 def params_to_pois_pager(params, state = default_state):
50     from . import pagers, ramdb
51     data, errors = pipe(
52         struct(
53             dict(
54                 category = pipe(
55                     str_to_category_slug,
56                     function(lambda slug: ramdb.categories_by_slug[slug]),
57                     make_test(lambda category: (category.tags_slug or set()).issuperset(state.category_tags_slug or []),
58                         error = N_(u'Missing required tags to category')),
59                     ),
60                 page = pipe(
61                     str_to_int,
62                     make_greater_or_equal(1),
63                     default(1),
64                     ),
65                 term = str_to_slug,
66                 territory = pipe(
67                     str_to_postal_distribution,
68                     postal_distribution_to_territory,
69                     ),
70                 ),
71             default = 'ignore',
72             keep_empty = True,
73             ),
74         rename_item('page', 'page_number'),
75         )(params, state = state)
76     if errors is not None:
77         return data, errors
78
79     categories_slug = set(state.base_categories_slug or [])
80     if data.get('category') is not None:
81         categories_slug.add(data['category'].slug)
82     if data.get('territory') is None:
83         territory_kind_code = None
84     else:
85         territory_kind_code = territory.new_kind_code()
86         territory_kind_code = (territory_kind_code['kind'], territory_kind_code['code'])
87     pois_id = list(ramdb.iter_pois_id(categories_slug = categories_slug, term = data.get('term'),
88         territory_kind_code = territory_kind_code))
89     pager = pagers.Pager(item_count = len(pois_id), page_number = data['page_number'])
90     pager.items = [
91         ramdb.ram_pois_by_id[poi_id]
92         for poi_id in pois_id[pager.first_item_index:pager.last_item_number]
93         ]
94     return pager, None
95
96
97 def pois_to_geojson(pois, state = default_state):
98     if pois is None:
99         return pois, None
100     geojson = {
101         'type': 'FeatureCollection',
102         'properties': {'date': unicode(datetime.datetime.utcnow())},
103         'features': [
104             {
105                 'geometry': {
106                     'type': 'Point',
107                     'coordinates': [poi.geo[1], poi.geo[0]],
108                     },
109                 'type': 'Feature',
110                 'properties': {
111                     'id': str(poi._id),
112                     'name': poi.name,
113                     },
114                 }
115             for poi in pois
116             if poi.geo is not None
117             ],
118         }
119     return geojson, None
120
121
122 def postal_distribution_to_territory(postal_distribution, state = default_state):
123     from . import model
124     if postal_distribution is None:
125         return postal_distribution, None
126     found_territories = list(model.Territory.find({
127         'main_postal_distribution.postal_code': postal_distribution[0],
128         'main_postal_distribution.postal_routing': postal_distribution[1],
129         }).limit(2))
130     if not found_territories:
131         return postal_distribution, state._(u'Unknown territory')
132     if len(found_territories) > 1:
133         return postal_distribution, state._(u'Ambiguous territory')
134     return found_territories[0], None
135
136
137 def str_to_category_slug(value, state = default_state):
138     from . import ramdb
139     return pipe(
140         str_to_slug,
141         make_test(lambda slug: slug in ramdb.categories_by_slug, error = N_(u'Invalid category')),
142         )(value, state = state)
143