Projet

Général

Profil

0001-planitech-getreservationprice-endpoint-30261.patch

Emmanuel Cazenave, 03 avril 2019 17:32

Télécharger (9,79 ko)

Voir les différences:

Subject: [PATCH 1/2] planitech: getreservationprice endpoint (#30261)

 passerelle/contrib/planitech/models.py | 131 ++++++++++++++++++++++---
 tests/test_planitech.py                |  87 ++++++++++++++++
 2 files changed, 204 insertions(+), 14 deletions(-)
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
-