planitech: getreservationprice endpoint (#30261)

This commit is contained in:
Emmanuel Cazenave 2019-02-01 15:25:35 +01:00
parent 678e09d29c
commit 62e683f378
2 changed files with 204 additions and 14 deletions

View File

@ -110,6 +110,66 @@ CREATE_RESERVATION_SCHEMA = {
}
GET_RESERVATION_PRICE_SCHEMA = {
"$schema": "http://json-schema.org/draft-03/schema#",
"title": "Planitech getreservationprice",
"description": "",
"type": "object",
"properties": {
"date": {
"description": "Date",
"type": "string",
"required": True
},
"start_time": {
"description": "Start time",
"type": "string",
"required": True
},
"end_time": {
"description": "End time",
"type": "string",
"required": True
},
"place_id": {
"description": "Place identifier",
"type": "number",
"required": True
},
"name_id": {
"description": "Publik user nameID",
"type": "string",
"required": True
},
"first_name": {
"description": "First name",
"type": "string",
"required": True
},
"last_name": {
"description": "Last name",
"type": "string",
"required": True
},
"email": {
"description": "Email",
"type": "string",
"required": True
},
"activity_id": {
"description": "Activity identifier",
"type": "number",
"required": True
},
"type_id": {
"description": "Rerservation type identifier",
"type": "number",
"required": True
}
}
}
RESERVATION_STATUS = {
"confirmed": 3, "invalid": 0, " pre-reservation": 1, "standard": 2
}
@ -322,6 +382,62 @@ class PlanitechConnector(BaseResource):
except RequestException as e:
raise APIError("Authentication to Planitech failed: %s" % str(e))
def get_or_create_pairing(self, post_data):
with transaction.atomic():
pairing, created = Pairing.objects.get_or_create(
resource=self, name_id=post_data['name_id'],
defaults={'external_id': uuid.uuid4().get_hex()})
if created:
params = {
"externalUserIdentifier": pairing.external_id,
"name": post_data['last_name'],
"firstName": post_data['first_name'],
"mail": post_data['email']
}
data = self._call_planitech(self.requests.post, 'createPerson', params)
if data.get('creationStatus') != 'OK':
raise APIError("Person creation failed: %s" % data.get('creationStatus'))
return pairing
@endpoint(
perm='can_access',
post={
'description': _('Get reservation price'),
'request_body': {
'schema': {
'application/json': GET_RESERVATION_PRICE_SCHEMA
}
}
}
)
def getreservationprice(self, request, post_data):
start_datetime = combine_date_time(post_data['date'], post_data['start_time'])
end_datetime = combine_date_time(post_data['date'], post_data['end_time'])
pairing = self.get_or_create_pairing(post_data)
params = {
"activityID": mste.Uint32(post_data['activity_id']),
"contractorExternalIdentifier": pairing.external_id,
"end": end_datetime,
"isWeekly": False,
"places": [float(post_data['place_id'])],
"start": start_datetime,
"typeID": mste.Uint32(post_data['type_id']),
}
data = self._call_planitech(self.requests.post, 'getFutureReservationPrice', params)
if data.get('calculationStatus') != 'OK':
raise APIError("Get reservation price failed: %s" % data.get('calculationStatus'))
price = data.get('calculatedPrice', False)
if price is False:
raise APIError("Get reservation price failed: no price")
return {
'data': {
'price': int(price),
'raw_data': data
}
}
@endpoint(
perm='can_access',
post={
@ -338,20 +454,7 @@ class PlanitechConnector(BaseResource):
end_datetime = combine_date_time(post_data['date'], post_data['end_time'])
request_date = datetime.now()
with transaction.atomic():
pairing, created = Pairing.objects.get_or_create(
resource=self, name_id=post_data['name_id'],
defaults={'external_id': uuid.uuid4().get_hex()})
if created:
params = {
"externalUserIdentifier": pairing.external_id,
"name": post_data['last_name'],
"firstName": post_data['first_name'],
"mail": post_data['email']
}
data = self._call_planitech(self.requests.post, 'createPerson', params)
if data.get('creationStatus') != 'OK':
raise APIError("Person creation failed: %s" % data.get('creationStatus'))
pairing = self.get_or_create_pairing(post_data)
params = {
"activityID": mste.Uint32(post_data['activity_id']),

View File

@ -233,6 +233,93 @@ def test_create_reservation(app, connector, monkeypatch):
assert json_resp['err_desc'] == 'Reservation creation failed: no reservation ID'
def test_get_reservation_price(app, connector, monkeypatch):
side_effect = [
{
'creationStatus': 'OK',
'externalUserIdentifier': '22b9c0d91fdc4f379d1356a4aaa9d38b',
'requestDate': datetime(2019, 1, 9, 15, 41),
'requestName': 'createPerson',
'responseDate': datetime(2019, 1, 9, 15, 41),
'userIdentifier': 13826.0
},
{
'calculationStatus': 'OK',
'calculatedPrice': 10
}
]
mock_call_planitech = mock_planitech(monkeypatch, side_effect=side_effect)
params = {
'date': '2018-11-11',
'start_time': '10:00',
'end_time': '11:00',
'place_id': 1,
'name_id': 'john-doe',
'first_name': 'jon',
'last_name': 'doe',
'email': 'jon.doe@localhost',
'activity_id': 1,
'type_id': 1,
}
response = app.post_json('/planitech/slug-planitech/getreservationprice', params=params)
json_resp = response.json
assert json_resp['err'] == 0
assert json_resp['data']['price'] == 10
person_args = mock_call_planitech.call_args_list[0][0]
assert person_args[1] == 'createPerson'
person_args = person_args[2]
assert person_args['mail'] == 'jon.doe@localhost'
assert person_args['firstName'] == 'jon'
assert person_args['name'] == 'doe'
external_id = person_args['externalUserIdentifier']
pairing = Pairing.objects.get(resource=connector, name_id='john-doe')
assert pairing.external_id == external_id
reservation_args = mock_call_planitech.call_args_list[1][0]
assert reservation_args[1] == 'getFutureReservationPrice'
reservation_args = reservation_args[2]
assert reservation_args['start'] == datetime(2018, 11, 11, 10, 0)
assert reservation_args['end'] == datetime(2018, 11, 11, 11, 0)
assert reservation_args['places'] == [1]
assert reservation_args['contractorExternalIdentifier'] == pairing.external_id
assert reservation_args['activityID'] == 1
assert reservation_args['typeID'] == 1
# Second call for same user : no planitech person created
mock_call_planitech = mock_planitech(monkeypatch, return_value=side_effect[1])
response = app.post_json('/planitech/slug-planitech/getreservationprice', params=params)
json_resp = response.json
assert json_resp['err'] == 0
assert json_resp['data']['price'] == 10
reservation_args = mock_call_planitech.call_args_list[0][0]
assert reservation_args[1] == 'getFutureReservationPrice'
assert Pairing.objects.count() == 1
# Failure
mock_call_planitech = mock_planitech(
monkeypatch, return_value={
'calculationStatus': 'NOTOK',
'calculatedPrice': 10
})
response = app.post_json('/planitech/slug-planitech/getreservationprice', params=params)
json_resp = response.json
assert json_resp['err'] == 1
assert json_resp['err_desc'] == 'Get reservation price failed: NOTOK'
# Create reservation failed - nor reservation ID
mock_call_planitech = mock_planitech(
monkeypatch, return_value={
'calculationStatus': 'OK'
})
response = app.post_json('/planitech/slug-planitech/getreservationprice', params=params)
json_resp = response.json
assert json_resp['err'] == 1
assert json_resp['err_desc'] == 'Get reservation price failed: no price'
def test_getplaces_referential(app, connector, monkeypatch):
side_effect = [
{