0002-toulouse_smart-add-get-intervention-endpoint-55230.patch
passerelle/contrib/toulouse_smart/models.py | ||
---|---|---|
17 | 17 |
import datetime |
18 | 18 | |
19 | 19 |
import lxml.etree as ET |
20 | 20 |
from django.contrib.postgres.fields import JSONField |
21 | 21 |
from django.db import models |
22 | 22 |
from django.utils.text import slugify |
23 | 23 |
from django.utils.timezone import now |
24 | 24 |
from django.utils.translation import ugettext_lazy as _ |
25 |
from requests import RequestException |
|
25 | 26 | |
26 | 27 |
from passerelle.base.models import BaseResource, HTTPResource |
27 | 28 |
from passerelle.utils import xml |
28 | 29 |
from passerelle.utils.api import endpoint |
30 |
from passerelle.utils.jsonresponse import APIError |
|
29 | 31 | |
30 | 32 | |
31 | 33 |
class ToulouseSmartResource(BaseResource, HTTPResource): |
32 | 34 |
category = _('Business Process Connectors') |
33 | 35 | |
34 | 36 |
webservice_base_url = models.URLField(_('Webservice Base URL')) |
35 | 37 | |
36 | 38 |
log_requests_errors = False |
... | ... | |
102 | 104 |
{ |
103 | 105 |
'id': '', |
104 | 106 |
'text': _('Service is unavailable'), |
105 | 107 |
'disabled': True, |
106 | 108 |
} |
107 | 109 |
] |
108 | 110 |
} |
109 | 111 | |
112 |
def request(self, url, json=None): |
|
113 |
headers = {'Accept': 'application/json'} |
|
114 |
if json: |
|
115 |
headers['Content-Type'] = 'application/json' |
|
116 |
response = self.requests.post(url, headers=headers, json=json) |
|
117 |
else: |
|
118 |
response = self.requests.get(url, headers=headers) |
|
119 |
try: |
|
120 |
response.raise_for_status() |
|
121 |
except RequestException as e: |
|
122 |
raise APIError('failed to %s %s: %s' % ('post' if json else 'get', url, e)) |
|
123 |
return response |
|
124 | ||
125 |
@endpoint( |
|
126 |
name='get-intervention', |
|
127 |
methods=['get'], |
|
128 |
description=_('Retrieve an intervention'), |
|
129 |
perm='can_access', |
|
130 |
parameters={ |
|
131 |
'id': {'description': _('Intervention identifier')}, |
|
132 |
}, |
|
133 |
) |
|
134 |
def get_intervention(self, request, id): |
|
135 |
url = self.webservice_base_url + 'v1/intervention/%s' % id |
|
136 |
response = self.request(url) |
|
137 |
return {'data': response.json()} |
|
138 | ||
110 | 139 | |
111 | 140 |
class Cache(models.Model): |
112 | 141 |
resource = models.ForeignKey( |
113 | 142 |
verbose_name=_('Resource'), |
114 | 143 |
to=ToulouseSmartResource, |
115 | 144 |
on_delete=models.CASCADE, |
116 | 145 |
related_name='cache_entries', |
117 | 146 |
) |
tests/data/toulouse_smart/get_intervention.json | ||
---|---|---|
1 |
{ |
|
2 |
"id": "3f0558bd-7d85-49a8-97e4-d07bc7f8dc9b", |
|
3 |
"name": "DI-20210731-0103", |
|
4 |
"description": "Justice nul part", |
|
5 |
"geom": { |
|
6 |
"type": "Point", |
|
7 |
"coordinates": [ |
|
8 |
2.1431744096480547, |
|
9 |
48.69856386916798 |
|
10 |
], |
|
11 |
"crs": "EPSG:3943" |
|
12 |
}, |
|
13 |
"interventionData": {}, |
|
14 |
"safeguardRequired": false, |
|
15 |
"media": null, |
|
16 |
"safeguardDone": null, |
|
17 |
"interventionCreated": "2021-07-30T22:44:38.748Z", |
|
18 |
"interventionDesired": "2021-07-31T00:40:03Z", |
|
19 |
"interventionDone": null, |
|
20 |
"submitter": { |
|
21 |
"id": null, |
|
22 |
"lastName": "", |
|
23 |
"firstName": "admin", |
|
24 |
"mail": "admin@localhost", |
|
25 |
"furtherInformation": null, |
|
26 |
"phoneNumber": "0699999999", |
|
27 |
"address": "" |
|
28 |
}, |
|
29 |
"submitterType": "usager", |
|
30 |
"organizations": [ |
|
31 |
{ |
|
32 |
"id": "f1378d8a-12bf-4c14-913f-22624b0ecab8", |
|
33 |
"name": "Direction des P\u00f4les" |
|
34 |
}, |
|
35 |
{ |
|
36 |
"id": "8ad4af63-70b5-416f-a75d-c510d83ce1bd", |
|
37 |
"name": "Transport Logistique" |
|
38 |
} |
|
39 |
], |
|
40 |
"domain": null, |
|
41 |
"state": { |
|
42 |
"id": "e844e67f-5382-4c0f-94d8-56f618263485", |
|
43 |
"table": null, |
|
44 |
"stateLabel": "Nouveau", |
|
45 |
"closes": false |
|
46 |
}, |
|
47 |
"interventionTypeId": "407ef8d6-9b8c-4187-be51-d89f24424768", |
|
48 |
"onPrivateLand": false, |
|
49 |
"duplicates": null, |
|
50 |
"external_number": "36-10", |
|
51 |
"external_status": "statut 1", |
|
52 |
"cityId": "12345", |
|
53 |
"address": "https://wcs.dev.publik.love/backoffice/management/smart/10/" |
|
54 |
} |
tests/test_toulouse_smart.py | ||
---|---|---|
11 | 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | 12 |
# GNU Affero General Public License for more details. |
13 | 13 |
# |
14 | 14 |
# You should have received a copy of the GNU Affero General Public License |
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 | 17 |
import functools |
18 | 18 |
import io |
19 |
import os |
|
19 | 20 |
import zipfile |
20 | 21 | |
21 | 22 |
import httmock |
22 | 23 |
import lxml.etree as ET |
23 | 24 |
import pytest |
24 | 25 |
import utils |
25 | 26 |
from test_manager import login |
26 | 27 | |
27 | 28 |
from passerelle.contrib.toulouse_smart.models import ToulouseSmartResource |
28 |
from passerelle.utils.xml import to_json |
|
29 | ||
30 |
TEST_BASE_DIR = os.path.join(os.path.dirname(__file__), 'data', 'toulouse_smart') |
|
29 | 31 | |
30 | 32 | |
31 | 33 |
@pytest.fixture |
32 | 34 |
def smart(db): |
33 | 35 |
return utils.make_resource( |
34 | 36 |
ToulouseSmartResource, |
35 | 37 |
title='Test', |
36 | 38 |
slug='test', |
... | ... | |
67 | 69 |
with httmock.HTTMock(*handlers): |
68 | 70 |
return func(*args, **kwargs) |
69 | 71 | |
70 | 72 |
return wrapper |
71 | 73 | |
72 | 74 |
return decorator |
73 | 75 | |
74 | 76 | |
77 |
def get_json_file(filename): |
|
78 |
with open(os.path.join(TEST_BASE_DIR, "%s.json" % filename)) as desc: |
|
79 |
return desc.read() |
|
80 | ||
81 | ||
75 | 82 |
@mock_response(['/v1/type-intervention', b'<List></List>']) |
76 | 83 |
def test_empty_intervention_types(smart): |
77 | 84 |
assert smart.get_intervention_types() == [] |
78 | 85 | |
79 | 86 | |
80 | 87 |
INTERVENTION_TYPES = '''<List> |
81 | 88 |
<item> |
82 | 89 |
<id>1234</id> |
... | ... | |
192 | 199 |
<validation> |
193 | 200 |
<type>digits</type> |
194 | 201 |
</validation> |
195 | 202 |
</field> |
196 | 203 |
</fields> |
197 | 204 |
</block> |
198 | 205 |
''' |
199 | 206 |
) |
207 | ||
208 | ||
209 |
@mock_response( |
|
210 |
['/v1/intervention', get_json_file('get_intervention')], |
|
211 |
) |
|
212 |
def test_get_intervention(app, smart): |
|
213 |
resp = app.get(URL + 'get-intervention?id=3f0558bd-7d85-49a8-97e4-d07bc7f8dc9b') |
|
214 |
assert not resp.json['err'] |
|
215 |
assert resp.json['data']['id'] == '3f0558bd-7d85-49a8-97e4-d07bc7f8dc9b' |
|
216 |
assert resp.json['data']['state'] == { |
|
217 |
'id': 'e844e67f-5382-4c0f-94d8-56f618263485', |
|
218 |
'table': None, |
|
219 |
'stateLabel': 'Nouveau', |
|
220 |
'closes': False, |
|
221 |
} |
|
222 | ||
223 | ||
224 |
@mock_response( |
|
225 |
['/v1/intervention', None, 500], |
|
226 |
) |
|
227 |
def test_get_intervention_error_status(app, smart): |
|
228 |
resp = app.get(URL + 'get-intervention?id=3f0558bd-7d85-49a8-97e4-d07bc7f8dc9b') |
|
229 |
assert resp.json['err'] |
|
230 |
assert 'failed to get' in resp.json['err_desc'] |
|
231 | ||
232 | ||
233 |
@mock_response( |
|
234 |
['/v1/intervention', None, 404], |
|
235 |
) |
|
236 |
def test_get_intervention_wrond_id(app, smart): |
|
237 |
resp = app.get(URL + 'get-intervention?id=3f0558bd-7d85-49a8-97e4-d07bc7f8dc9b') |
|
238 |
assert resp.json['err'] |
|
239 |
assert 'failed to get' in resp.json['err_desc'] |
|
240 |
assert '404' in resp.json['err_desc'] |
|
200 |
- |