0001-planitech-getreservationprice-endpoint-30261.patch
passerelle/contrib/planitech/models.py | ||
---|---|---|
110 | 110 |
} |
111 | 111 | |
112 | 112 | |
113 |
GET_RESERVATION_PRICE_SCHEMA = { |
|
114 |
"$schema": "http://json-schema.org/draft-03/schema#", |
|
115 |
"title": "Planitech getreservationprice", |
|
116 |
"description": "", |
|
117 |
"type": "object", |
|
118 |
"properties": { |
|
119 |
"date": { |
|
120 |
"description": "Date", |
|
121 |
"type": "string", |
|
122 |
"required": True |
|
123 |
}, |
|
124 |
"start_time": { |
|
125 |
"description": "Start time", |
|
126 |
"type": "string", |
|
127 |
"required": True |
|
128 |
}, |
|
129 |
"end_time": { |
|
130 |
"description": "End time", |
|
131 |
"type": "string", |
|
132 |
"required": True |
|
133 |
}, |
|
134 |
"place_id": { |
|
135 |
"description": "Place identifier", |
|
136 |
"type": "number", |
|
137 |
"required": True |
|
138 |
}, |
|
139 |
"name_id": { |
|
140 |
"description": "Publik user nameID", |
|
141 |
"type": "string", |
|
142 |
"required": True |
|
143 |
}, |
|
144 |
"first_name": { |
|
145 |
"description": "First name", |
|
146 |
"type": "string", |
|
147 |
"required": True |
|
148 |
}, |
|
149 |
"last_name": { |
|
150 |
"description": "Last name", |
|
151 |
"type": "string", |
|
152 |
"required": True |
|
153 |
}, |
|
154 |
"email": { |
|
155 |
"description": "Email", |
|
156 |
"type": "string", |
|
157 |
"required": True |
|
158 |
}, |
|
159 |
"activity_id": { |
|
160 |
"description": "Activity identifier", |
|
161 |
"type": "number", |
|
162 |
"required": True |
|
163 |
}, |
|
164 |
"type_id": { |
|
165 |
"description": "Rerservation type identifier", |
|
166 |
"type": "number", |
|
167 |
"required": True |
|
168 |
} |
|
169 |
} |
|
170 |
} |
|
171 | ||
172 | ||
113 | 173 |
RESERVATION_STATUS = { |
114 | 174 |
"confirmed": 3, "invalid": 0, " pre-reservation": 1, "standard": 2 |
115 | 175 |
} |
... | ... | |
322 | 382 |
except RequestException as e: |
323 | 383 |
raise APIError("Authentication to Planitech failed: %s" % str(e)) |
324 | 384 | |
385 |
def get_or_create_pairing(self, post_data): |
|
386 |
with transaction.atomic(): |
|
387 |
pairing, created = Pairing.objects.get_or_create( |
|
388 |
resource=self, name_id=post_data['name_id'], |
|
389 |
defaults={'external_id': uuid.uuid4().get_hex()}) |
|
390 |
if created: |
|
391 |
params = { |
|
392 |
"externalUserIdentifier": pairing.external_id, |
|
393 |
"name": post_data['last_name'], |
|
394 |
"firstName": post_data['first_name'], |
|
395 |
"mail": post_data['email'] |
|
396 |
} |
|
397 |
data = self._call_planitech(self.requests.post, 'createPerson', params) |
|
398 |
if data.get('creationStatus') != 'OK': |
|
399 |
raise APIError("Person creation failed: %s" % data.get('creationStatus')) |
|
400 |
return pairing |
|
401 | ||
402 |
@endpoint( |
|
403 |
perm='can_access', |
|
404 |
post={ |
|
405 |
'description': _('Get reservation price'), |
|
406 |
'request_body': { |
|
407 |
'schema': { |
|
408 |
'application/json': GET_RESERVATION_PRICE_SCHEMA |
|
409 |
} |
|
410 |
} |
|
411 |
} |
|
412 |
) |
|
413 |
def getreservationprice(self, request, post_data): |
|
414 |
start_datetime = combine_date_time(post_data['date'], post_data['start_time']) |
|
415 |
end_datetime = combine_date_time(post_data['date'], post_data['end_time']) |
|
416 | ||
417 |
pairing = self.get_or_create_pairing(post_data) |
|
418 | ||
419 |
params = { |
|
420 |
"activityID": mste.Uint32(post_data['activity_id']), |
|
421 |
"contractorExternalIdentifier": pairing.external_id, |
|
422 |
"end": end_datetime, |
|
423 |
"isWeekly": False, |
|
424 |
"places": [float(post_data['place_id'])], |
|
425 |
"start": start_datetime, |
|
426 |
"typeID": mste.Uint32(post_data['type_id']), |
|
427 |
} |
|
428 |
data = self._call_planitech(self.requests.post, 'getFutureReservationPrice', params) |
|
429 |
if data.get('calculationStatus') != 'OK': |
|
430 |
raise APIError("Get reservation price failed: %s" % data.get('calculationStatus')) |
|
431 |
price = data.get('calculatedPrice', False) |
|
432 |
if price is False: |
|
433 |
raise APIError("Get reservation price failed: no price") |
|
434 |
return { |
|
435 |
'data': { |
|
436 |
'price': int(price), |
|
437 |
'raw_data': data |
|
438 |
} |
|
439 |
} |
|
440 | ||
325 | 441 |
@endpoint( |
326 | 442 |
perm='can_access', |
327 | 443 |
post={ |
... | ... | |
338 | 454 |
end_datetime = combine_date_time(post_data['date'], post_data['end_time']) |
339 | 455 |
request_date = datetime.now() |
340 | 456 | |
341 |
with transaction.atomic(): |
|
342 |
pairing, created = Pairing.objects.get_or_create( |
|
343 |
resource=self, name_id=post_data['name_id'], |
|
344 |
defaults={'external_id': uuid.uuid4().get_hex()}) |
|
345 |
if created: |
|
346 |
params = { |
|
347 |
"externalUserIdentifier": pairing.external_id, |
|
348 |
"name": post_data['last_name'], |
|
349 |
"firstName": post_data['first_name'], |
|
350 |
"mail": post_data['email'] |
|
351 |
} |
|
352 |
data = self._call_planitech(self.requests.post, 'createPerson', params) |
|
353 |
if data.get('creationStatus') != 'OK': |
|
354 |
raise APIError("Person creation failed: %s" % data.get('creationStatus')) |
|
457 |
pairing = self.get_or_create_pairing(post_data) |
|
355 | 458 | |
356 | 459 |
params = { |
357 | 460 |
"activityID": mste.Uint32(post_data['activity_id']), |
tests/test_planitech.py | ||
---|---|---|
233 | 233 |
assert json_resp['err_desc'] == 'Reservation creation failed: no reservation ID' |
234 | 234 | |
235 | 235 | |
236 |
def test_get_reservation_price(app, connector, monkeypatch): |
|
237 |
side_effect = [ |
|
238 |
{ |
|
239 |
'creationStatus': 'OK', |
|
240 |
'externalUserIdentifier': '22b9c0d91fdc4f379d1356a4aaa9d38b', |
|
241 |
'requestDate': datetime(2019, 1, 9, 15, 41), |
|
242 |
'requestName': 'createPerson', |
|
243 |
'responseDate': datetime(2019, 1, 9, 15, 41), |
|
244 |
'userIdentifier': 13826.0 |
|
245 |
}, |
|
246 |
{ |
|
247 |
'calculationStatus': 'OK', |
|
248 |
'calculatedPrice': 10 |
|
249 |
} |
|
250 |
] |
|
251 |
mock_call_planitech = mock_planitech(monkeypatch, side_effect=side_effect) |
|
252 |
params = { |
|
253 |
'date': '2018-11-11', |
|
254 |
'start_time': '10:00', |
|
255 |
'end_time': '11:00', |
|
256 |
'place_id': 1, |
|
257 |
'name_id': 'john-doe', |
|
258 |
'first_name': 'jon', |
|
259 |
'last_name': 'doe', |
|
260 |
'email': 'jon.doe@localhost', |
|
261 |
'activity_id': 1, |
|
262 |
'type_id': 1, |
|
263 |
} |
|
264 | ||
265 |
response = app.post_json('/planitech/slug-planitech/getreservationprice', params=params) |
|
266 |
json_resp = response.json |
|
267 |
assert json_resp['err'] == 0 |
|
268 |
assert json_resp['data']['price'] == 10 |
|
269 | ||
270 |
person_args = mock_call_planitech.call_args_list[0][0] |
|
271 |
assert person_args[1] == 'createPerson' |
|
272 |
person_args = person_args[2] |
|
273 |
assert person_args['mail'] == 'jon.doe@localhost' |
|
274 |
assert person_args['firstName'] == 'jon' |
|
275 |
assert person_args['name'] == 'doe' |
|
276 |
external_id = person_args['externalUserIdentifier'] |
|
277 |
pairing = Pairing.objects.get(resource=connector, name_id='john-doe') |
|
278 |
assert pairing.external_id == external_id |
|
279 | ||
280 |
reservation_args = mock_call_planitech.call_args_list[1][0] |
|
281 |
assert reservation_args[1] == 'getFutureReservationPrice' |
|
282 |
reservation_args = reservation_args[2] |
|
283 |
assert reservation_args['start'] == datetime(2018, 11, 11, 10, 0) |
|
284 |
assert reservation_args['end'] == datetime(2018, 11, 11, 11, 0) |
|
285 |
assert reservation_args['places'] == [1] |
|
286 |
assert reservation_args['contractorExternalIdentifier'] == pairing.external_id |
|
287 |
assert reservation_args['activityID'] == 1 |
|
288 |
assert reservation_args['typeID'] == 1 |
|
289 | ||
290 |
# Second call for same user : no planitech person created |
|
291 |
mock_call_planitech = mock_planitech(monkeypatch, return_value=side_effect[1]) |
|
292 |
response = app.post_json('/planitech/slug-planitech/getreservationprice', params=params) |
|
293 |
json_resp = response.json |
|
294 |
assert json_resp['err'] == 0 |
|
295 |
assert json_resp['data']['price'] == 10 |
|
296 | ||
297 |
reservation_args = mock_call_planitech.call_args_list[0][0] |
|
298 |
assert reservation_args[1] == 'getFutureReservationPrice' |
|
299 |
assert Pairing.objects.count() == 1 |
|
300 | ||
301 |
# Failure |
|
302 |
mock_call_planitech = mock_planitech( |
|
303 |
monkeypatch, return_value={ |
|
304 |
'calculationStatus': 'NOTOK', |
|
305 |
'calculatedPrice': 10 |
|
306 |
}) |
|
307 |
response = app.post_json('/planitech/slug-planitech/getreservationprice', params=params) |
|
308 |
json_resp = response.json |
|
309 |
assert json_resp['err'] == 1 |
|
310 |
assert json_resp['err_desc'] == 'Get reservation price failed: NOTOK' |
|
311 | ||
312 |
# Create reservation failed - nor reservation ID |
|
313 |
mock_call_planitech = mock_planitech( |
|
314 |
monkeypatch, return_value={ |
|
315 |
'calculationStatus': 'OK' |
|
316 |
}) |
|
317 |
response = app.post_json('/planitech/slug-planitech/getreservationprice', params=params) |
|
318 |
json_resp = response.json |
|
319 |
assert json_resp['err'] == 1 |
|
320 |
assert json_resp['err_desc'] == 'Get reservation price failed: no price' |
|
321 | ||
322 | ||
236 | 323 |
def test_getplaces_referential(app, connector, monkeypatch): |
237 | 324 |
side_effect = [ |
238 | 325 |
{ |
239 |
- |